1 /*
2  * schemas.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  */
9 
10 /*
11  * TODO:
12  *   - when types are redefined in includes, check that all
13  *     types in the redef list are equal
14  *     -> need a type equality operation.
15  *   - if we don't intend to use the schema for schemas, we
16  *     need to validate all schema attributes (ref, type, name)
17  *     against their types.
18  *   - Eliminate item creation for: ??
19  *
20  * URGENT TODO:
21  *   - For xsi-driven schema acquisition, augment the IDCs after every
22  *     acquisition episode (xmlSchemaAugmentIDC).
23  *
24  * NOTES:
25  *   - Elimated item creation for: <restriction>, <extension>,
26  *     <simpleContent>, <complexContent>, <list>, <union>
27  *
28  * PROBLEMS:
29  *   - http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0337.html
30  *     IDC XPath expression and chameleon includes: the targetNamespace is changed, so
31  *     XPath will have trouble to resolve to this namespace, since not known.
32  *
33  *
34  * CONSTRAINTS:
35  *
36  * Schema Component Constraint:
37  *   All Group Limited (cos-all-limited)
38  *   Status: complete
39  *   (1.2)
40  *     In xmlSchemaGroupDefReferenceTermFixup() and
41  *   (2)
42  *     In xmlSchemaParseModelGroup()
43  *     TODO: Actually this should go to component-level checks,
44  *     but is done here due to performance. Move it to an other layer
45  *     is schema construction via an API is implemented.
46  */
47 #define IN_LIBXML
48 #include "libxml.h"
49 
50 #ifdef LIBXML_SCHEMAS_ENABLED
51 
52 #include <string.h>
53 #include <libxml/xmlmemory.h>
54 #include <libxml/parser.h>
55 #include <libxml/parserInternals.h>
56 #include <libxml/hash.h>
57 #include <libxml/uri.h>
58 #include <libxml/xmlschemas.h>
59 #include <libxml/schemasInternals.h>
60 #include <libxml/xmlschemastypes.h>
61 #include <libxml/xmlautomata.h>
62 #include <libxml/xmlregexp.h>
63 #include <libxml/dict.h>
64 #include <libxml/encoding.h>
65 #include <libxml/xmlIO.h>
66 #ifdef LIBXML_PATTERN_ENABLED
67 #include <libxml/pattern.h>
68 #endif
69 #ifdef LIBXML_READER_ENABLED
70 #include <libxml/xmlreader.h>
71 #endif
72 
73 /* #define DEBUG 1 */
74 
75 /* #define DEBUG_CONTENT 1 */
76 
77 /* #define DEBUG_TYPE 1 */
78 
79 /* #define DEBUG_CONTENT_REGEXP 1 */
80 
81 /* #define DEBUG_AUTOMATA 1 */
82 
83 /* #define DEBUG_IDC */
84 
85 /* #define DEBUG_IDC_NODE_TABLE */
86 
87 /* #define WXS_ELEM_DECL_CONS_ENABLED */
88 
89 #ifdef DEBUG_IDC
90  #ifndef DEBUG_IDC_NODE_TABLE
91   #define DEBUG_IDC_NODE_TABLE
92  #endif
93 #endif
94 
95 /* #define ENABLE_PARTICLE_RESTRICTION 1 */
96 
97 #define ENABLE_REDEFINE
98 
99 /* #define ENABLE_NAMED_LOCALS */
100 
101 /* #define ENABLE_IDC_NODE_TABLES_TEST */
102 
103 #define DUMP_CONTENT_MODEL
104 
105 #ifdef LIBXML_READER_ENABLED
106 /* #define XML_SCHEMA_READER_ENABLED */
107 #endif
108 
109 #define UNBOUNDED (1 << 30)
110 #define TODO 								\
111     xmlGenericError(xmlGenericErrorContext,				\
112 	    "Unimplemented block at %s:%d\n",				\
113             __FILE__, __LINE__);
114 
115 #define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
116 
117 /*
118  * The XML Schemas namespaces
119  */
120 static const xmlChar *xmlSchemaNs = (const xmlChar *)
121     "http://www.w3.org/2001/XMLSchema";
122 
123 static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
124     "http://www.w3.org/2001/XMLSchema-instance";
125 
126 static const xmlChar *xmlNamespaceNs = (const xmlChar *)
127     "http://www.w3.org/2000/xmlns/";
128 
129 /*
130 * Come casting macros.
131 */
132 #define ACTXT_CAST (xmlSchemaAbstractCtxtPtr)
133 #define PCTXT_CAST (xmlSchemaParserCtxtPtr)
134 #define VCTXT_CAST (xmlSchemaValidCtxtPtr)
135 #define WXS_BASIC_CAST (xmlSchemaBasicItemPtr)
136 #define WXS_TREE_CAST (xmlSchemaTreeItemPtr)
137 #define WXS_PTC_CAST (xmlSchemaParticlePtr)
138 #define WXS_TYPE_CAST (xmlSchemaTypePtr)
139 #define WXS_ELEM_CAST (xmlSchemaElementPtr)
140 #define WXS_ATTR_GROUP_CAST (xmlSchemaAttributeGroupPtr)
141 #define WXS_ATTR_CAST (xmlSchemaAttributePtr)
142 #define WXS_ATTR_USE_CAST (xmlSchemaAttributeUsePtr)
143 #define WXS_ATTR_PROHIB_CAST (xmlSchemaAttributeUseProhibPtr)
144 #define WXS_MODEL_GROUPDEF_CAST (xmlSchemaModelGroupDefPtr)
145 #define WXS_MODEL_GROUP_CAST (xmlSchemaModelGroupPtr)
146 #define WXS_IDC_CAST (xmlSchemaIDCPtr)
147 #define WXS_QNAME_CAST (xmlSchemaQNameRefPtr)
148 #define WXS_LIST_CAST (xmlSchemaItemListPtr)
149 
150 /*
151 * Macros to query common properties of components.
152 */
153 #define WXS_ITEM_NODE(i) xmlSchemaGetComponentNode(WXS_BASIC_CAST (i))
154 
155 #define WXS_ITEM_TYPE_NAME(i) xmlSchemaGetComponentTypeStr(WXS_BASIC_CAST (i))
156 /*
157 * Macros for element declarations.
158 */
159 #define WXS_ELEM_TYPEDEF(e) (e)->subtypes
160 
161 #define WXS_SUBST_HEAD(item) (item)->refDecl
162 /*
163 * Macros for attribute declarations.
164 */
165 #define WXS_ATTR_TYPEDEF(a) (a)->subtypes
166 /*
167 * Macros for attribute uses.
168 */
169 #define WXS_ATTRUSE_DECL(au) WXS_ATTR_CAST (WXS_ATTR_USE_CAST (au))->attrDecl
170 
171 #define WXS_ATTRUSE_TYPEDEF(au) WXS_ATTR_TYPEDEF(WXS_ATTRUSE_DECL( WXS_ATTR_USE_CAST au))
172 
173 #define WXS_ATTRUSE_DECL_NAME(au) (WXS_ATTRUSE_DECL(au))->name
174 
175 #define WXS_ATTRUSE_DECL_TNS(au) (WXS_ATTRUSE_DECL(au))->targetNamespace
176 /*
177 * Macros for attribute groups.
178 */
179 #define WXS_ATTR_GROUP_HAS_REFS(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS)
180 #define WXS_ATTR_GROUP_EXPANDED(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED)
181 /*
182 * Macros for particles.
183 */
184 #define WXS_PARTICLE(p) WXS_PTC_CAST (p)
185 
186 #define WXS_PARTICLE_TERM(p) (WXS_PARTICLE(p))->children
187 
188 #define WXS_PARTICLE_TERM_AS_ELEM(p) (WXS_ELEM_CAST WXS_PARTICLE_TERM(p))
189 
190 #define WXS_PARTICLE_MODEL(p) WXS_MODEL_GROUP_CAST WXS_PARTICLE(p)->children
191 /*
192 * Macros for model groups definitions.
193 */
194 #define WXS_MODELGROUPDEF_MODEL(mgd) (WXS_MODEL_GROUP_CAST (mgd))->children
195 /*
196 * Macros for model groups.
197 */
198 #define WXS_IS_MODEL_GROUP(i) \
199     (((i)->type == XML_SCHEMA_TYPE_SEQUENCE) || \
200      ((i)->type == XML_SCHEMA_TYPE_CHOICE) || \
201      ((i)->type == XML_SCHEMA_TYPE_ALL))
202 
203 #define WXS_MODELGROUP_PARTICLE(mg) WXS_PTC_CAST (mg)->children
204 /*
205 * Macros for schema buckets.
206 */
207 #define WXS_IS_BUCKET_INCREDEF(t) (((t) == XML_SCHEMA_SCHEMA_INCLUDE) || \
208     ((t) == XML_SCHEMA_SCHEMA_REDEFINE))
209 
210 #define WXS_IS_BUCKET_IMPMAIN(t) (((t) == XML_SCHEMA_SCHEMA_MAIN) || \
211     ((t) == XML_SCHEMA_SCHEMA_IMPORT))
212 
213 #define WXS_IMPBUCKET(b) ((xmlSchemaImportPtr) (b))
214 
215 #define WXS_INCBUCKET(b) ((xmlSchemaIncludePtr) (b))
216 /*
217 * Macros for complex/simple types.
218 */
219 #define WXS_IS_ANYTYPE(i) \
220      (( (i)->type == XML_SCHEMA_TYPE_BASIC) && \
221       ( (WXS_TYPE_CAST (i))->builtInType == XML_SCHEMAS_ANYTYPE))
222 
223 #define WXS_IS_COMPLEX(i) \
224     (((i)->type == XML_SCHEMA_TYPE_COMPLEX) || \
225      ((i)->builtInType == XML_SCHEMAS_ANYTYPE))
226 
227 #define WXS_IS_SIMPLE(item) \
228     ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
229      ((item->type == XML_SCHEMA_TYPE_BASIC) && \
230       (item->builtInType != XML_SCHEMAS_ANYTYPE)))
231 
232 #define WXS_IS_ANY_SIMPLE_TYPE(i) \
233     (((i)->type == XML_SCHEMA_TYPE_BASIC) && \
234       ((i)->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
235 
236 #define WXS_IS_RESTRICTION(t) \
237     ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)
238 
239 #define WXS_IS_EXTENSION(t) \
240     ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
241 
242 #define WXS_IS_TYPE_NOT_FIXED(i) \
243     (((i)->type != XML_SCHEMA_TYPE_BASIC) && \
244      (((i)->flags & XML_SCHEMAS_TYPE_INTERNAL_RESOLVED) == 0))
245 
246 #define WXS_IS_TYPE_NOT_FIXED_1(item) \
247     (((item)->type != XML_SCHEMA_TYPE_BASIC) && \
248      (((item)->flags & XML_SCHEMAS_TYPE_FIXUP_1) == 0))
249 
250 #define WXS_TYPE_IS_GLOBAL(t) ((t)->flags & XML_SCHEMAS_TYPE_GLOBAL)
251 
252 #define WXS_TYPE_IS_LOCAL(t) (((t)->flags & XML_SCHEMAS_TYPE_GLOBAL) == 0)
253 /*
254 * Macros for exclusively for complex types.
255 */
256 #define WXS_HAS_COMPLEX_CONTENT(item) \
257     ((item->contentType == XML_SCHEMA_CONTENT_MIXED) || \
258      (item->contentType == XML_SCHEMA_CONTENT_EMPTY) || \
259      (item->contentType == XML_SCHEMA_CONTENT_ELEMENTS))
260 
261 #define WXS_HAS_SIMPLE_CONTENT(item) \
262     ((item->contentType == XML_SCHEMA_CONTENT_SIMPLE) || \
263      (item->contentType == XML_SCHEMA_CONTENT_BASIC))
264 
265 #define WXS_HAS_MIXED_CONTENT(item) \
266     (item->contentType == XML_SCHEMA_CONTENT_MIXED)
267 
268 #define WXS_EMPTIABLE(t) \
269     (xmlSchemaIsParticleEmptiable(WXS_PTC_CAST (t)->subtypes))
270 
271 #define WXS_TYPE_CONTENTTYPE(t) (t)->subtypes
272 
273 #define WXS_TYPE_PARTICLE(t) WXS_PTC_CAST (t)->subtypes
274 
275 #define WXS_TYPE_PARTICLE_TERM(t) WXS_PARTICLE_TERM(WXS_TYPE_PARTICLE(t))
276 /*
277 * Macros for exclusively for simple types.
278 */
279 #define WXS_LIST_ITEMTYPE(t) (t)->subtypes
280 
281 #define WXS_IS_ATOMIC(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
282 
283 #define WXS_IS_LIST(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
284 
285 #define WXS_IS_UNION(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)
286 /*
287 * Misc parser context macros.
288 */
289 #define WXS_CONSTRUCTOR(ctx) (ctx)->constructor
290 
291 #define WXS_HAS_BUCKETS(ctx) \
292 ( (WXS_CONSTRUCTOR((ctx))->buckets != NULL) && \
293 (WXS_CONSTRUCTOR((ctx))->buckets->nbItems > 0) )
294 
295 #define WXS_SUBST_GROUPS(ctx) WXS_CONSTRUCTOR((ctx))->substGroups
296 
297 #define WXS_BUCKET(ctx) WXS_CONSTRUCTOR((ctx))->bucket
298 
299 #define WXS_SCHEMA(ctx) (ctx)->schema
300 
301 #define WXS_ADD_LOCAL(ctx, item) \
302     xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->locals), 10, item)
303 
304 #define WXS_ADD_GLOBAL(ctx, item) \
305     xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->globals), 5, item)
306 
307 #define WXS_ADD_PENDING(ctx, item) \
308     xmlSchemaAddItemSize(&((ctx)->constructor->pending), 10, item)
309 /*
310 * xmlSchemaItemList macros.
311 */
312 #define WXS_ILIST_IS_EMPTY(l) ((l == NULL) || ((l)->nbItems == 0))
313 /*
314 * Misc macros.
315 */
316 #define IS_SCHEMA(node, type) \
317    ((node != NULL) && (node->ns != NULL) && \
318     (xmlStrEqual(node->name, (const xmlChar *) type)) && \
319     (xmlStrEqual(node->ns->href, xmlSchemaNs)))
320 
321 #define FREE_AND_NULL(str) if ((str) != NULL) { xmlFree((xmlChar *) (str)); str = NULL; }
322 
323 /*
324 * Since we put the default/fixed values into the dict, we can
325 * use pointer comparison for those values.
326 * REMOVED: (xmlStrEqual((v1), (v2)))
327 */
328 #define WXS_ARE_DEFAULT_STR_EQUAL(v1, v2) ((v1) == (v2))
329 
330 #define INODE_NILLED(item) (item->flags & XML_SCHEMA_ELEM_INFO_NILLED)
331 
332 #define CAN_PARSE_SCHEMA(b) (((b)->doc != NULL) && ((b)->parsed == 0))
333 
334 #define HFAILURE if (res == -1) goto exit_failure;
335 
336 #define HERROR if (res != 0) goto exit_error;
337 
338 #define HSTOP(ctx) if ((ctx)->stop) goto exit;
339 /*
340 * Some flags used for various schema constraints.
341 */
342 #define SUBSET_RESTRICTION  1<<0
343 #define SUBSET_EXTENSION    1<<1
344 #define SUBSET_SUBSTITUTION 1<<2
345 #define SUBSET_LIST         1<<3
346 #define SUBSET_UNION        1<<4
347 
348 typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
349 typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
350 
351 typedef struct _xmlSchemaItemList xmlSchemaItemList;
352 typedef xmlSchemaItemList *xmlSchemaItemListPtr;
353 struct _xmlSchemaItemList {
354     void **items;  /* used for dynamic addition of schemata */
355     int nbItems; /* used for dynamic addition of schemata */
356     int sizeItems; /* used for dynamic addition of schemata */
357 };
358 
359 #define XML_SCHEMA_CTXT_PARSER 1
360 #define XML_SCHEMA_CTXT_VALIDATOR 2
361 
362 typedef struct _xmlSchemaAbstractCtxt xmlSchemaAbstractCtxt;
363 typedef xmlSchemaAbstractCtxt *xmlSchemaAbstractCtxtPtr;
364 struct _xmlSchemaAbstractCtxt {
365     int type; /* E.g. XML_SCHEMA_CTXT_VALIDATOR */
366 };
367 
368 typedef struct _xmlSchemaBucket xmlSchemaBucket;
369 typedef xmlSchemaBucket *xmlSchemaBucketPtr;
370 
371 #define XML_SCHEMA_SCHEMA_MAIN 0
372 #define XML_SCHEMA_SCHEMA_IMPORT 1
373 #define XML_SCHEMA_SCHEMA_INCLUDE 2
374 #define XML_SCHEMA_SCHEMA_REDEFINE 3
375 
376 /**
377  * xmlSchemaSchemaRelation:
378  *
379  * Used to create a graph of schema relationships.
380  */
381 typedef struct _xmlSchemaSchemaRelation xmlSchemaSchemaRelation;
382 typedef xmlSchemaSchemaRelation *xmlSchemaSchemaRelationPtr;
383 struct _xmlSchemaSchemaRelation {
384     xmlSchemaSchemaRelationPtr next;
385     int type; /* E.g. XML_SCHEMA_SCHEMA_IMPORT */
386     const xmlChar *importNamespace;
387     xmlSchemaBucketPtr bucket;
388 };
389 
390 #define XML_SCHEMA_BUCKET_MARKED 1<<0
391 #define XML_SCHEMA_BUCKET_COMPS_ADDED 1<<1
392 
393 struct _xmlSchemaBucket {
394     int type;
395     int flags;
396     const xmlChar *schemaLocation;
397     const xmlChar *origTargetNamespace;
398     const xmlChar *targetNamespace;
399     xmlDocPtr doc;
400     xmlSchemaSchemaRelationPtr relations;
401     int located;
402     int parsed;
403     int imported;
404     int preserveDoc;
405     xmlSchemaItemListPtr globals; /* Global components. */
406     xmlSchemaItemListPtr locals; /* Local components. */
407 };
408 
409 /**
410  * xmlSchemaImport:
411  * (extends xmlSchemaBucket)
412  *
413  * Reflects a schema. Holds some information
414  * about the schema and its toplevel components. Duplicate
415  * toplevel components are not checked at this level.
416  */
417 typedef struct _xmlSchemaImport xmlSchemaImport;
418 typedef xmlSchemaImport *xmlSchemaImportPtr;
419 struct _xmlSchemaImport {
420     int type; /* Main OR import OR include. */
421     int flags;
422     const xmlChar *schemaLocation; /* The URI of the schema document. */
423     /* For chameleon includes, @origTargetNamespace will be NULL */
424     const xmlChar *origTargetNamespace;
425     /*
426     * For chameleon includes, @targetNamespace will be the
427     * targetNamespace of the including schema.
428     */
429     const xmlChar *targetNamespace;
430     xmlDocPtr doc; /* The schema node-tree. */
431     /* @relations will hold any included/imported/redefined schemas. */
432     xmlSchemaSchemaRelationPtr relations;
433     int located;
434     int parsed;
435     int imported;
436     int preserveDoc;
437     xmlSchemaItemListPtr globals;
438     xmlSchemaItemListPtr locals;
439     /* The imported schema. */
440     xmlSchemaPtr schema;
441 };
442 
443 /*
444 * (extends xmlSchemaBucket)
445 */
446 typedef struct _xmlSchemaInclude xmlSchemaInclude;
447 typedef xmlSchemaInclude *xmlSchemaIncludePtr;
448 struct _xmlSchemaInclude {
449     int type;
450     int flags;
451     const xmlChar *schemaLocation;
452     const xmlChar *origTargetNamespace;
453     const xmlChar *targetNamespace;
454     xmlDocPtr doc;
455     xmlSchemaSchemaRelationPtr relations;
456     int located;
457     int parsed;
458     int imported;
459     int preserveDoc;
460     xmlSchemaItemListPtr globals; /* Global components. */
461     xmlSchemaItemListPtr locals; /* Local components. */
462 
463     /* The owning main or import schema bucket. */
464     xmlSchemaImportPtr ownerImport;
465 };
466 
467 /**
468  * xmlSchemaBasicItem:
469  *
470  * The abstract base type for schema components.
471  */
472 typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
473 typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
474 struct _xmlSchemaBasicItem {
475     xmlSchemaTypeType type;
476 };
477 
478 /**
479  * xmlSchemaAnnotItem:
480  *
481  * The abstract base type for annotated schema components.
482  * (Extends xmlSchemaBasicItem)
483  */
484 typedef struct _xmlSchemaAnnotItem xmlSchemaAnnotItem;
485 typedef xmlSchemaAnnotItem *xmlSchemaAnnotItemPtr;
486 struct _xmlSchemaAnnotItem {
487     xmlSchemaTypeType type;
488     xmlSchemaAnnotPtr annot;
489 };
490 
491 /**
492  * xmlSchemaTreeItem:
493  *
494  * The abstract base type for tree-like structured schema components.
495  * (Extends xmlSchemaAnnotItem)
496  */
497 typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
498 typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
499 struct _xmlSchemaTreeItem {
500     xmlSchemaTypeType type;
501     xmlSchemaAnnotPtr annot;
502     xmlSchemaTreeItemPtr next;
503     xmlSchemaTreeItemPtr children;
504 };
505 
506 
507 #define XML_SCHEMA_ATTR_USE_FIXED 1<<0
508 /**
509  * xmlSchemaAttributeUsePtr:
510  *
511  * The abstract base type for tree-like structured schema components.
512  * (Extends xmlSchemaTreeItem)
513  */
514 typedef struct _xmlSchemaAttributeUse xmlSchemaAttributeUse;
515 typedef xmlSchemaAttributeUse *xmlSchemaAttributeUsePtr;
516 struct _xmlSchemaAttributeUse {
517     xmlSchemaTypeType type;
518     xmlSchemaAnnotPtr annot;
519     xmlSchemaAttributeUsePtr next; /* The next attr. use. */
520     /*
521     * The attr. decl. OR a QName-ref. to an attr. decl. OR
522     * a QName-ref. to an attribute group definition.
523     */
524     xmlSchemaAttributePtr attrDecl;
525 
526     int flags;
527     xmlNodePtr node;
528     int occurs; /* required, optional */
529     const xmlChar * defValue;
530     xmlSchemaValPtr defVal;
531 };
532 
533 /**
534  * xmlSchemaAttributeUseProhibPtr:
535  *
536  * A helper component to reflect attribute prohibitions.
537  * (Extends xmlSchemaBasicItem)
538  */
539 typedef struct _xmlSchemaAttributeUseProhib xmlSchemaAttributeUseProhib;
540 typedef xmlSchemaAttributeUseProhib *xmlSchemaAttributeUseProhibPtr;
541 struct _xmlSchemaAttributeUseProhib {
542     xmlSchemaTypeType type; /* == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB */
543     xmlNodePtr node;
544     const xmlChar *name;
545     const xmlChar *targetNamespace;
546     int isRef;
547 };
548 
549 /**
550  * xmlSchemaRedef:
551  */
552 typedef struct _xmlSchemaRedef xmlSchemaRedef;
553 typedef xmlSchemaRedef *xmlSchemaRedefPtr;
554 struct _xmlSchemaRedef {
555     xmlSchemaRedefPtr next;
556     xmlSchemaBasicItemPtr item; /* The redefining component. */
557     xmlSchemaBasicItemPtr reference; /* The referencing component. */
558     xmlSchemaBasicItemPtr target; /* The to-be-redefined component. */
559     const xmlChar *refName; /* The name of the to-be-redefined component. */
560     const xmlChar *refTargetNs; /* The target namespace of the
561                                    to-be-redefined comp. */
562     xmlSchemaBucketPtr targetBucket; /* The redefined schema. */
563 };
564 
565 /**
566  * xmlSchemaConstructionCtxt:
567  */
568 typedef struct _xmlSchemaConstructionCtxt xmlSchemaConstructionCtxt;
569 typedef xmlSchemaConstructionCtxt *xmlSchemaConstructionCtxtPtr;
570 struct _xmlSchemaConstructionCtxt {
571     xmlSchemaPtr mainSchema; /* The main schema. */
572     xmlSchemaBucketPtr mainBucket; /* The main schema bucket */
573     xmlDictPtr dict;
574     xmlSchemaItemListPtr buckets; /* List of schema buckets. */
575     /* xmlSchemaItemListPtr relations; */ /* List of schema relations. */
576     xmlSchemaBucketPtr bucket; /* The current schema bucket */
577     xmlSchemaItemListPtr pending; /* All Components of all schemas that
578                                      need to be fixed. */
579     xmlHashTablePtr substGroups;
580     xmlSchemaRedefPtr redefs;
581     xmlSchemaRedefPtr lastRedef;
582 };
583 
584 #define XML_SCHEMAS_PARSE_ERROR		1
585 #define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
586 
587 struct _xmlSchemaParserCtxt {
588     int type;
589     void *errCtxt;             /* user specific error context */
590     xmlSchemaValidityErrorFunc error;   /* the callback in case of errors */
591     xmlSchemaValidityWarningFunc warning;       /* the callback in case of warning */
592     int err;
593     int nberrors;
594     xmlStructuredErrorFunc serror;
595 
596     xmlSchemaConstructionCtxtPtr constructor;
597     int ownsConstructor; /* TODO: Move this to parser *flags*. */
598 
599     /* xmlSchemaPtr topschema;	*/
600     /* xmlHashTablePtr namespaces;  */
601 
602     xmlSchemaPtr schema;        /* The main schema in use */
603     int counter;
604 
605     const xmlChar *URL;
606     xmlDocPtr doc;
607     int preserve;		/* Whether the doc should be freed  */
608 
609     const char *buffer;
610     int size;
611 
612     /*
613      * Used to build complex element content models
614      */
615     xmlAutomataPtr am;
616     xmlAutomataStatePtr start;
617     xmlAutomataStatePtr end;
618     xmlAutomataStatePtr state;
619 
620     xmlDictPtr dict;		/* dictionnary for interned string names */
621     xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
622     int options;
623     xmlSchemaValidCtxtPtr vctxt;
624     int isS4S;
625     int isRedefine;
626     int xsiAssemble;
627     int stop; /* If the parser should stop; i.e. a critical error. */
628     const xmlChar *targetNamespace;
629     xmlSchemaBucketPtr redefined; /* The schema to be redefined. */
630 
631     xmlSchemaRedefPtr redef; /* Used for redefinitions. */
632     int redefCounter; /* Used for redefinitions. */
633     xmlSchemaItemListPtr attrProhibs;
634 };
635 
636 /**
637  * xmlSchemaQNameRef:
638  *
639  * A component reference item (not a schema component)
640  * (Extends xmlSchemaBasicItem)
641  */
642 typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef;
643 typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr;
644 struct _xmlSchemaQNameRef {
645     xmlSchemaTypeType type;
646     xmlSchemaBasicItemPtr item; /* The resolved referenced item. */
647     xmlSchemaTypeType itemType;
648     const xmlChar *name;
649     const xmlChar *targetNamespace;
650     xmlNodePtr node;
651 };
652 
653 /**
654  * xmlSchemaParticle:
655  *
656  * A particle component.
657  * (Extends xmlSchemaTreeItem)
658  */
659 typedef struct _xmlSchemaParticle xmlSchemaParticle;
660 typedef xmlSchemaParticle *xmlSchemaParticlePtr;
661 struct _xmlSchemaParticle {
662     xmlSchemaTypeType type;
663     xmlSchemaAnnotPtr annot;
664     xmlSchemaTreeItemPtr next; /* next particle */
665     xmlSchemaTreeItemPtr children; /* the "term" (e.g. a model group,
666 	a group definition, a XML_SCHEMA_EXTRA_QNAMEREF (if a reference),
667         etc.) */
668     int minOccurs;
669     int maxOccurs;
670     xmlNodePtr node;
671 };
672 
673 /**
674  * xmlSchemaModelGroup:
675  *
676  * A model group component.
677  * (Extends xmlSchemaTreeItem)
678  */
679 typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
680 typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
681 struct _xmlSchemaModelGroup {
682     xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_SEQUENCE, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL */
683     xmlSchemaAnnotPtr annot;
684     xmlSchemaTreeItemPtr next; /* not used */
685     xmlSchemaTreeItemPtr children; /* first particle (OR "element decl" OR "wildcard") */
686     xmlNodePtr node;
687 };
688 
689 #define XML_SCHEMA_MODEL_GROUP_DEF_MARKED 1<<0
690 #define XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED 1<<1
691 /**
692  * xmlSchemaModelGroupDef:
693  *
694  * A model group definition component.
695  * (Extends xmlSchemaTreeItem)
696  */
697 typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
698 typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
699 struct _xmlSchemaModelGroupDef {
700     xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_GROUP */
701     xmlSchemaAnnotPtr annot;
702     xmlSchemaTreeItemPtr next; /* not used */
703     xmlSchemaTreeItemPtr children; /* the "model group" */
704     const xmlChar *name;
705     const xmlChar *targetNamespace;
706     xmlNodePtr node;
707     int flags;
708 };
709 
710 typedef struct _xmlSchemaIDC xmlSchemaIDC;
711 typedef xmlSchemaIDC *xmlSchemaIDCPtr;
712 
713 /**
714  * xmlSchemaIDCSelect:
715  *
716  * The identity-constraint "field" and "selector" item, holding the
717  * XPath expression.
718  */
719 typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
720 typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
721 struct _xmlSchemaIDCSelect {
722     xmlSchemaIDCSelectPtr next;
723     xmlSchemaIDCPtr idc;
724     int index; /* an index position if significant for IDC key-sequences */
725     const xmlChar *xpath; /* the XPath expression */
726     void *xpathComp; /* the compiled XPath expression */
727 };
728 
729 /**
730  * xmlSchemaIDC:
731  *
732  * The identity-constraint definition component.
733  * (Extends xmlSchemaAnnotItem)
734  */
735 
736 struct _xmlSchemaIDC {
737     xmlSchemaTypeType type;
738     xmlSchemaAnnotPtr annot;
739     xmlSchemaIDCPtr next;
740     xmlNodePtr node;
741     const xmlChar *name;
742     const xmlChar *targetNamespace;
743     xmlSchemaIDCSelectPtr selector;
744     xmlSchemaIDCSelectPtr fields;
745     int nbFields;
746     xmlSchemaQNameRefPtr ref;
747 };
748 
749 /**
750  * xmlSchemaIDCAug:
751  *
752  * The augmented IDC information used for validation.
753  */
754 typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
755 typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
756 struct _xmlSchemaIDCAug {
757     xmlSchemaIDCAugPtr next; /* next in a list */
758     xmlSchemaIDCPtr def; /* the IDC definition */
759     int keyrefDepth; /* the lowest tree level to which IDC
760                         tables need to be bubbled upwards */
761 };
762 
763 /**
764  * xmlSchemaPSVIIDCKeySequence:
765  *
766  * The key sequence of a node table item.
767  */
768 typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
769 typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
770 struct _xmlSchemaPSVIIDCKey {
771     xmlSchemaTypePtr type;
772     xmlSchemaValPtr val;
773 };
774 
775 /**
776  * xmlSchemaPSVIIDCNode:
777  *
778  * The node table item of a node table.
779  */
780 typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
781 typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
782 struct _xmlSchemaPSVIIDCNode {
783     xmlNodePtr node;
784     xmlSchemaPSVIIDCKeyPtr *keys;
785     int nodeLine;
786     int nodeQNameID;
787 
788 };
789 
790 /**
791  * xmlSchemaPSVIIDCBinding:
792  *
793  * The identity-constraint binding item of the [identity-constraint table].
794  */
795 typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
796 typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
797 struct _xmlSchemaPSVIIDCBinding {
798     xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
799     xmlSchemaIDCPtr definition; /* the IDC definition */
800     xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
801     int nbNodes; /* number of entries in the node table */
802     int sizeNodes; /* size of the node table */
803     xmlSchemaItemListPtr dupls;
804 };
805 
806 
807 #define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
808 #define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
809 
810 #define XPATH_STATE_OBJ_MATCHES -2
811 #define XPATH_STATE_OBJ_BLOCKED -3
812 
813 typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
814 typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
815 
816 /**
817  * xmlSchemaIDCStateObj:
818  *
819  * The state object used to evaluate XPath expressions.
820  */
821 typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
822 typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
823 struct _xmlSchemaIDCStateObj {
824     int type;
825     xmlSchemaIDCStateObjPtr next; /* next if in a list */
826     int depth; /* depth of creation */
827     int *history; /* list of (depth, state-id) tuples */
828     int nbHistory;
829     int sizeHistory;
830     xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
831                                        matcher */
832     xmlSchemaIDCSelectPtr sel;
833     void *xpathCtxt;
834 };
835 
836 #define IDC_MATCHER 0
837 
838 /**
839  * xmlSchemaIDCMatcher:
840  *
841  * Used to evaluate IDC selectors (and fields).
842  */
843 struct _xmlSchemaIDCMatcher {
844     int type;
845     int depth; /* the tree depth at creation time */
846     xmlSchemaIDCMatcherPtr next; /* next in the list */
847     xmlSchemaIDCMatcherPtr nextCached; /* next in the cache list */
848     xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
849     int idcType;
850     xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
851                                          elements */
852     int sizeKeySeqs;
853     xmlSchemaItemListPtr targets; /* list of target-node
854                                      (xmlSchemaPSVIIDCNodePtr) entries */
855 };
856 
857 /*
858 * Element info flags.
859 */
860 #define XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES  1<<0
861 #define XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES 1<<1
862 #define XML_SCHEMA_ELEM_INFO_NILLED	       1<<2
863 #define XML_SCHEMA_ELEM_INFO_LOCAL_TYPE	       1<<3
864 
865 #define XML_SCHEMA_NODE_INFO_VALUE_NEEDED      1<<4
866 #define XML_SCHEMA_ELEM_INFO_EMPTY             1<<5
867 #define XML_SCHEMA_ELEM_INFO_HAS_CONTENT       1<<6
868 
869 #define XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT  1<<7
870 #define XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT  1<<8
871 #define XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED  1<<9
872 #define XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE  1<<10
873 
874 /**
875  * xmlSchemaNodeInfo:
876  *
877  * Holds information of an element node.
878  */
879 struct _xmlSchemaNodeInfo {
880     int nodeType;
881     xmlNodePtr node;
882     int nodeLine;
883     const xmlChar *localName;
884     const xmlChar *nsName;
885     const xmlChar *value;
886     xmlSchemaValPtr val; /* the pre-computed value if any */
887     xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
888 
889     int flags; /* combination of node info flags */
890 
891     int valNeeded;
892     int normVal;
893 
894     xmlSchemaElementPtr decl; /* the element/attribute declaration */
895     int depth;
896     xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
897                                             for the scope element*/
898     xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
899                                            element */
900     xmlRegExecCtxtPtr regexCtxt;
901 
902     const xmlChar **nsBindings; /* Namespace bindings on this element */
903     int nbNsBindings;
904     int sizeNsBindings;
905 
906     int hasKeyrefs;
907     int appliedXPath; /* Indicates that an XPath has been applied. */
908 };
909 
910 #define XML_SCHEMAS_ATTR_UNKNOWN 1
911 #define XML_SCHEMAS_ATTR_ASSESSED 2
912 #define XML_SCHEMAS_ATTR_PROHIBITED 3
913 #define XML_SCHEMAS_ATTR_ERR_MISSING 4
914 #define XML_SCHEMAS_ATTR_INVALID_VALUE 5
915 #define XML_SCHEMAS_ATTR_ERR_NO_TYPE 6
916 #define XML_SCHEMAS_ATTR_ERR_FIXED_VALUE 7
917 #define XML_SCHEMAS_ATTR_DEFAULT 8
918 #define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
919 #define XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL 10
920 #define XML_SCHEMAS_ATTR_HAS_ATTR_USE 11
921 #define XML_SCHEMAS_ATTR_HAS_ATTR_DECL 12
922 #define XML_SCHEMAS_ATTR_WILD_SKIP 13
923 #define XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL 14
924 #define XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID 15
925 #define XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID 16
926 #define XML_SCHEMAS_ATTR_META 17
927 /*
928 * @metaType values of xmlSchemaAttrInfo.
929 */
930 #define XML_SCHEMA_ATTR_INFO_META_XSI_TYPE 1
931 #define XML_SCHEMA_ATTR_INFO_META_XSI_NIL 2
932 #define XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC 3
933 #define XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC 4
934 #define XML_SCHEMA_ATTR_INFO_META_XMLNS 5
935 
936 typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo;
937 typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr;
938 struct _xmlSchemaAttrInfo {
939     int nodeType;
940     xmlNodePtr node;
941     int nodeLine;
942     const xmlChar *localName;
943     const xmlChar *nsName;
944     const xmlChar *value;
945     xmlSchemaValPtr val; /* the pre-computed value if any */
946     xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
947     int flags; /* combination of node info flags */
948 
949     xmlSchemaAttributePtr decl; /* the attribute declaration */
950     xmlSchemaAttributeUsePtr use;  /* the attribute use */
951     int state;
952     int metaType;
953     const xmlChar *vcValue; /* the value constraint value */
954     xmlSchemaNodeInfoPtr parent;
955 };
956 
957 
958 #define XML_SCHEMA_VALID_CTXT_FLAG_STREAM 1
959 /**
960  * xmlSchemaValidCtxt:
961  *
962  * A Schemas validation context
963  */
964 struct _xmlSchemaValidCtxt {
965     int type;
966     void *errCtxt;             /* user specific data block */
967     xmlSchemaValidityErrorFunc error;   /* the callback in case of errors */
968     xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
969     xmlStructuredErrorFunc serror;
970 
971     xmlSchemaPtr schema;        /* The schema in use */
972     xmlDocPtr doc;
973     xmlParserInputBufferPtr input;
974     xmlCharEncoding enc;
975     xmlSAXHandlerPtr sax;
976     xmlParserCtxtPtr parserCtxt;
977     void *user_data; /* TODO: What is this for? */
978 
979     int err;
980     int nberrors;
981 
982     xmlNodePtr node;
983     xmlNodePtr cur;
984     /* xmlSchemaTypePtr type; */
985 
986     xmlRegExecCtxtPtr regexp;
987     xmlSchemaValPtr value;
988 
989     int valueWS;
990     int options;
991     xmlNodePtr validationRoot;
992     xmlSchemaParserCtxtPtr pctxt;
993     int xsiAssemble;
994 
995     int depth;
996     xmlSchemaNodeInfoPtr *elemInfos; /* array of element informations */
997     int sizeElemInfos;
998     xmlSchemaNodeInfoPtr inode; /* the current element information */
999 
1000     xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */
1001 
1002     xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
1003     xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
1004     xmlSchemaIDCMatcherPtr idcMatcherCache; /* Cache for IDC matcher objects. */
1005 
1006     xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
1007     int nbIdcNodes;
1008     int sizeIdcNodes;
1009 
1010     xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
1011     int nbIdcKeys;
1012     int sizeIdcKeys;
1013 
1014     int flags;
1015 
1016     xmlDictPtr dict;
1017 
1018 #ifdef LIBXML_READER_ENABLED
1019     xmlTextReaderPtr reader;
1020 #endif
1021 
1022     xmlSchemaAttrInfoPtr *attrInfos;
1023     int nbAttrInfos;
1024     int sizeAttrInfos;
1025 
1026     int skipDepth;
1027     xmlSchemaItemListPtr nodeQNames;
1028     int hasKeyrefs;
1029     int createIDCNodeTables;
1030     int psviExposeIDCNodeTables;
1031 };
1032 
1033 /**
1034  * xmlSchemaSubstGroup:
1035  *
1036  *
1037  */
1038 typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup;
1039 typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr;
1040 struct _xmlSchemaSubstGroup {
1041     xmlSchemaElementPtr head;
1042     xmlSchemaItemListPtr members;
1043 };
1044 
1045 /************************************************************************
1046  * 									*
1047  * 			Some predeclarations				*
1048  * 									*
1049  ************************************************************************/
1050 
1051 static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
1052                                  xmlSchemaPtr schema,
1053                                  xmlNodePtr node);
1054 static int xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr ctxt,
1055                                  xmlSchemaPtr schema,
1056                                  xmlNodePtr node);
1057 static int
1058 xmlSchemaTypeFixup(xmlSchemaTypePtr type,
1059                    xmlSchemaAbstractCtxtPtr ctxt);
1060 static const xmlChar *
1061 xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
1062 static int
1063 xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1064                      xmlNodePtr node);
1065 static int
1066 xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
1067                        xmlSchemaParserCtxtPtr ctxt);
1068 static void
1069 xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
1070 static xmlSchemaWhitespaceValueType
1071 xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
1072 static xmlSchemaTreeItemPtr
1073 xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1074 			 xmlNodePtr node, xmlSchemaTypeType type,
1075 			 int withParticle);
1076 static const xmlChar *
1077 xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item);
1078 static xmlSchemaTypeLinkPtr
1079 xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
1080 static void
1081 xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
1082 		     const char *funcName,
1083 		     const char *message);
1084 static int
1085 xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr ctxt,
1086 			     xmlSchemaTypePtr type,
1087 			     xmlSchemaTypePtr baseType,
1088 			     int subset);
1089 static void
1090 xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
1091 				   xmlSchemaParserCtxtPtr ctxt);
1092 static void
1093 xmlSchemaComponentListFree(xmlSchemaItemListPtr list);
1094 static xmlSchemaQNameRefPtr
1095 xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
1096 				xmlSchemaPtr schema,
1097 				xmlNodePtr node);
1098 
1099 /************************************************************************
1100  *									*
1101  * 			Helper functions			        *
1102  *									*
1103  ************************************************************************/
1104 
1105 /**
1106  * xmlSchemaItemTypeToStr:
1107  * @type: the type of the schema item
1108  *
1109  * Returns the component name of a schema item.
1110  */
1111 static const xmlChar *
xmlSchemaItemTypeToStr(xmlSchemaTypeType type)1112 xmlSchemaItemTypeToStr(xmlSchemaTypeType type)
1113 {
1114     switch (type) {
1115 	case XML_SCHEMA_TYPE_BASIC:
1116 	    return(BAD_CAST "simple type definition");
1117 	case XML_SCHEMA_TYPE_SIMPLE:
1118 	    return(BAD_CAST "simple type definition");
1119 	case XML_SCHEMA_TYPE_COMPLEX:
1120 	    return(BAD_CAST "complex type definition");
1121 	case XML_SCHEMA_TYPE_ELEMENT:
1122 	    return(BAD_CAST "element declaration");
1123 	case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1124 	    return(BAD_CAST "attribute use");
1125 	case XML_SCHEMA_TYPE_ATTRIBUTE:
1126 	    return(BAD_CAST "attribute declaration");
1127 	case XML_SCHEMA_TYPE_GROUP:
1128 	    return(BAD_CAST "model group definition");
1129 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1130 	    return(BAD_CAST "attribute group definition");
1131 	case XML_SCHEMA_TYPE_NOTATION:
1132 	    return(BAD_CAST "notation declaration");
1133 	case XML_SCHEMA_TYPE_SEQUENCE:
1134 	    return(BAD_CAST "model group (sequence)");
1135 	case XML_SCHEMA_TYPE_CHOICE:
1136 	    return(BAD_CAST "model group (choice)");
1137 	case XML_SCHEMA_TYPE_ALL:
1138 	    return(BAD_CAST "model group (all)");
1139 	case XML_SCHEMA_TYPE_PARTICLE:
1140 	    return(BAD_CAST "particle");
1141 	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1142 	    return(BAD_CAST "unique identity-constraint");
1143 	    /* return(BAD_CAST "IDC (unique)"); */
1144 	case XML_SCHEMA_TYPE_IDC_KEY:
1145 	    return(BAD_CAST "key identity-constraint");
1146 	    /* return(BAD_CAST "IDC (key)"); */
1147 	case XML_SCHEMA_TYPE_IDC_KEYREF:
1148 	    return(BAD_CAST "keyref identity-constraint");
1149 	    /* return(BAD_CAST "IDC (keyref)"); */
1150 	case XML_SCHEMA_TYPE_ANY:
1151 	    return(BAD_CAST "wildcard (any)");
1152 	case XML_SCHEMA_EXTRA_QNAMEREF:
1153 	    return(BAD_CAST "[helper component] QName reference");
1154 	case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
1155 	    return(BAD_CAST "[helper component] attribute use prohibition");
1156 	default:
1157 	    return(BAD_CAST "Not a schema component");
1158     }
1159 }
1160 
1161 /**
1162  * xmlSchemaGetComponentTypeStr:
1163  * @type: the type of the schema item
1164  *
1165  * Returns the component name of a schema item.
1166  */
1167 static const xmlChar *
xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item)1168 xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item)
1169 {
1170     switch (item->type) {
1171 	case XML_SCHEMA_TYPE_BASIC:
1172 	    if (WXS_IS_COMPLEX(WXS_TYPE_CAST item))
1173 		return(BAD_CAST "complex type definition");
1174 	    else
1175 		return(BAD_CAST "simple type definition");
1176 	default:
1177 	    return(xmlSchemaItemTypeToStr(item->type));
1178     }
1179 }
1180 
1181 /**
1182  * xmlSchemaGetComponentNode:
1183  * @item: a schema component
1184  *
1185  * Returns node associated with the schema component.
1186  * NOTE that such a node need not be available; plus, a component's
1187  * node need not to reflect the component directly, since there is no
1188  * one-to-one relationship between the XML Schema representation and
1189  * the component representation.
1190  */
1191 static xmlNodePtr
xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)1192 xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
1193 {
1194     switch (item->type) {
1195 	case XML_SCHEMA_TYPE_ELEMENT:
1196 	    return (((xmlSchemaElementPtr) item)->node);
1197 	case XML_SCHEMA_TYPE_ATTRIBUTE:
1198 	    return (((xmlSchemaAttributePtr) item)->node);
1199 	case XML_SCHEMA_TYPE_COMPLEX:
1200 	case XML_SCHEMA_TYPE_SIMPLE:
1201 	    return (((xmlSchemaTypePtr) item)->node);
1202 	case XML_SCHEMA_TYPE_ANY:
1203 	case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1204 	    return (((xmlSchemaWildcardPtr) item)->node);
1205 	case XML_SCHEMA_TYPE_PARTICLE:
1206 	    return (((xmlSchemaParticlePtr) item)->node);
1207 	case XML_SCHEMA_TYPE_SEQUENCE:
1208 	case XML_SCHEMA_TYPE_CHOICE:
1209 	case XML_SCHEMA_TYPE_ALL:
1210 	    return (((xmlSchemaModelGroupPtr) item)->node);
1211 	case XML_SCHEMA_TYPE_GROUP:
1212 	    return (((xmlSchemaModelGroupDefPtr) item)->node);
1213 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1214 	    return (((xmlSchemaAttributeGroupPtr) item)->node);
1215 	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1216 	case XML_SCHEMA_TYPE_IDC_KEY:
1217 	case XML_SCHEMA_TYPE_IDC_KEYREF:
1218 	    return (((xmlSchemaIDCPtr) item)->node);
1219 	case XML_SCHEMA_EXTRA_QNAMEREF:
1220 	    return(((xmlSchemaQNameRefPtr) item)->node);
1221 	/* TODO: What to do with NOTATIONs?
1222 	case XML_SCHEMA_TYPE_NOTATION:
1223 	    return (((xmlSchemaNotationPtr) item)->node);
1224 	*/
1225 	case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1226 	    return (((xmlSchemaAttributeUsePtr) item)->node);
1227 	default:
1228 	    return (NULL);
1229     }
1230 }
1231 
1232 #if 0
1233 /**
1234  * xmlSchemaGetNextComponent:
1235  * @item: a schema component
1236  *
1237  * Returns the next sibling of the schema component.
1238  */
1239 static xmlSchemaBasicItemPtr
1240 xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
1241 {
1242     switch (item->type) {
1243 	case XML_SCHEMA_TYPE_ELEMENT:
1244 	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
1245 	case XML_SCHEMA_TYPE_ATTRIBUTE:
1246 	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
1247 	case XML_SCHEMA_TYPE_COMPLEX:
1248 	case XML_SCHEMA_TYPE_SIMPLE:
1249 	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
1250 	case XML_SCHEMA_TYPE_ANY:
1251 	case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1252 	    return (NULL);
1253 	case XML_SCHEMA_TYPE_PARTICLE:
1254 	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
1255 	case XML_SCHEMA_TYPE_SEQUENCE:
1256 	case XML_SCHEMA_TYPE_CHOICE:
1257 	case XML_SCHEMA_TYPE_ALL:
1258 	    return (NULL);
1259 	case XML_SCHEMA_TYPE_GROUP:
1260 	    return (NULL);
1261 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1262 	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
1263 	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1264 	case XML_SCHEMA_TYPE_IDC_KEY:
1265 	case XML_SCHEMA_TYPE_IDC_KEYREF:
1266 	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
1267 	default:
1268 	    return (NULL);
1269     }
1270 }
1271 #endif
1272 
1273 
1274 /**
1275  * xmlSchemaFormatQName:
1276  * @buf: the string buffer
1277  * @namespaceName:  the namespace name
1278  * @localName: the local name
1279  *
1280  * Returns the given QName in the format "{namespaceName}localName" or
1281  * just "localName" if @namespaceName is NULL.
1282  *
1283  * Returns the localName if @namespaceName is NULL, a formatted
1284  * string otherwise.
1285  */
1286 static const xmlChar*
xmlSchemaFormatQName(xmlChar ** buf,const xmlChar * namespaceName,const xmlChar * localName)1287 xmlSchemaFormatQName(xmlChar **buf,
1288 		     const xmlChar *namespaceName,
1289 		     const xmlChar *localName)
1290 {
1291     FREE_AND_NULL(*buf)
1292     if (namespaceName != NULL) {
1293 	*buf = xmlStrdup(BAD_CAST "{");
1294 	*buf = xmlStrcat(*buf, namespaceName);
1295 	*buf = xmlStrcat(*buf, BAD_CAST "}");
1296     }
1297     if (localName != NULL) {
1298 	if (namespaceName == NULL)
1299 	    return(localName);
1300 	*buf = xmlStrcat(*buf, localName);
1301     } else {
1302 	*buf = xmlStrcat(*buf, BAD_CAST "(NULL)");
1303     }
1304     return ((const xmlChar *) *buf);
1305 }
1306 
1307 static const xmlChar*
xmlSchemaFormatQNameNs(xmlChar ** buf,xmlNsPtr ns,const xmlChar * localName)1308 xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName)
1309 {
1310     if (ns != NULL)
1311 	return (xmlSchemaFormatQName(buf, ns->href, localName));
1312     else
1313 	return (xmlSchemaFormatQName(buf, NULL, localName));
1314 }
1315 
1316 static const xmlChar *
xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)1317 xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
1318 {
1319     switch (item->type) {
1320 	case XML_SCHEMA_TYPE_ELEMENT:
1321 	    return (((xmlSchemaElementPtr) item)->name);
1322 	case XML_SCHEMA_TYPE_ATTRIBUTE:
1323 	    return (((xmlSchemaAttributePtr) item)->name);
1324 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1325 	    return (((xmlSchemaAttributeGroupPtr) item)->name);
1326 	case XML_SCHEMA_TYPE_BASIC:
1327 	case XML_SCHEMA_TYPE_SIMPLE:
1328 	case XML_SCHEMA_TYPE_COMPLEX:
1329 	    return (((xmlSchemaTypePtr) item)->name);
1330 	case XML_SCHEMA_TYPE_GROUP:
1331 	    return (((xmlSchemaModelGroupDefPtr) item)->name);
1332 	case XML_SCHEMA_TYPE_IDC_KEY:
1333 	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1334 	case XML_SCHEMA_TYPE_IDC_KEYREF:
1335 	    return (((xmlSchemaIDCPtr) item)->name);
1336 	case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1337 	    if (WXS_ATTRUSE_DECL(item) != NULL) {
1338 		return(xmlSchemaGetComponentName(
1339 		    WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1340 	    } else
1341 		return(NULL);
1342 	case XML_SCHEMA_EXTRA_QNAMEREF:
1343 	    return (((xmlSchemaQNameRefPtr) item)->name);
1344 	case XML_SCHEMA_TYPE_NOTATION:
1345 	    return (((xmlSchemaNotationPtr) item)->name);
1346 	default:
1347 	    /*
1348 	    * Other components cannot have names.
1349 	    */
1350 	    break;
1351     }
1352     return (NULL);
1353 }
1354 
1355 #define xmlSchemaGetQNameRefName(r) (WXS_QNAME_CAST (r))->name
1356 #define xmlSchemaGetQNameRefTargetNs(r) (WXS_QNAME_CAST (r))->targetNamespace
1357 /*
1358 static const xmlChar *
1359 xmlSchemaGetQNameRefName(void *ref)
1360 {
1361     return(((xmlSchemaQNameRefPtr) ref)->name);
1362 }
1363 
1364 static const xmlChar *
1365 xmlSchemaGetQNameRefTargetNs(void *ref)
1366 {
1367     return(((xmlSchemaQNameRefPtr) ref)->targetNamespace);
1368 }
1369 */
1370 
1371 static const xmlChar *
xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)1372 xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
1373 {
1374     switch (item->type) {
1375 	case XML_SCHEMA_TYPE_ELEMENT:
1376 	    return (((xmlSchemaElementPtr) item)->targetNamespace);
1377 	case XML_SCHEMA_TYPE_ATTRIBUTE:
1378 	    return (((xmlSchemaAttributePtr) item)->targetNamespace);
1379 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1380 	    return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
1381 	case XML_SCHEMA_TYPE_BASIC:
1382 	    return (BAD_CAST "http://www.w3.org/2001/XMLSchema");
1383 	case XML_SCHEMA_TYPE_SIMPLE:
1384 	case XML_SCHEMA_TYPE_COMPLEX:
1385 	    return (((xmlSchemaTypePtr) item)->targetNamespace);
1386 	case XML_SCHEMA_TYPE_GROUP:
1387 	    return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1388 	case XML_SCHEMA_TYPE_IDC_KEY:
1389 	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1390 	case XML_SCHEMA_TYPE_IDC_KEYREF:
1391 	    return (((xmlSchemaIDCPtr) item)->targetNamespace);
1392 	case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1393 	    if (WXS_ATTRUSE_DECL(item) != NULL) {
1394 		return(xmlSchemaGetComponentTargetNs(
1395 		    WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1396 	    }
1397 	    /* TODO: Will returning NULL break something? */
1398 	    break;
1399 	case XML_SCHEMA_EXTRA_QNAMEREF:
1400 	    return (((xmlSchemaQNameRefPtr) item)->targetNamespace);
1401 	case XML_SCHEMA_TYPE_NOTATION:
1402 	    return (((xmlSchemaNotationPtr) item)->targetNamespace);
1403 	default:
1404 	    /*
1405 	    * Other components cannot have names.
1406 	    */
1407 	    break;
1408     }
1409     return (NULL);
1410 }
1411 
1412 static const xmlChar*
xmlSchemaGetComponentQName(xmlChar ** buf,void * item)1413 xmlSchemaGetComponentQName(xmlChar **buf,
1414 			   void *item)
1415 {
1416     return (xmlSchemaFormatQName(buf,
1417 	xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1418 	xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1419 }
1420 
1421 static const xmlChar*
xmlSchemaGetComponentDesignation(xmlChar ** buf,void * item)1422 xmlSchemaGetComponentDesignation(xmlChar **buf, void *item)
1423 {
1424     xmlChar *str = NULL;
1425 
1426     *buf = xmlStrcat(*buf, WXS_ITEM_TYPE_NAME(item));
1427     *buf = xmlStrcat(*buf, BAD_CAST " '");
1428     *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str,
1429 	(xmlSchemaBasicItemPtr) item));
1430     *buf = xmlStrcat(*buf, BAD_CAST "'");
1431     FREE_AND_NULL(str);
1432     return(*buf);
1433 }
1434 
1435 static const xmlChar*
xmlSchemaGetIDCDesignation(xmlChar ** buf,xmlSchemaIDCPtr idc)1436 xmlSchemaGetIDCDesignation(xmlChar **buf, xmlSchemaIDCPtr idc)
1437 {
1438     return(xmlSchemaGetComponentDesignation(buf, idc));
1439 }
1440 
1441 /**
1442  * xmlSchemaWildcardPCToString:
1443  * @pc: the type of processContents
1444  *
1445  * Returns a string representation of the type of
1446  * processContents.
1447  */
1448 static const xmlChar *
xmlSchemaWildcardPCToString(int pc)1449 xmlSchemaWildcardPCToString(int pc)
1450 {
1451     switch (pc) {
1452 	case XML_SCHEMAS_ANY_SKIP:
1453 	    return (BAD_CAST "skip");
1454 	case XML_SCHEMAS_ANY_LAX:
1455 	    return (BAD_CAST "lax");
1456 	case XML_SCHEMAS_ANY_STRICT:
1457 	    return (BAD_CAST "strict");
1458 	default:
1459 	    return (BAD_CAST "invalid process contents");
1460     }
1461 }
1462 
1463 /**
1464  * xmlSchemaGetCanonValueWhtspExt:
1465  * @val: the precomputed value
1466  * @retValue: the returned value
1467  * @ws: the whitespace type of the value
1468  *
1469  * Get a the cononical representation of the value.
1470  * The caller has to free the returned retValue.
1471  *
1472  * Returns 0 if the value could be built and -1 in case of
1473  *         API errors or if the value type is not supported yet.
1474  */
1475 static int
xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,xmlSchemaWhitespaceValueType ws,xmlChar ** retValue)1476 xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
1477 			       xmlSchemaWhitespaceValueType ws,
1478 			       xmlChar **retValue)
1479 {
1480     int list;
1481     xmlSchemaValType valType;
1482     const xmlChar *value, *value2 = NULL;
1483 
1484 
1485     if ((retValue == NULL) || (val == NULL))
1486 	return (-1);
1487     list = xmlSchemaValueGetNext(val) ? 1 : 0;
1488     *retValue = NULL;
1489     do {
1490 	value = NULL;
1491 	valType = xmlSchemaGetValType(val);
1492 	switch (valType) {
1493 	    case XML_SCHEMAS_STRING:
1494 	    case XML_SCHEMAS_NORMSTRING:
1495 	    case XML_SCHEMAS_ANYSIMPLETYPE:
1496 		value = xmlSchemaValueGetAsString(val);
1497 		if (value != NULL) {
1498 		    if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1499 			value2 = xmlSchemaCollapseString(value);
1500 		    else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1501 			value2 = xmlSchemaWhiteSpaceReplace(value);
1502 		    if (value2 != NULL)
1503 			value = value2;
1504 		}
1505 		break;
1506 	    default:
1507 		if (xmlSchemaGetCanonValue(val, &value2) == -1) {
1508 		    if (value2 != NULL)
1509 			xmlFree((xmlChar *) value2);
1510 		    goto internal_error;
1511 		}
1512 		value = value2;
1513 	}
1514 	if (*retValue == NULL)
1515 	    if (value == NULL) {
1516 		if (! list)
1517 		    *retValue = xmlStrdup(BAD_CAST "");
1518 	    } else
1519 		*retValue = xmlStrdup(value);
1520 	else if (value != NULL) {
1521 	    /* List. */
1522 	    *retValue = xmlStrcat((xmlChar *) *retValue, BAD_CAST " ");
1523 	    *retValue = xmlStrcat((xmlChar *) *retValue, value);
1524 	}
1525 	FREE_AND_NULL(value2)
1526 	val = xmlSchemaValueGetNext(val);
1527     } while (val != NULL);
1528 
1529     return (0);
1530 internal_error:
1531     if (*retValue != NULL)
1532 	xmlFree((xmlChar *) (*retValue));
1533     if (value2 != NULL)
1534 	xmlFree((xmlChar *) value2);
1535     return (-1);
1536 }
1537 
1538 /**
1539  * xmlSchemaFormatItemForReport:
1540  * @buf: the string buffer
1541  * @itemDes: the designation of the item
1542  * @itemName: the name of the item
1543  * @item: the item as an object
1544  * @itemNode: the node of the item
1545  * @local: the local name
1546  * @parsing: if the function is used during the parse
1547  *
1548  * Returns a representation of the given item used
1549  * for error reports.
1550  *
1551  * The following order is used to build the resulting
1552  * designation if the arguments are not NULL:
1553  * 1a. If itemDes not NULL -> itemDes
1554  * 1b. If (itemDes not NULL) and (itemName not NULL)
1555  *     -> itemDes + itemName
1556  * 2. If the preceding was NULL and (item not NULL) -> item
1557  * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
1558  *
1559  * If the itemNode is an attribute node, the name of the attribute
1560  * will be appended to the result.
1561  *
1562  * Returns the formatted string and sets @buf to the resulting value.
1563  */
1564 static xmlChar*
xmlSchemaFormatItemForReport(xmlChar ** buf,const xmlChar * itemDes,xmlSchemaBasicItemPtr item,xmlNodePtr itemNode)1565 xmlSchemaFormatItemForReport(xmlChar **buf,
1566 		     const xmlChar *itemDes,
1567 		     xmlSchemaBasicItemPtr item,
1568 		     xmlNodePtr itemNode)
1569 {
1570     xmlChar *str = NULL;
1571     int named = 1;
1572 
1573     if (*buf != NULL) {
1574 	xmlFree(*buf);
1575 	*buf = NULL;
1576     }
1577 
1578     if (itemDes != NULL) {
1579 	*buf = xmlStrdup(itemDes);
1580     } else if (item != NULL) {
1581 	switch (item->type) {
1582 	case XML_SCHEMA_TYPE_BASIC: {
1583 	    xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1584 
1585 	    if (WXS_IS_ATOMIC(type))
1586 		*buf = xmlStrdup(BAD_CAST "atomic type 'xs:");
1587 	    else if (WXS_IS_LIST(type))
1588 		*buf = xmlStrdup(BAD_CAST "list type 'xs:");
1589 	    else if (WXS_IS_UNION(type))
1590 		*buf = xmlStrdup(BAD_CAST "union type 'xs:");
1591 	    else
1592 		*buf = xmlStrdup(BAD_CAST "simple type 'xs:");
1593 	    *buf = xmlStrcat(*buf, type->name);
1594 	    *buf = xmlStrcat(*buf, BAD_CAST "'");
1595 	    }
1596 	    break;
1597 	case XML_SCHEMA_TYPE_SIMPLE: {
1598 	    xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1599 
1600 	    if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1601 		*buf = xmlStrdup(BAD_CAST"");
1602 	    } else {
1603 		*buf = xmlStrdup(BAD_CAST "local ");
1604 	    }
1605 	    if (WXS_IS_ATOMIC(type))
1606 		*buf = xmlStrcat(*buf, BAD_CAST "atomic type");
1607 	    else if (WXS_IS_LIST(type))
1608 		*buf = xmlStrcat(*buf, BAD_CAST "list type");
1609 	    else if (WXS_IS_UNION(type))
1610 		*buf = xmlStrcat(*buf, BAD_CAST "union type");
1611 	    else
1612 		*buf = xmlStrcat(*buf, BAD_CAST "simple type");
1613 	    if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1614 		*buf = xmlStrcat(*buf, BAD_CAST " '");
1615 		*buf = xmlStrcat(*buf, type->name);
1616 		*buf = xmlStrcat(*buf, BAD_CAST "'");
1617 	    }
1618 	    }
1619 	    break;
1620 	case XML_SCHEMA_TYPE_COMPLEX: {
1621 	    xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1622 
1623 	    if (type->flags & XML_SCHEMAS_TYPE_GLOBAL)
1624 		*buf = xmlStrdup(BAD_CAST "");
1625 	    else
1626 		*buf = xmlStrdup(BAD_CAST "local ");
1627 	    *buf = xmlStrcat(*buf, BAD_CAST "complex type");
1628 	    if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1629 		*buf = xmlStrcat(*buf, BAD_CAST " '");
1630 		*buf = xmlStrcat(*buf, type->name);
1631 		*buf = xmlStrcat(*buf, BAD_CAST "'");
1632 	    }
1633 	    }
1634 	    break;
1635 	case XML_SCHEMA_TYPE_ATTRIBUTE_USE: {
1636 		xmlSchemaAttributeUsePtr ause;
1637 
1638 		ause = WXS_ATTR_USE_CAST item;
1639 		*buf = xmlStrdup(BAD_CAST "attribute use ");
1640 		if (WXS_ATTRUSE_DECL(ause) != NULL) {
1641 		    *buf = xmlStrcat(*buf, BAD_CAST "'");
1642 		    *buf = xmlStrcat(*buf,
1643 			xmlSchemaGetComponentQName(&str, WXS_ATTRUSE_DECL(ause)));
1644 		    FREE_AND_NULL(str)
1645 			*buf = xmlStrcat(*buf, BAD_CAST "'");
1646 		} else {
1647 		    *buf = xmlStrcat(*buf, BAD_CAST "(unknown)");
1648 		}
1649 	    }
1650 	    break;
1651 	case XML_SCHEMA_TYPE_ATTRIBUTE: {
1652 		xmlSchemaAttributePtr attr;
1653 
1654 		attr = (xmlSchemaAttributePtr) item;
1655 		*buf = xmlStrdup(BAD_CAST "attribute decl.");
1656 		*buf = xmlStrcat(*buf, BAD_CAST " '");
1657 		*buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1658 		    attr->targetNamespace, attr->name));
1659 		FREE_AND_NULL(str)
1660 		    *buf = xmlStrcat(*buf, BAD_CAST "'");
1661 	    }
1662 	    break;
1663 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1664 	    xmlSchemaGetComponentDesignation(buf, item);
1665 	    break;
1666 	case XML_SCHEMA_TYPE_ELEMENT: {
1667 		xmlSchemaElementPtr elem;
1668 
1669 		elem = (xmlSchemaElementPtr) item;
1670 		*buf = xmlStrdup(BAD_CAST "element decl.");
1671 		*buf = xmlStrcat(*buf, BAD_CAST " '");
1672 		*buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1673 		    elem->targetNamespace, elem->name));
1674 		*buf = xmlStrcat(*buf, BAD_CAST "'");
1675 	    }
1676 	    break;
1677 	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1678 	case XML_SCHEMA_TYPE_IDC_KEY:
1679 	case XML_SCHEMA_TYPE_IDC_KEYREF:
1680 	    if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1681 		*buf = xmlStrdup(BAD_CAST "unique '");
1682 	    else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1683 		*buf = xmlStrdup(BAD_CAST "key '");
1684 	    else
1685 		*buf = xmlStrdup(BAD_CAST "keyRef '");
1686 	    *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1687 	    *buf = xmlStrcat(*buf, BAD_CAST "'");
1688 	    break;
1689 	case XML_SCHEMA_TYPE_ANY:
1690 	case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1691 	    *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1692 		    ((xmlSchemaWildcardPtr) item)->processContents));
1693 	    *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1694 	    break;
1695 	case XML_SCHEMA_FACET_MININCLUSIVE:
1696 	case XML_SCHEMA_FACET_MINEXCLUSIVE:
1697 	case XML_SCHEMA_FACET_MAXINCLUSIVE:
1698 	case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1699 	case XML_SCHEMA_FACET_TOTALDIGITS:
1700 	case XML_SCHEMA_FACET_FRACTIONDIGITS:
1701 	case XML_SCHEMA_FACET_PATTERN:
1702 	case XML_SCHEMA_FACET_ENUMERATION:
1703 	case XML_SCHEMA_FACET_WHITESPACE:
1704 	case XML_SCHEMA_FACET_LENGTH:
1705 	case XML_SCHEMA_FACET_MAXLENGTH:
1706 	case XML_SCHEMA_FACET_MINLENGTH:
1707 	    *buf = xmlStrdup(BAD_CAST "facet '");
1708 	    *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1709 	    *buf = xmlStrcat(*buf, BAD_CAST "'");
1710 	    break;
1711 	case XML_SCHEMA_TYPE_GROUP: {
1712 		*buf = xmlStrdup(BAD_CAST "model group def.");
1713 		*buf = xmlStrcat(*buf, BAD_CAST " '");
1714 		*buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1715 		*buf = xmlStrcat(*buf, BAD_CAST "'");
1716 		FREE_AND_NULL(str)
1717 	    }
1718 	    break;
1719 	case XML_SCHEMA_TYPE_SEQUENCE:
1720 	case XML_SCHEMA_TYPE_CHOICE:
1721 	case XML_SCHEMA_TYPE_ALL:
1722 	case XML_SCHEMA_TYPE_PARTICLE:
1723 	    *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1724 	    break;
1725 	case XML_SCHEMA_TYPE_NOTATION: {
1726 		*buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1727 		*buf = xmlStrcat(*buf, BAD_CAST " '");
1728 		*buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1729 		*buf = xmlStrcat(*buf, BAD_CAST "'");
1730 		FREE_AND_NULL(str);
1731 	    }
1732 	default:
1733 	    named = 0;
1734 	}
1735     } else
1736 	named = 0;
1737 
1738     if ((named == 0) && (itemNode != NULL)) {
1739 	xmlNodePtr elem;
1740 
1741 	if (itemNode->type == XML_ATTRIBUTE_NODE)
1742 	    elem = itemNode->parent;
1743 	else
1744 	    elem = itemNode;
1745 	*buf = xmlStrdup(BAD_CAST "Element '");
1746 	if (elem->ns != NULL) {
1747 	    *buf = xmlStrcat(*buf,
1748 		xmlSchemaFormatQName(&str, elem->ns->href, elem->name));
1749 	    FREE_AND_NULL(str)
1750 	} else
1751 	    *buf = xmlStrcat(*buf, elem->name);
1752 	*buf = xmlStrcat(*buf, BAD_CAST "'");
1753 
1754     }
1755     if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1756 	*buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1757 	if (itemNode->ns != NULL) {
1758 	    *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1759 		itemNode->ns->href, itemNode->name));
1760 	    FREE_AND_NULL(str)
1761 	} else
1762 	    *buf = xmlStrcat(*buf, itemNode->name);
1763 	*buf = xmlStrcat(*buf, BAD_CAST "'");
1764     }
1765     FREE_AND_NULL(str)
1766 
1767     return (*buf);
1768 }
1769 
1770 /**
1771  * xmlSchemaFormatFacetEnumSet:
1772  * @buf: the string buffer
1773  * @type: the type holding the enumeration facets
1774  *
1775  * Builds a string consisting of all enumeration elements.
1776  *
1777  * Returns a string of all enumeration elements.
1778  */
1779 static const xmlChar *
xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,xmlChar ** buf,xmlSchemaTypePtr type)1780 xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,
1781 			    xmlChar **buf, xmlSchemaTypePtr type)
1782 {
1783     xmlSchemaFacetPtr facet;
1784     xmlSchemaWhitespaceValueType ws;
1785     xmlChar *value = NULL;
1786     int res, found = 0;
1787 
1788     if (*buf != NULL)
1789 	xmlFree(*buf);
1790     *buf = NULL;
1791 
1792     do {
1793 	/*
1794 	* Use the whitespace type of the base type.
1795 	*/
1796 	ws = xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
1797 	for (facet = type->facets; facet != NULL; facet = facet->next) {
1798 	    if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1799 		continue;
1800 	    found = 1;
1801 	    res = xmlSchemaGetCanonValueWhtspExt(facet->val,
1802 		ws, &value);
1803 	    if (res == -1) {
1804 		xmlSchemaInternalErr(actxt,
1805 		    "xmlSchemaFormatFacetEnumSet",
1806 		    "compute the canonical lexical representation");
1807 		if (*buf != NULL)
1808 		    xmlFree(*buf);
1809 		*buf = NULL;
1810 		return (NULL);
1811 	    }
1812 	    if (*buf == NULL)
1813 		*buf = xmlStrdup(BAD_CAST "'");
1814 	    else
1815 		*buf = xmlStrcat(*buf, BAD_CAST ", '");
1816 	    *buf = xmlStrcat(*buf, BAD_CAST value);
1817 	    *buf = xmlStrcat(*buf, BAD_CAST "'");
1818 	    if (value != NULL) {
1819 		xmlFree((xmlChar *)value);
1820 		value = NULL;
1821 	    }
1822 	}
1823 	/*
1824 	* The enumeration facet of a type restricts the enumeration
1825 	* facet of the ancestor type; i.e., such restricted enumerations
1826 	* do not belong to the set of the given type. Thus we break
1827 	* on the first found enumeration.
1828 	*/
1829 	if (found)
1830 	    break;
1831 	type = type->baseType;
1832     } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
1833 
1834     return ((const xmlChar *) *buf);
1835 }
1836 
1837 /************************************************************************
1838  *									*
1839  * 			Error functions				        *
1840  *									*
1841  ************************************************************************/
1842 
1843 #if 0
1844 static void
1845 xmlSchemaErrMemory(const char *msg)
1846 {
1847     __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1848                      msg);
1849 }
1850 #endif
1851 
1852 static void
xmlSchemaPSimpleErr(const char * msg)1853 xmlSchemaPSimpleErr(const char *msg)
1854 {
1855     __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1856                      msg);
1857 }
1858 
1859 /**
1860  * xmlSchemaPErrMemory:
1861  * @node: a context node
1862  * @extra:  extra informations
1863  *
1864  * Handle an out of memory condition
1865  */
1866 static void
xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,const char * extra,xmlNodePtr node)1867 xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
1868                     const char *extra, xmlNodePtr node)
1869 {
1870     if (ctxt != NULL)
1871         ctxt->nberrors++;
1872     __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
1873                      extra);
1874 }
1875 
1876 /**
1877  * xmlSchemaPErr:
1878  * @ctxt: the parsing context
1879  * @node: the context node
1880  * @error: the error code
1881  * @msg: the error message
1882  * @str1: extra data
1883  * @str2: extra data
1884  *
1885  * Handle a parser error
1886  */
1887 static void
xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int error,const char * msg,const xmlChar * str1,const xmlChar * str2)1888 xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1889               const char *msg, const xmlChar * str1, const xmlChar * str2)
1890 {
1891     xmlGenericErrorFunc channel = NULL;
1892     xmlStructuredErrorFunc schannel = NULL;
1893     void *data = NULL;
1894 
1895     if (ctxt != NULL) {
1896         ctxt->nberrors++;
1897 	ctxt->err = error;
1898         channel = ctxt->error;
1899         data = ctxt->errCtxt;
1900 	schannel = ctxt->serror;
1901     }
1902     __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1903                     error, XML_ERR_ERROR, NULL, 0,
1904                     (const char *) str1, (const char *) str2, NULL, 0, 0,
1905                     msg, str1, str2);
1906 }
1907 
1908 /**
1909  * xmlSchemaPErr2:
1910  * @ctxt: the parsing context
1911  * @node: the context node
1912  * @node: the current child
1913  * @error: the error code
1914  * @msg: the error message
1915  * @str1: extra data
1916  * @str2: extra data
1917  *
1918  * Handle a parser error
1919  */
1920 static void
xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,xmlNodePtr child,int error,const char * msg,const xmlChar * str1,const xmlChar * str2)1921 xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1922                xmlNodePtr child, int error,
1923                const char *msg, const xmlChar * str1, const xmlChar * str2)
1924 {
1925     if (child != NULL)
1926         xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
1927     else
1928         xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
1929 }
1930 
1931 
1932 /**
1933  * xmlSchemaPErrExt:
1934  * @ctxt: the parsing context
1935  * @node: the context node
1936  * @error: the error code
1937  * @strData1: extra data
1938  * @strData2: extra data
1939  * @strData3: extra data
1940  * @msg: the message
1941  * @str1:  extra parameter for the message display
1942  * @str2:  extra parameter for the message display
1943  * @str3:  extra parameter for the message display
1944  * @str4:  extra parameter for the message display
1945  * @str5:  extra parameter for the message display
1946  *
1947  * Handle a parser error
1948  */
1949 static void
xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int error,const xmlChar * strData1,const xmlChar * strData2,const xmlChar * strData3,const char * msg,const xmlChar * str1,const xmlChar * str2,const xmlChar * str3,const xmlChar * str4,const xmlChar * str5)1950 xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1951 		const xmlChar * strData1, const xmlChar * strData2,
1952 		const xmlChar * strData3, const char *msg, const xmlChar * str1,
1953 		const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
1954 		const xmlChar * str5)
1955 {
1956 
1957     xmlGenericErrorFunc channel = NULL;
1958     xmlStructuredErrorFunc schannel = NULL;
1959     void *data = NULL;
1960 
1961     if (ctxt != NULL) {
1962         ctxt->nberrors++;
1963 	ctxt->err = error;
1964         channel = ctxt->error;
1965         data = ctxt->errCtxt;
1966 	schannel = ctxt->serror;
1967     }
1968     __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1969                     error, XML_ERR_ERROR, NULL, 0,
1970                     (const char *) strData1, (const char *) strData2,
1971 		    (const char *) strData3, 0, 0, msg, str1, str2,
1972 		    str3, str4, str5);
1973 }
1974 
1975 /************************************************************************
1976  *									*
1977  * 			Allround error functions			*
1978  *									*
1979  ************************************************************************/
1980 
1981 /**
1982  * xmlSchemaVTypeErrMemory:
1983  * @node: a context node
1984  * @extra:  extra informations
1985  *
1986  * Handle an out of memory condition
1987  */
1988 static void
xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,const char * extra,xmlNodePtr node)1989 xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
1990                     const char *extra, xmlNodePtr node)
1991 {
1992     if (ctxt != NULL) {
1993         ctxt->nberrors++;
1994         ctxt->err = XML_SCHEMAV_INTERNAL;
1995     }
1996     __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
1997                      extra);
1998 }
1999 
2000 static void
xmlSchemaPSimpleInternalErr(xmlNodePtr node,const char * msg,const xmlChar * str)2001 xmlSchemaPSimpleInternalErr(xmlNodePtr node,
2002 			    const char *msg, const xmlChar *str)
2003 {
2004      __xmlSimpleError(XML_FROM_SCHEMASP, XML_SCHEMAP_INTERNAL, node,
2005 	 msg, (const char *) str);
2006 }
2007 
2008 #define WXS_ERROR_TYPE_ERROR 1
2009 #define WXS_ERROR_TYPE_WARNING 2
2010 /**
2011  * xmlSchemaErr3:
2012  * @ctxt: the validation context
2013  * @node: the context node
2014  * @error: the error code
2015  * @msg: the error message
2016  * @str1: extra data
2017  * @str2: extra data
2018  * @str3: extra data
2019  *
2020  * Handle a validation error
2021  */
2022 static void
xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt,xmlErrorLevel errorLevel,int error,xmlNodePtr node,int line,const char * msg,const xmlChar * str1,const xmlChar * str2,const xmlChar * str3,const xmlChar * str4)2023 xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt,
2024 		  xmlErrorLevel errorLevel,
2025 		  int error, xmlNodePtr node, int line, const char *msg,
2026 		  const xmlChar *str1, const xmlChar *str2,
2027 		  const xmlChar *str3, const xmlChar *str4)
2028 {
2029     xmlStructuredErrorFunc schannel = NULL;
2030     xmlGenericErrorFunc channel = NULL;
2031     void *data = NULL;
2032 
2033     if (ctxt != NULL) {
2034 	if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2035 	    xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
2036 	    const char *file = NULL;
2037 	    if (errorLevel != XML_ERR_WARNING) {
2038 		vctxt->nberrors++;
2039 		vctxt->err = error;
2040 		channel = vctxt->error;
2041 	    } else {
2042 		channel = vctxt->warning;
2043 	    }
2044 	    schannel = vctxt->serror;
2045 	    data = vctxt->errCtxt;
2046 
2047 	    /*
2048 	    * Error node. If we specify a line number, then
2049 	    * do not channel any node to the error function.
2050 	    */
2051 	    if (line == 0) {
2052 		if ((node == NULL) &&
2053 		    (vctxt->depth >= 0) &&
2054 		    (vctxt->inode != NULL)) {
2055 		    node = vctxt->inode->node;
2056 		}
2057 		/*
2058 		* Get filename and line if no node-tree.
2059 		*/
2060 		if ((node == NULL) &&
2061 		    (vctxt->parserCtxt != NULL) &&
2062 		    (vctxt->parserCtxt->input != NULL)) {
2063 		    file = vctxt->parserCtxt->input->filename;
2064 		    line = vctxt->parserCtxt->input->line;
2065 		}
2066 	    } else {
2067 		/*
2068 		* Override the given node's (if any) position
2069 		* and channel only the given line number.
2070 		*/
2071 		node = NULL;
2072 		/*
2073 		* Get filename.
2074 		*/
2075 		if (vctxt->doc != NULL)
2076 		    file = (const char *) vctxt->doc->URL;
2077 		else if ((vctxt->parserCtxt != NULL) &&
2078 		    (vctxt->parserCtxt->input != NULL))
2079 		    file = vctxt->parserCtxt->input->filename;
2080 	    }
2081 	    __xmlRaiseError(schannel, channel, data, ctxt,
2082 		node, XML_FROM_SCHEMASV,
2083 		error, errorLevel, file, line,
2084 		(const char *) str1, (const char *) str2,
2085 		(const char *) str3, 0, 0, msg, str1, str2, str3, str4);
2086 
2087 	} else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
2088 	    xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
2089 	    if (errorLevel != XML_ERR_WARNING) {
2090 		pctxt->nberrors++;
2091 		pctxt->err = error;
2092 		channel = pctxt->error;
2093 	    } else {
2094 		channel = pctxt->warning;
2095 	    }
2096 	    schannel = pctxt->serror;
2097 	    data = pctxt->errCtxt;
2098 	    __xmlRaiseError(schannel, channel, data, ctxt,
2099 		node, XML_FROM_SCHEMASP, error,
2100 		errorLevel, NULL, 0,
2101 		(const char *) str1, (const char *) str2,
2102 		(const char *) str3, 0, 0, msg, str1, str2, str3, str4);
2103 	} else {
2104 	    TODO
2105 	}
2106     }
2107 }
2108 
2109 /**
2110  * xmlSchemaErr3:
2111  * @ctxt: the validation context
2112  * @node: the context node
2113  * @error: the error code
2114  * @msg: the error message
2115  * @str1: extra data
2116  * @str2: extra data
2117  * @str3: extra data
2118  *
2119  * Handle a validation error
2120  */
2121 static void
xmlSchemaErr3(xmlSchemaAbstractCtxtPtr actxt,int error,xmlNodePtr node,const char * msg,const xmlChar * str1,const xmlChar * str2,const xmlChar * str3)2122 xmlSchemaErr3(xmlSchemaAbstractCtxtPtr actxt,
2123 	      int error, xmlNodePtr node, const char *msg,
2124 	      const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
2125 {
2126     xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2127 	msg, str1, str2, str3, NULL);
2128 }
2129 
2130 static void
xmlSchemaErr4(xmlSchemaAbstractCtxtPtr actxt,int error,xmlNodePtr node,const char * msg,const xmlChar * str1,const xmlChar * str2,const xmlChar * str3,const xmlChar * str4)2131 xmlSchemaErr4(xmlSchemaAbstractCtxtPtr actxt,
2132 	      int error, xmlNodePtr node, const char *msg,
2133 	      const xmlChar *str1, const xmlChar *str2,
2134 	      const xmlChar *str3, const xmlChar *str4)
2135 {
2136     xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2137 	msg, str1, str2, str3, str4);
2138 }
2139 
2140 static void
xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,int error,xmlNodePtr node,const char * msg,const xmlChar * str1,const xmlChar * str2)2141 xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
2142 	     int error, xmlNodePtr node, const char *msg,
2143 	     const xmlChar *str1, const xmlChar *str2)
2144 {
2145     xmlSchemaErr4(actxt, error, node, msg, str1, str2, NULL, NULL);
2146 }
2147 
2148 static xmlChar *
xmlSchemaFormatNodeForError(xmlChar ** msg,xmlSchemaAbstractCtxtPtr actxt,xmlNodePtr node)2149 xmlSchemaFormatNodeForError(xmlChar ** msg,
2150 			    xmlSchemaAbstractCtxtPtr actxt,
2151 			    xmlNodePtr node)
2152 {
2153     xmlChar *str = NULL;
2154 
2155     *msg = NULL;
2156     if ((node != NULL) &&
2157 	(node->type != XML_ELEMENT_NODE) &&
2158 	(node->type != XML_ATTRIBUTE_NODE))
2159     {
2160 	/*
2161 	* Don't try to format other nodes than element and
2162 	* attribute nodes.
2163 	* Play save and return an empty string.
2164 	*/
2165 	*msg = xmlStrdup(BAD_CAST "");
2166 	return(*msg);
2167     }
2168     if (node != NULL) {
2169 	/*
2170 	* Work on tree nodes.
2171 	*/
2172 	if (node->type == XML_ATTRIBUTE_NODE) {
2173 	    xmlNodePtr elem = node->parent;
2174 
2175 	    *msg = xmlStrdup(BAD_CAST "Element '");
2176 	    if (elem->ns != NULL)
2177 		*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2178 		    elem->ns->href, elem->name));
2179 	    else
2180 		*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2181 		    NULL, elem->name));
2182 	    FREE_AND_NULL(str);
2183 	    *msg = xmlStrcat(*msg, BAD_CAST "', ");
2184 	    *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2185 	} else {
2186 	    *msg = xmlStrdup(BAD_CAST "Element '");
2187 	}
2188 	if (node->ns != NULL)
2189 	    *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2190 	    node->ns->href, node->name));
2191 	else
2192 	    *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2193 	    NULL, node->name));
2194 	FREE_AND_NULL(str);
2195 	*msg = xmlStrcat(*msg, BAD_CAST "': ");
2196     } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2197 	xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
2198 	/*
2199 	* Work on node infos.
2200 	*/
2201 	if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
2202 	    xmlSchemaNodeInfoPtr ielem =
2203 		vctxt->elemInfos[vctxt->depth];
2204 
2205 	    *msg = xmlStrdup(BAD_CAST "Element '");
2206 	    *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2207 		ielem->nsName, ielem->localName));
2208 	    FREE_AND_NULL(str);
2209 	    *msg = xmlStrcat(*msg, BAD_CAST "', ");
2210 	    *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2211 	} else {
2212 	    *msg = xmlStrdup(BAD_CAST "Element '");
2213 	}
2214 	*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2215 	    vctxt->inode->nsName, vctxt->inode->localName));
2216 	FREE_AND_NULL(str);
2217 	*msg = xmlStrcat(*msg, BAD_CAST "': ");
2218     } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
2219 	/*
2220 	* Hmm, no node while parsing?
2221 	* Return an empty string, in case NULL will break something.
2222 	*/
2223 	*msg = xmlStrdup(BAD_CAST "");
2224     } else {
2225 	TODO
2226 	return (NULL);
2227     }
2228     /*
2229     * VAL TODO: The output of the given schema component is currently
2230     * disabled.
2231     */
2232 #if 0
2233     if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
2234 	*msg = xmlStrcat(*msg, BAD_CAST " [");
2235 	*msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
2236 	    NULL, type, NULL, 0));
2237 	FREE_AND_NULL(str)
2238 	*msg = xmlStrcat(*msg, BAD_CAST "]");
2239     }
2240 #endif
2241     return (*msg);
2242 }
2243 
2244 static void
xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,const char * funcName,const char * message,const xmlChar * str1,const xmlChar * str2)2245 xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,
2246 		     const char *funcName,
2247 		     const char *message,
2248 		     const xmlChar *str1,
2249 		     const xmlChar *str2)
2250 {
2251     xmlChar *msg = NULL;
2252 
2253     if (actxt == NULL)
2254         return;
2255     msg = xmlStrdup(BAD_CAST "Internal error: ");
2256     msg = xmlStrcat(msg, BAD_CAST funcName);
2257     msg = xmlStrcat(msg, BAD_CAST ", ");
2258     msg = xmlStrcat(msg, BAD_CAST message);
2259     msg = xmlStrcat(msg, BAD_CAST ".\n");
2260 
2261     if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
2262 	xmlSchemaErr(actxt, XML_SCHEMAV_INTERNAL, NULL,
2263 	    (const char *) msg, str1, str2);
2264 
2265     else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
2266 	xmlSchemaErr(actxt, XML_SCHEMAP_INTERNAL, NULL,
2267 	    (const char *) msg, str1, str2);
2268 
2269     FREE_AND_NULL(msg)
2270 }
2271 
2272 static void
xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,const char * funcName,const char * message)2273 xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
2274 		     const char *funcName,
2275 		     const char *message)
2276 {
2277     xmlSchemaInternalErr2(actxt, funcName, message, NULL, NULL);
2278 }
2279 
2280 #if 0
2281 static void
2282 xmlSchemaPInternalErr(xmlSchemaParserCtxtPtr pctxt,
2283 		     const char *funcName,
2284 		     const char *message,
2285 		     const xmlChar *str1,
2286 		     const xmlChar *str2)
2287 {
2288     xmlSchemaInternalErr2(ACTXT_CAST pctxt, funcName, message,
2289 	str1, str2);
2290 }
2291 #endif
2292 
2293 static void
xmlSchemaCustomErr4(xmlSchemaAbstractCtxtPtr actxt,xmlParserErrors error,xmlNodePtr node,xmlSchemaBasicItemPtr item,const char * message,const xmlChar * str1,const xmlChar * str2,const xmlChar * str3,const xmlChar * str4)2294 xmlSchemaCustomErr4(xmlSchemaAbstractCtxtPtr actxt,
2295 		   xmlParserErrors error,
2296 		   xmlNodePtr node,
2297 		   xmlSchemaBasicItemPtr item,
2298 		   const char *message,
2299 		   const xmlChar *str1, const xmlChar *str2,
2300 		   const xmlChar *str3, const xmlChar *str4)
2301 {
2302     xmlChar *msg = NULL;
2303 
2304     if ((node == NULL) && (item != NULL) &&
2305 	(actxt->type == XML_SCHEMA_CTXT_PARSER)) {
2306 	node = WXS_ITEM_NODE(item);
2307 	xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2308 	msg = xmlStrcat(msg, BAD_CAST ": ");
2309     } else
2310 	xmlSchemaFormatNodeForError(&msg, actxt, node);
2311     msg = xmlStrcat(msg, (const xmlChar *) message);
2312     msg = xmlStrcat(msg, BAD_CAST ".\n");
2313     xmlSchemaErr4(actxt, error, node,
2314 	(const char *) msg, str1, str2, str3, str4);
2315     FREE_AND_NULL(msg)
2316 }
2317 
2318 static void
xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,xmlParserErrors error,xmlNodePtr node,xmlSchemaBasicItemPtr item,const char * message,const xmlChar * str1,const xmlChar * str2)2319 xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
2320 		   xmlParserErrors error,
2321 		   xmlNodePtr node,
2322 		   xmlSchemaBasicItemPtr item,
2323 		   const char *message,
2324 		   const xmlChar *str1,
2325 		   const xmlChar *str2)
2326 {
2327     xmlSchemaCustomErr4(actxt, error, node, item,
2328 	message, str1, str2, NULL, NULL);
2329 }
2330 
2331 
2332 
2333 static void
xmlSchemaCustomWarning(xmlSchemaAbstractCtxtPtr actxt,xmlParserErrors error,xmlNodePtr node,xmlSchemaTypePtr type ATTRIBUTE_UNUSED,const char * message,const xmlChar * str1,const xmlChar * str2,const xmlChar * str3)2334 xmlSchemaCustomWarning(xmlSchemaAbstractCtxtPtr actxt,
2335 		   xmlParserErrors error,
2336 		   xmlNodePtr node,
2337 		   xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2338 		   const char *message,
2339 		   const xmlChar *str1,
2340 		   const xmlChar *str2,
2341 		   const xmlChar *str3)
2342 {
2343     xmlChar *msg = NULL;
2344 
2345     xmlSchemaFormatNodeForError(&msg, actxt, node);
2346     msg = xmlStrcat(msg, (const xmlChar *) message);
2347     msg = xmlStrcat(msg, BAD_CAST ".\n");
2348 
2349     /* URGENT TODO: Set the error code to something sane. */
2350     xmlSchemaErr4Line(actxt, XML_ERR_WARNING, error, node, 0,
2351 	(const char *) msg, str1, str2, str3, NULL);
2352 
2353     FREE_AND_NULL(msg)
2354 }
2355 
2356 
2357 
2358 static void
xmlSchemaKeyrefErr(xmlSchemaValidCtxtPtr vctxt,xmlParserErrors error,xmlSchemaPSVIIDCNodePtr idcNode,xmlSchemaTypePtr type ATTRIBUTE_UNUSED,const char * message,const xmlChar * str1,const xmlChar * str2)2359 xmlSchemaKeyrefErr(xmlSchemaValidCtxtPtr vctxt,
2360 		   xmlParserErrors error,
2361 		   xmlSchemaPSVIIDCNodePtr idcNode,
2362 		   xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2363 		   const char *message,
2364 		   const xmlChar *str1,
2365 		   const xmlChar *str2)
2366 {
2367     xmlChar *msg = NULL, *qname = NULL;
2368 
2369     msg = xmlStrdup(BAD_CAST "Element '%s': ");
2370     msg = xmlStrcat(msg, (const xmlChar *) message);
2371     msg = xmlStrcat(msg, BAD_CAST ".\n");
2372     xmlSchemaErr4Line(ACTXT_CAST vctxt, XML_ERR_ERROR,
2373 	error, NULL, idcNode->nodeLine, (const char *) msg,
2374 	xmlSchemaFormatQName(&qname,
2375 	    vctxt->nodeQNames->items[idcNode->nodeQNameID +1],
2376 	    vctxt->nodeQNames->items[idcNode->nodeQNameID]),
2377 	str1, str2, NULL);
2378     FREE_AND_NULL(qname);
2379     FREE_AND_NULL(msg);
2380 }
2381 
2382 static int
xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,xmlNodePtr node)2383 xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
2384 			   xmlNodePtr node)
2385 {
2386     if (node != NULL)
2387 	return (node->type);
2388     if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
2389 	(((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
2390 	return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
2391     return (-1);
2392 }
2393 
2394 static int
xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)2395 xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
2396 {
2397     switch (item->type) {
2398 	case XML_SCHEMA_TYPE_COMPLEX:
2399 	case XML_SCHEMA_TYPE_SIMPLE:
2400 	    if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2401 		return(1);
2402 	    break;
2403 	case XML_SCHEMA_TYPE_GROUP:
2404 	    return (1);
2405 	case XML_SCHEMA_TYPE_ELEMENT:
2406 	    if ( ((xmlSchemaElementPtr) item)->flags &
2407 		XML_SCHEMAS_ELEM_GLOBAL)
2408 		return(1);
2409 	    break;
2410 	case XML_SCHEMA_TYPE_ATTRIBUTE:
2411 	    if ( ((xmlSchemaAttributePtr) item)->flags &
2412 		XML_SCHEMAS_ATTR_GLOBAL)
2413 		return(1);
2414 	    break;
2415 	/* Note that attribute groups are always global. */
2416 	default:
2417 	    return(1);
2418     }
2419     return (0);
2420 }
2421 
2422 static void
xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,xmlParserErrors error,xmlNodePtr node,const xmlChar * value,xmlSchemaTypePtr type,int displayValue)2423 xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2424 		       xmlParserErrors error,
2425 		       xmlNodePtr node,
2426 		       const xmlChar *value,
2427 		       xmlSchemaTypePtr type,
2428 		       int displayValue)
2429 {
2430     xmlChar *msg = NULL;
2431 
2432     xmlSchemaFormatNodeForError(&msg, actxt, node);
2433 
2434     if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2435 	    XML_ATTRIBUTE_NODE))
2436 	msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2437     else
2438 	msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
2439 	    "value of ");
2440 
2441     if (! xmlSchemaIsGlobalItem(type))
2442 	msg = xmlStrcat(msg, BAD_CAST "the local ");
2443     else
2444 	msg = xmlStrcat(msg, BAD_CAST "the ");
2445 
2446     if (WXS_IS_ATOMIC(type))
2447 	msg = xmlStrcat(msg, BAD_CAST "atomic type");
2448     else if (WXS_IS_LIST(type))
2449 	msg = xmlStrcat(msg, BAD_CAST "list type");
2450     else if (WXS_IS_UNION(type))
2451 	msg = xmlStrcat(msg, BAD_CAST "union type");
2452 
2453     if (xmlSchemaIsGlobalItem(type)) {
2454 	xmlChar *str = NULL;
2455 	msg = xmlStrcat(msg, BAD_CAST " '");
2456 	if (type->builtInType != 0) {
2457 	    msg = xmlStrcat(msg, BAD_CAST "xs:");
2458 	    msg = xmlStrcat(msg, type->name);
2459 	} else
2460 	    msg = xmlStrcat(msg,
2461 		xmlSchemaFormatQName(&str,
2462 		    type->targetNamespace, type->name));
2463 	msg = xmlStrcat(msg, BAD_CAST "'");
2464 	FREE_AND_NULL(str);
2465     }
2466     msg = xmlStrcat(msg, BAD_CAST ".\n");
2467     if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2468 	    XML_ATTRIBUTE_NODE))
2469 	xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2470     else
2471 	xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2472     FREE_AND_NULL(msg)
2473 }
2474 
2475 static const xmlChar *
xmlSchemaFormatErrorNodeQName(xmlChar ** str,xmlSchemaNodeInfoPtr ni,xmlNodePtr node)2476 xmlSchemaFormatErrorNodeQName(xmlChar ** str,
2477 			      xmlSchemaNodeInfoPtr ni,
2478 			      xmlNodePtr node)
2479 {
2480     if (node != NULL) {
2481 	if (node->ns != NULL)
2482 	    return (xmlSchemaFormatQName(str, node->ns->href, node->name));
2483 	else
2484 	    return (xmlSchemaFormatQName(str, NULL, node->name));
2485     } else if (ni != NULL)
2486 	return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
2487     return (NULL);
2488 }
2489 
2490 static void
xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,xmlParserErrors error,xmlSchemaAttrInfoPtr ni,xmlNodePtr node)2491 xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
2492 			xmlParserErrors error,
2493 			xmlSchemaAttrInfoPtr ni,
2494 			xmlNodePtr node)
2495 {
2496     xmlChar *msg = NULL, *str = NULL;
2497 
2498     xmlSchemaFormatNodeForError(&msg, actxt, node);
2499     msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
2500     xmlSchemaErr(actxt, error, node, (const char *) msg,
2501 	xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
2502 	NULL);
2503     FREE_AND_NULL(str)
2504     FREE_AND_NULL(msg)
2505 }
2506 
2507 static void
xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,xmlParserErrors error,xmlNodePtr node,xmlSchemaTypePtr type ATTRIBUTE_UNUSED,const char * message,int nbval,int nbneg,xmlChar ** values)2508 xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2509 		        xmlParserErrors error,
2510 		        xmlNodePtr node,
2511 			xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2512 			const char *message,
2513 			int nbval,
2514 			int nbneg,
2515 			xmlChar **values)
2516 {
2517     xmlChar *str = NULL, *msg = NULL;
2518     xmlChar *localName, *nsName;
2519     const xmlChar *cur, *end;
2520     int i;
2521 
2522     xmlSchemaFormatNodeForError(&msg, actxt, node);
2523     msg = xmlStrcat(msg, (const xmlChar *) message);
2524     msg = xmlStrcat(msg, BAD_CAST ".");
2525     /*
2526     * Note that is does not make sense to report that we have a
2527     * wildcard here, since the wildcard might be unfolded into
2528     * multiple transitions.
2529     */
2530     if (nbval + nbneg > 0) {
2531 	if (nbval + nbneg > 1) {
2532 	    str = xmlStrdup(BAD_CAST " Expected is one of ( ");
2533 	} else
2534 	    str = xmlStrdup(BAD_CAST " Expected is ( ");
2535 	nsName = NULL;
2536 
2537 	for (i = 0; i < nbval + nbneg; i++) {
2538 	    cur = values[i];
2539 	    if (cur == NULL)
2540 	        continue;
2541 	    if ((cur[0] == 'n') && (cur[1] == 'o') && (cur[2] == 't') &&
2542 	        (cur[3] == ' ')) {
2543 		cur += 4;
2544 		str = xmlStrcat(str, BAD_CAST "##other");
2545 	    }
2546 	    /*
2547 	    * Get the local name.
2548 	    */
2549 	    localName = NULL;
2550 
2551 	    end = cur;
2552 	    if (*end == '*') {
2553 		localName = xmlStrdup(BAD_CAST "*");
2554 		end++;
2555 	    } else {
2556 		while ((*end != 0) && (*end != '|'))
2557 		    end++;
2558 		localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
2559 	    }
2560 	    if (*end != 0) {
2561 		end++;
2562 		/*
2563 		* Skip "*|*" if they come with negated expressions, since
2564 		* they represent the same negated wildcard.
2565 		*/
2566 		if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
2567 		    /*
2568 		    * Get the namespace name.
2569 		    */
2570 		    cur = end;
2571 		    if (*end == '*') {
2572 			nsName = xmlStrdup(BAD_CAST "{*}");
2573 		    } else {
2574 			while (*end != 0)
2575 			    end++;
2576 
2577 			if (i >= nbval)
2578 			    nsName = xmlStrdup(BAD_CAST "{##other:");
2579 			else
2580 			    nsName = xmlStrdup(BAD_CAST "{");
2581 
2582 			nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
2583 			nsName = xmlStrcat(nsName, BAD_CAST "}");
2584 		    }
2585 		    str = xmlStrcat(str, BAD_CAST nsName);
2586 		    FREE_AND_NULL(nsName)
2587 		} else {
2588 		    FREE_AND_NULL(localName);
2589 		    continue;
2590 		}
2591 	    }
2592 	    str = xmlStrcat(str, BAD_CAST localName);
2593 	    FREE_AND_NULL(localName);
2594 
2595 	    if (i < nbval + nbneg -1)
2596 		str = xmlStrcat(str, BAD_CAST ", ");
2597 	}
2598 	str = xmlStrcat(str, BAD_CAST " ).\n");
2599 	msg = xmlStrcat(msg, BAD_CAST str);
2600 	FREE_AND_NULL(str)
2601     } else
2602       msg = xmlStrcat(msg, BAD_CAST "\n");
2603     xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2604     xmlFree(msg);
2605 }
2606 
2607 static void
xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,xmlParserErrors error,xmlNodePtr node,const xmlChar * value,unsigned long length,xmlSchemaTypePtr type,xmlSchemaFacetPtr facet,const char * message,const xmlChar * str1,const xmlChar * str2)2608 xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
2609 		  xmlParserErrors error,
2610 		  xmlNodePtr node,
2611 		  const xmlChar *value,
2612 		  unsigned long length,
2613 		  xmlSchemaTypePtr type,
2614 		  xmlSchemaFacetPtr facet,
2615 		  const char *message,
2616 		  const xmlChar *str1,
2617 		  const xmlChar *str2)
2618 {
2619     xmlChar *str = NULL, *msg = NULL;
2620     xmlSchemaTypeType facetType;
2621     int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
2622 
2623     xmlSchemaFormatNodeForError(&msg, actxt, node);
2624     if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
2625 	facetType = XML_SCHEMA_FACET_ENUMERATION;
2626 	/*
2627 	* If enumerations are validated, one must not expect the
2628 	* facet to be given.
2629 	*/
2630     } else
2631 	facetType = facet->type;
2632     msg = xmlStrcat(msg, BAD_CAST "[");
2633     msg = xmlStrcat(msg, BAD_CAST "facet '");
2634     msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
2635     msg = xmlStrcat(msg, BAD_CAST "'] ");
2636     if (message == NULL) {
2637 	/*
2638 	* Use a default message.
2639 	*/
2640 	if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
2641 	    (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
2642 	    (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
2643 
2644 	    char len[25], actLen[25];
2645 
2646 	    /* FIXME, TODO: What is the max expected string length of the
2647 	    * this value?
2648 	    */
2649 	    if (nodeType == XML_ATTRIBUTE_NODE)
2650 		msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
2651 	    else
2652 		msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
2653 
2654 	    snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
2655 	    snprintf(actLen, 24, "%lu", length);
2656 
2657 	    if (facetType == XML_SCHEMA_FACET_LENGTH)
2658 		msg = xmlStrcat(msg,
2659 		BAD_CAST "this differs from the allowed length of '%s'.\n");
2660 	    else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
2661 		msg = xmlStrcat(msg,
2662 		BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2663 	    else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
2664 		msg = xmlStrcat(msg,
2665 		BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
2666 
2667 	    if (nodeType == XML_ATTRIBUTE_NODE)
2668 		xmlSchemaErr3(actxt, error, node, (const char *) msg,
2669 		    value, (const xmlChar *) actLen, (const xmlChar *) len);
2670 	    else
2671 		xmlSchemaErr(actxt, error, node, (const char *) msg,
2672 		    (const xmlChar *) actLen, (const xmlChar *) len);
2673 
2674 	} else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2675 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2676 		"of the set {%s}.\n");
2677 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2678 		xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2679 	} else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2680 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2681 		"by the pattern '%s'.\n");
2682 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2683 		facet->value);
2684 	} else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2685 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2686 		"minimum value allowed ('%s').\n");
2687 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2688 		facet->value);
2689 	} else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2690 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2691 		"maximum value allowed ('%s').\n");
2692 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2693 		facet->value);
2694 	} else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
2695 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be greater than "
2696 		"'%s'.\n");
2697 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2698 		facet->value);
2699 	} else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
2700 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
2701 		"'%s'.\n");
2702 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2703 		facet->value);
2704 	} else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2705 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2706 		"digits than are allowed ('%s').\n");
2707 	    xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2708 		facet->value);
2709 	} else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2710 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2711 		"digits than are allowed ('%s').\n");
2712 	    xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2713 		facet->value);
2714 	} else if (nodeType == XML_ATTRIBUTE_NODE) {
2715 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
2716 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2717 	} else {
2718 	    msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2719 	    xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2720 	}
2721     } else {
2722 	msg = xmlStrcat(msg, (const xmlChar *) message);
2723 	msg = xmlStrcat(msg, BAD_CAST ".\n");
2724 	xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
2725     }
2726     FREE_AND_NULL(str)
2727     xmlFree(msg);
2728 }
2729 
2730 #define VERROR(err, type, msg) \
2731     xmlSchemaCustomErr(ACTXT_CAST vctxt, err, NULL, type, msg, NULL, NULL);
2732 
2733 #define VERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST vctxt, func, msg);
2734 
2735 #define PERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST pctxt, func, msg);
2736 #define PERROR_INT2(func, msg) xmlSchemaInternalErr(ACTXT_CAST ctxt, func, msg);
2737 
2738 #define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2739 
2740 
2741 /**
2742  * xmlSchemaPMissingAttrErr:
2743  * @ctxt: the schema validation context
2744  * @ownerDes: the designation of  the owner
2745  * @ownerName: the name of the owner
2746  * @ownerItem: the owner as a schema object
2747  * @ownerElem: the owner as an element node
2748  * @node: the parent element node of the missing attribute node
2749  * @type: the corresponding type of the attribute node
2750  *
2751  * Reports an illegal attribute.
2752  */
2753 static void
xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr ownerItem,xmlNodePtr ownerElem,const char * name,const char * message)2754 xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
2755 			 xmlParserErrors error,
2756 			 xmlSchemaBasicItemPtr ownerItem,
2757 			 xmlNodePtr ownerElem,
2758 			 const char *name,
2759 			 const char *message)
2760 {
2761     xmlChar *des = NULL;
2762 
2763     xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2764 
2765     if (message != NULL)
2766 	xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
2767     else
2768 	xmlSchemaPErr(ctxt, ownerElem, error,
2769 	    "%s: The attribute '%s' is required but missing.\n",
2770 	    BAD_CAST des, BAD_CAST name);
2771     FREE_AND_NULL(des);
2772 }
2773 
2774 
2775 /**
2776  * xmlSchemaPResCompAttrErr:
2777  * @ctxt: the schema validation context
2778  * @error: the error code
2779  * @ownerDes: the designation of  the owner
2780  * @ownerItem: the owner as a schema object
2781  * @ownerElem: the owner as an element node
2782  * @name: the name of the attribute holding the QName
2783  * @refName: the referenced local name
2784  * @refURI: the referenced namespace URI
2785  * @message: optional message
2786  *
2787  * Used to report QName attribute values that failed to resolve
2788  * to schema components.
2789  */
2790 static void
xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr ownerItem,xmlNodePtr ownerElem,const char * name,const xmlChar * refName,const xmlChar * refURI,xmlSchemaTypeType refType,const char * refTypeStr)2791 xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
2792 			 xmlParserErrors error,
2793 			 xmlSchemaBasicItemPtr ownerItem,
2794 			 xmlNodePtr ownerElem,
2795 			 const char *name,
2796 			 const xmlChar *refName,
2797 			 const xmlChar *refURI,
2798 			 xmlSchemaTypeType refType,
2799 			 const char *refTypeStr)
2800 {
2801     xmlChar *des = NULL, *strA = NULL;
2802 
2803     xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2804     if (refTypeStr == NULL)
2805 	refTypeStr = (const char *) xmlSchemaItemTypeToStr(refType);
2806 	xmlSchemaPErrExt(ctxt, ownerElem, error,
2807 	    NULL, NULL, NULL,
2808 	    "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2809 	    "%s.\n", BAD_CAST des, BAD_CAST name,
2810 	    xmlSchemaFormatQName(&strA, refURI, refName),
2811 	    BAD_CAST refTypeStr, NULL);
2812     FREE_AND_NULL(des)
2813     FREE_AND_NULL(strA)
2814 }
2815 
2816 /**
2817  * xmlSchemaPCustomAttrErr:
2818  * @ctxt: the schema parser context
2819  * @error: the error code
2820  * @ownerDes: the designation of the owner
2821  * @ownerItem: the owner as a schema object
2822  * @attr: the illegal attribute node
2823  *
2824  * Reports an illegal attribute during the parse.
2825  */
2826 static void
xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlChar ** ownerDes,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,const char * msg)2827 xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
2828 			xmlParserErrors error,
2829 			xmlChar **ownerDes,
2830 			xmlSchemaBasicItemPtr ownerItem,
2831 			xmlAttrPtr attr,
2832 			const char *msg)
2833 {
2834     xmlChar *des = NULL;
2835 
2836     if (ownerDes == NULL)
2837 	xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
2838     else if (*ownerDes == NULL) {
2839 	xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
2840 	des = *ownerDes;
2841     } else
2842 	des = *ownerDes;
2843     if (attr == NULL) {
2844 	xmlSchemaPErrExt(ctxt, NULL, error, NULL, NULL, NULL,
2845 	    "%s, attribute '%s': %s.\n",
2846 	    BAD_CAST des, (const xmlChar *) "Unknown",
2847 	    (const xmlChar *) msg, NULL, NULL);
2848     } else {
2849 	xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
2850 	    "%s, attribute '%s': %s.\n",
2851 	    BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2852     }
2853     if (ownerDes == NULL)
2854 	FREE_AND_NULL(des);
2855 }
2856 
2857 /**
2858  * xmlSchemaPIllegalAttrErr:
2859  * @ctxt: the schema parser context
2860  * @error: the error code
2861  * @ownerDes: the designation of the attribute's owner
2862  * @ownerItem: the attribute's owner item
2863  * @attr: the illegal attribute node
2864  *
2865  * Reports an illegal attribute during the parse.
2866  */
2867 static void
xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr ownerComp ATTRIBUTE_UNUSED,xmlAttrPtr attr)2868 xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
2869 			 xmlParserErrors error,
2870 			 xmlSchemaBasicItemPtr ownerComp ATTRIBUTE_UNUSED,
2871 			 xmlAttrPtr attr)
2872 {
2873     xmlChar *strA = NULL, *strB = NULL;
2874 
2875     xmlSchemaFormatNodeForError(&strA, ACTXT_CAST ctxt, attr->parent);
2876     xmlSchemaErr4(ACTXT_CAST ctxt, error, (xmlNodePtr) attr,
2877 	"%sThe attribute '%s' is not allowed.\n", BAD_CAST strA,
2878 	xmlSchemaFormatQNameNs(&strB, attr->ns, attr->name),
2879 	NULL, NULL);
2880     FREE_AND_NULL(strA);
2881     FREE_AND_NULL(strB);
2882 }
2883 
2884 /**
2885  * xmlSchemaPCustomErr:
2886  * @ctxt: the schema parser context
2887  * @error: the error code
2888  * @itemDes: the designation of the schema item
2889  * @item: the schema item
2890  * @itemElem: the node of the schema item
2891  * @message: the error message
2892  * @str1: an optional param for the error message
2893  * @str2: an optional param for the error message
2894  * @str3: an optional param for the error message
2895  *
2896  * Reports an error during parsing.
2897  */
2898 static void
xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr item,xmlNodePtr itemElem,const char * message,const xmlChar * str1,const xmlChar * str2,const xmlChar * str3)2899 xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
2900 		    xmlParserErrors error,
2901 		    xmlSchemaBasicItemPtr item,
2902 		    xmlNodePtr itemElem,
2903 		    const char *message,
2904 		    const xmlChar *str1,
2905 		    const xmlChar *str2,
2906 		    const xmlChar *str3)
2907 {
2908     xmlChar *des = NULL, *msg = NULL;
2909 
2910     xmlSchemaFormatItemForReport(&des, NULL, item, itemElem);
2911     msg = xmlStrdup(BAD_CAST "%s: ");
2912     msg = xmlStrcat(msg, (const xmlChar *) message);
2913     msg = xmlStrcat(msg, BAD_CAST ".\n");
2914     if ((itemElem == NULL) && (item != NULL))
2915 	itemElem = WXS_ITEM_NODE(item);
2916     xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
2917 	(const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
2918     FREE_AND_NULL(des);
2919     FREE_AND_NULL(msg);
2920 }
2921 
2922 /**
2923  * xmlSchemaPCustomErr:
2924  * @ctxt: the schema parser context
2925  * @error: the error code
2926  * @itemDes: the designation of the schema item
2927  * @item: the schema item
2928  * @itemElem: the node of the schema item
2929  * @message: the error message
2930  * @str1: the optional param for the error message
2931  *
2932  * Reports an error during parsing.
2933  */
2934 static void
xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr item,xmlNodePtr itemElem,const char * message,const xmlChar * str1)2935 xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
2936 		    xmlParserErrors error,
2937 		    xmlSchemaBasicItemPtr item,
2938 		    xmlNodePtr itemElem,
2939 		    const char *message,
2940 		    const xmlChar *str1)
2941 {
2942     xmlSchemaPCustomErrExt(ctxt, error, item, itemElem, message,
2943 	str1, NULL, NULL);
2944 }
2945 
2946 /**
2947  * xmlSchemaPAttrUseErr:
2948  * @ctxt: the schema parser context
2949  * @error: the error code
2950  * @itemDes: the designation of the schema type
2951  * @item: the schema type
2952  * @itemElem: the node of the schema type
2953  * @attr: the invalid schema attribute
2954  * @message: the error message
2955  * @str1: the optional param for the error message
2956  *
2957  * Reports an attribute use error during parsing.
2958  */
2959 static void
xmlSchemaPAttrUseErr4(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlNodePtr node,xmlSchemaBasicItemPtr ownerItem,const xmlSchemaAttributeUsePtr attruse,const char * message,const xmlChar * str1,const xmlChar * str2,const xmlChar * str3,const xmlChar * str4)2960 xmlSchemaPAttrUseErr4(xmlSchemaParserCtxtPtr ctxt,
2961 		    xmlParserErrors error,
2962 		    xmlNodePtr node,
2963 		    xmlSchemaBasicItemPtr ownerItem,
2964 		    const xmlSchemaAttributeUsePtr attruse,
2965 		    const char *message,
2966 		    const xmlChar *str1, const xmlChar *str2,
2967 		    const xmlChar *str3,const xmlChar *str4)
2968 {
2969     xmlChar *str = NULL, *msg = NULL;
2970 
2971     xmlSchemaFormatItemForReport(&msg, NULL, ownerItem, NULL);
2972     msg = xmlStrcat(msg, BAD_CAST ", ");
2973     msg = xmlStrcat(msg,
2974 	BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
2975 	WXS_BASIC_CAST attruse, NULL));
2976     FREE_AND_NULL(str);
2977     msg = xmlStrcat(msg, BAD_CAST ": ");
2978     msg = xmlStrcat(msg, (const xmlChar *) message);
2979     msg = xmlStrcat(msg, BAD_CAST ".\n");
2980     xmlSchemaErr4(ACTXT_CAST ctxt, error, node,
2981 	(const char *) msg, str1, str2, str3, str4);
2982     xmlFree(msg);
2983 }
2984 
2985 /**
2986  * xmlSchemaPIllegalFacetAtomicErr:
2987  * @ctxt: the schema parser context
2988  * @error: the error code
2989  * @type: the schema type
2990  * @baseType: the base type of type
2991  * @facet: the illegal facet
2992  *
2993  * Reports an illegal facet for atomic simple types.
2994  */
2995 static void
xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaTypePtr type,xmlSchemaTypePtr baseType,xmlSchemaFacetPtr facet)2996 xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
2997 			  xmlParserErrors error,
2998 			  xmlSchemaTypePtr type,
2999 			  xmlSchemaTypePtr baseType,
3000 			  xmlSchemaFacetPtr facet)
3001 {
3002     xmlChar *des = NULL, *strT = NULL;
3003 
3004     xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type, type->node);
3005     xmlSchemaPErrExt(ctxt, type->node, error, NULL, NULL, NULL,
3006 	"%s: The facet '%s' is not allowed on types derived from the "
3007 	"type %s.\n",
3008 	BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
3009 	xmlSchemaFormatItemForReport(&strT, NULL, WXS_BASIC_CAST baseType, NULL),
3010 	NULL, NULL);
3011     FREE_AND_NULL(des);
3012     FREE_AND_NULL(strT);
3013 }
3014 
3015 /**
3016  * xmlSchemaPIllegalFacetListUnionErr:
3017  * @ctxt: the schema parser context
3018  * @error: the error code
3019  * @itemDes: the designation of the schema item involved
3020  * @item: the schema item involved
3021  * @facet: the illegal facet
3022  *
3023  * Reports an illegal facet for <list> and <union>.
3024  */
3025 static void
xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaTypePtr type,xmlSchemaFacetPtr facet)3026 xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
3027 			  xmlParserErrors error,
3028 			  xmlSchemaTypePtr type,
3029 			  xmlSchemaFacetPtr facet)
3030 {
3031     xmlChar *des = NULL;
3032 
3033     xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type,
3034 	type->node);
3035     xmlSchemaPErr(ctxt, type->node, error,
3036 	"%s: The facet '%s' is not allowed.\n",
3037 	BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
3038     FREE_AND_NULL(des);
3039 }
3040 
3041 /**
3042  * xmlSchemaPMutualExclAttrErr:
3043  * @ctxt: the schema validation context
3044  * @error: the error code
3045  * @elemDes: the designation of the parent element node
3046  * @attr: the bad attribute node
3047  * @type: the corresponding type of the attribute node
3048  *
3049  * Reports an illegal attribute.
3050  */
3051 static void
xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,const char * name1,const char * name2)3052 xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
3053 			 xmlParserErrors error,
3054 			 xmlSchemaBasicItemPtr ownerItem,
3055 			 xmlAttrPtr attr,
3056 			 const char *name1,
3057 			 const char *name2)
3058 {
3059     xmlChar *des = NULL;
3060 
3061     xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST ownerItem, attr->parent);
3062     xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
3063 	"%s: The attributes '%s' and '%s' are mutually exclusive.\n",
3064 	BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
3065     FREE_AND_NULL(des);
3066 }
3067 
3068 /**
3069  * xmlSchemaPSimpleTypeErr:
3070  * @ctxt:  the schema validation context
3071  * @error: the error code
3072  * @type: the type specifier
3073  * @ownerDes: the designation of the owner
3074  * @ownerItem: the schema object if existent
3075  * @node: the validated node
3076  * @value: the validated value
3077  *
3078  * Reports a simple type validation error.
3079  * TODO: Should this report the value of an element as well?
3080  */
3081 static void
xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr ownerItem ATTRIBUTE_UNUSED,xmlNodePtr node,xmlSchemaTypePtr type,const char * expected,const xmlChar * value,const char * message,const xmlChar * str1,const xmlChar * str2)3082 xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
3083 			xmlParserErrors error,
3084 			xmlSchemaBasicItemPtr ownerItem ATTRIBUTE_UNUSED,
3085 			xmlNodePtr node,
3086 			xmlSchemaTypePtr type,
3087 			const char *expected,
3088 			const xmlChar *value,
3089 			const char *message,
3090 			const xmlChar *str1,
3091 			const xmlChar *str2)
3092 {
3093     xmlChar *msg = NULL;
3094 
3095     xmlSchemaFormatNodeForError(&msg, ACTXT_CAST ctxt, node);
3096     if (message == NULL) {
3097 	/*
3098 	* Use default messages.
3099 	*/
3100 	if (type != NULL) {
3101 	    if (node->type == XML_ATTRIBUTE_NODE)
3102 		msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
3103 	    else
3104 		msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
3105 		"valid value of ");
3106 	    if (! xmlSchemaIsGlobalItem(type))
3107 		msg = xmlStrcat(msg, BAD_CAST "the local ");
3108 	    else
3109 		msg = xmlStrcat(msg, BAD_CAST "the ");
3110 
3111 	    if (WXS_IS_ATOMIC(type))
3112 		msg = xmlStrcat(msg, BAD_CAST "atomic type");
3113 	    else if (WXS_IS_LIST(type))
3114 		msg = xmlStrcat(msg, BAD_CAST "list type");
3115 	    else if (WXS_IS_UNION(type))
3116 		msg = xmlStrcat(msg, BAD_CAST "union type");
3117 
3118 	    if (xmlSchemaIsGlobalItem(type)) {
3119 		xmlChar *str = NULL;
3120 		msg = xmlStrcat(msg, BAD_CAST " '");
3121 		if (type->builtInType != 0) {
3122 		    msg = xmlStrcat(msg, BAD_CAST "xs:");
3123 		    msg = xmlStrcat(msg, type->name);
3124 		} else
3125 		    msg = xmlStrcat(msg,
3126 			xmlSchemaFormatQName(&str,
3127 			    type->targetNamespace, type->name));
3128 		msg = xmlStrcat(msg, BAD_CAST "'.");
3129 		FREE_AND_NULL(str);
3130 	    }
3131 	} else {
3132 	    if (node->type == XML_ATTRIBUTE_NODE)
3133 		msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
3134 	    else
3135 		msg = xmlStrcat(msg, BAD_CAST "The character content is not "
3136 		"valid.");
3137 	}
3138 	if (expected) {
3139 	    msg = xmlStrcat(msg, BAD_CAST " Expected is '");
3140 	    msg = xmlStrcat(msg, BAD_CAST expected);
3141 	    msg = xmlStrcat(msg, BAD_CAST "'.\n");
3142 	} else
3143 	    msg = xmlStrcat(msg, BAD_CAST "\n");
3144 	if (node->type == XML_ATTRIBUTE_NODE)
3145 	    xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
3146 	else
3147 	    xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
3148     } else {
3149 	msg = xmlStrcat(msg, BAD_CAST message);
3150 	msg = xmlStrcat(msg, BAD_CAST ".\n");
3151 	xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
3152 	     (const char*) msg, str1, str2, NULL, NULL, NULL);
3153     }
3154     /* Cleanup. */
3155     FREE_AND_NULL(msg)
3156 }
3157 
3158 /**
3159  * xmlSchemaPContentErr:
3160  * @ctxt: the schema parser context
3161  * @error: the error code
3162  * @onwerDes: the designation of the holder of the content
3163  * @ownerItem: the owner item of the holder of the content
3164  * @ownerElem: the node of the holder of the content
3165  * @child: the invalid child node
3166  * @message: the optional error message
3167  * @content: the optional string describing the correct content
3168  *
3169  * Reports an error concerning the content of a schema element.
3170  */
3171 static void
xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr ownerItem,xmlNodePtr ownerElem,xmlNodePtr child,const char * message,const char * content)3172 xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
3173 		     xmlParserErrors error,
3174 		     xmlSchemaBasicItemPtr ownerItem,
3175 		     xmlNodePtr ownerElem,
3176 		     xmlNodePtr child,
3177 		     const char *message,
3178 		     const char *content)
3179 {
3180     xmlChar *des = NULL;
3181 
3182     xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
3183     if (message != NULL)
3184 	xmlSchemaPErr2(ctxt, ownerElem, child, error,
3185 	    "%s: %s.\n",
3186 	    BAD_CAST des, BAD_CAST message);
3187     else {
3188 	if (content != NULL) {
3189 	    xmlSchemaPErr2(ctxt, ownerElem, child, error,
3190 		"%s: The content is not valid. Expected is %s.\n",
3191 		BAD_CAST des, BAD_CAST content);
3192 	} else {
3193 	    xmlSchemaPErr2(ctxt, ownerElem, child, error,
3194 		"%s: The content is not valid.\n",
3195 		BAD_CAST des, NULL);
3196 	}
3197     }
3198     FREE_AND_NULL(des)
3199 }
3200 
3201 /************************************************************************
3202  * 									*
3203  * 			Streamable error functions                      *
3204  * 									*
3205  ************************************************************************/
3206 
3207 
3208 
3209 
3210 /************************************************************************
3211  * 									*
3212  * 			Validation helper functions			*
3213  * 									*
3214  ************************************************************************/
3215 
3216 
3217 /************************************************************************
3218  * 									*
3219  * 			Allocation functions				*
3220  * 									*
3221  ************************************************************************/
3222 
3223 /**
3224  * xmlSchemaNewSchemaForParserCtxt:
3225  * @ctxt:  a schema validation context
3226  *
3227  * Allocate a new Schema structure.
3228  *
3229  * Returns the newly allocated structure or NULL in case or error
3230  */
3231 static xmlSchemaPtr
xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)3232 xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
3233 {
3234     xmlSchemaPtr ret;
3235 
3236     ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
3237     if (ret == NULL) {
3238         xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
3239         return (NULL);
3240     }
3241     memset(ret, 0, sizeof(xmlSchema));
3242     ret->dict = ctxt->dict;
3243     xmlDictReference(ret->dict);
3244 
3245     return (ret);
3246 }
3247 
3248 /**
3249  * xmlSchemaNewFacet:
3250  *
3251  * Allocate a new Facet structure.
3252  *
3253  * Returns the newly allocated structure or NULL in case or error
3254  */
3255 xmlSchemaFacetPtr
xmlSchemaNewFacet(void)3256 xmlSchemaNewFacet(void)
3257 {
3258     xmlSchemaFacetPtr ret;
3259 
3260     ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
3261     if (ret == NULL) {
3262         return (NULL);
3263     }
3264     memset(ret, 0, sizeof(xmlSchemaFacet));
3265 
3266     return (ret);
3267 }
3268 
3269 /**
3270  * xmlSchemaNewAnnot:
3271  * @ctxt:  a schema validation context
3272  * @node:  a node
3273  *
3274  * Allocate a new annotation structure.
3275  *
3276  * Returns the newly allocated structure or NULL in case or error
3277  */
3278 static xmlSchemaAnnotPtr
xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node)3279 xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3280 {
3281     xmlSchemaAnnotPtr ret;
3282 
3283     ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
3284     if (ret == NULL) {
3285         xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
3286         return (NULL);
3287     }
3288     memset(ret, 0, sizeof(xmlSchemaAnnot));
3289     ret->content = node;
3290     return (ret);
3291 }
3292 
3293 static xmlSchemaItemListPtr
xmlSchemaItemListCreate(void)3294 xmlSchemaItemListCreate(void)
3295 {
3296     xmlSchemaItemListPtr ret;
3297 
3298     ret = xmlMalloc(sizeof(xmlSchemaItemList));
3299     if (ret == NULL) {
3300 	xmlSchemaPErrMemory(NULL,
3301 	    "allocating an item list structure", NULL);
3302 	return (NULL);
3303     }
3304     memset(ret, 0, sizeof(xmlSchemaItemList));
3305     return (ret);
3306 }
3307 
3308 static void
xmlSchemaItemListClear(xmlSchemaItemListPtr list)3309 xmlSchemaItemListClear(xmlSchemaItemListPtr list)
3310 {
3311     if (list->items != NULL) {
3312 	xmlFree(list->items);
3313 	list->items = NULL;
3314     }
3315     list->nbItems = 0;
3316     list->sizeItems = 0;
3317 }
3318 
3319 static int
xmlSchemaItemListAdd(xmlSchemaItemListPtr list,void * item)3320 xmlSchemaItemListAdd(xmlSchemaItemListPtr list, void *item)
3321 {
3322     if (list->items == NULL) {
3323 	list->items = (void **) xmlMalloc(
3324 	    20 * sizeof(void *));
3325 	if (list->items == NULL) {
3326 	    xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3327 	    return(-1);
3328 	}
3329 	list->sizeItems = 20;
3330     } else if (list->sizeItems <= list->nbItems) {
3331 	list->sizeItems *= 2;
3332 	list->items = (void **) xmlRealloc(list->items,
3333 	    list->sizeItems * sizeof(void *));
3334 	if (list->items == NULL) {
3335 	    xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3336 	    list->sizeItems = 0;
3337 	    return(-1);
3338 	}
3339     }
3340     list->items[list->nbItems++] = item;
3341     return(0);
3342 }
3343 
3344 static int
xmlSchemaItemListAddSize(xmlSchemaItemListPtr list,int initialSize,void * item)3345 xmlSchemaItemListAddSize(xmlSchemaItemListPtr list,
3346 			 int initialSize,
3347 			 void *item)
3348 {
3349     if (list->items == NULL) {
3350 	if (initialSize <= 0)
3351 	    initialSize = 1;
3352 	list->items = (void **) xmlMalloc(
3353 	    initialSize * sizeof(void *));
3354 	if (list->items == NULL) {
3355 	    xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3356 	    return(-1);
3357 	}
3358 	list->sizeItems = initialSize;
3359     } else if (list->sizeItems <= list->nbItems) {
3360 	list->sizeItems *= 2;
3361 	list->items = (void **) xmlRealloc(list->items,
3362 	    list->sizeItems * sizeof(void *));
3363 	if (list->items == NULL) {
3364 	    xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3365 	    list->sizeItems = 0;
3366 	    return(-1);
3367 	}
3368     }
3369     list->items[list->nbItems++] = item;
3370     return(0);
3371 }
3372 
3373 static int
xmlSchemaItemListInsert(xmlSchemaItemListPtr list,void * item,int idx)3374 xmlSchemaItemListInsert(xmlSchemaItemListPtr list, void *item, int idx)
3375 {
3376     if (list->items == NULL) {
3377 	list->items = (void **) xmlMalloc(
3378 	    20 * sizeof(void *));
3379 	if (list->items == NULL) {
3380 	    xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3381 	    return(-1);
3382 	}
3383 	list->sizeItems = 20;
3384     } else if (list->sizeItems <= list->nbItems) {
3385 	list->sizeItems *= 2;
3386 	list->items = (void **) xmlRealloc(list->items,
3387 	    list->sizeItems * sizeof(void *));
3388 	if (list->items == NULL) {
3389 	    xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3390 	    list->sizeItems = 0;
3391 	    return(-1);
3392 	}
3393     }
3394     /*
3395     * Just append if the index is greater/equal than the item count.
3396     */
3397     if (idx >= list->nbItems) {
3398 	list->items[list->nbItems++] = item;
3399     } else {
3400 	int i;
3401 	for (i = list->nbItems; i > idx; i--)
3402 	    list->items[i] = list->items[i-1];
3403 	list->items[idx] = item;
3404 	list->nbItems++;
3405     }
3406     return(0);
3407 }
3408 
3409 #if 0 /* enable if ever needed */
3410 static int
3411 xmlSchemaItemListInsertSize(xmlSchemaItemListPtr list,
3412 			    int initialSize,
3413 			    void *item,
3414 			    int idx)
3415 {
3416     if (list->items == NULL) {
3417 	if (initialSize <= 0)
3418 	    initialSize = 1;
3419 	list->items = (void **) xmlMalloc(
3420 	    initialSize * sizeof(void *));
3421 	if (list->items == NULL) {
3422 	    xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3423 	    return(-1);
3424 	}
3425 	list->sizeItems = initialSize;
3426     } else if (list->sizeItems <= list->nbItems) {
3427 	list->sizeItems *= 2;
3428 	list->items = (void **) xmlRealloc(list->items,
3429 	    list->sizeItems * sizeof(void *));
3430 	if (list->items == NULL) {
3431 	    xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3432 	    list->sizeItems = 0;
3433 	    return(-1);
3434 	}
3435     }
3436     /*
3437     * Just append if the index is greater/equal than the item count.
3438     */
3439     if (idx >= list->nbItems) {
3440 	list->items[list->nbItems++] = item;
3441     } else {
3442 	int i;
3443 	for (i = list->nbItems; i > idx; i--)
3444 	    list->items[i] = list->items[i-1];
3445 	list->items[idx] = item;
3446 	list->nbItems++;
3447     }
3448     return(0);
3449 }
3450 #endif
3451 
3452 static int
xmlSchemaItemListRemove(xmlSchemaItemListPtr list,int idx)3453 xmlSchemaItemListRemove(xmlSchemaItemListPtr list, int idx)
3454 {
3455     int i;
3456     if ((list->items == NULL) || (idx >= list->nbItems)) {
3457 	xmlSchemaPSimpleErr("Internal error: xmlSchemaItemListRemove, "
3458 	    "index error.\n");
3459 	return(-1);
3460     }
3461 
3462     if (list->nbItems == 1) {
3463 	/* TODO: Really free the list? */
3464 	xmlFree(list->items);
3465 	list->items = NULL;
3466 	list->nbItems = 0;
3467 	list->sizeItems = 0;
3468     } else if (list->nbItems -1 == idx) {
3469 	list->nbItems--;
3470     } else {
3471 	for (i = idx; i < list->nbItems -1; i++)
3472 	    list->items[i] = list->items[i+1];
3473 	list->nbItems--;
3474     }
3475     return(0);
3476 }
3477 
3478 /**
3479  * xmlSchemaItemListFree:
3480  * @annot:  a schema type structure
3481  *
3482  * Deallocate a annotation structure
3483  */
3484 static void
xmlSchemaItemListFree(xmlSchemaItemListPtr list)3485 xmlSchemaItemListFree(xmlSchemaItemListPtr list)
3486 {
3487     if (list == NULL)
3488 	return;
3489     if (list->items != NULL)
3490 	xmlFree(list->items);
3491     xmlFree(list);
3492 }
3493 
3494 static void
xmlSchemaBucketFree(xmlSchemaBucketPtr bucket)3495 xmlSchemaBucketFree(xmlSchemaBucketPtr bucket)
3496 {
3497     if (bucket == NULL)
3498 	return;
3499     if (bucket->globals != NULL) {
3500 	xmlSchemaComponentListFree(bucket->globals);
3501 	xmlSchemaItemListFree(bucket->globals);
3502     }
3503     if (bucket->locals != NULL) {
3504 	xmlSchemaComponentListFree(bucket->locals);
3505 	xmlSchemaItemListFree(bucket->locals);
3506     }
3507     if (bucket->relations != NULL) {
3508 	xmlSchemaSchemaRelationPtr prev, cur = bucket->relations;
3509 	do {
3510 	    prev = cur;
3511 	    cur = cur->next;
3512 	    xmlFree(prev);
3513 	} while (cur != NULL);
3514     }
3515     if ((! bucket->preserveDoc) && (bucket->doc != NULL)) {
3516 	xmlFreeDoc(bucket->doc);
3517     }
3518     if (bucket->type == XML_SCHEMA_SCHEMA_IMPORT) {
3519 	if (WXS_IMPBUCKET(bucket)->schema != NULL)
3520 	    xmlSchemaFree(WXS_IMPBUCKET(bucket)->schema);
3521     }
3522     xmlFree(bucket);
3523 }
3524 
3525 static xmlSchemaBucketPtr
xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,int type,const xmlChar * targetNamespace)3526 xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,
3527 			 int type, const xmlChar *targetNamespace)
3528 {
3529     xmlSchemaBucketPtr ret;
3530     int size;
3531     xmlSchemaPtr mainSchema;
3532 
3533     if (WXS_CONSTRUCTOR(pctxt)->mainSchema == NULL) {
3534 	PERROR_INT("xmlSchemaBucketCreate",
3535 	    "no main schema on constructor");
3536 	return(NULL);
3537     }
3538     mainSchema = WXS_CONSTRUCTOR(pctxt)->mainSchema;
3539     /* Create the schema bucket. */
3540     if (WXS_IS_BUCKET_INCREDEF(type))
3541 	size = sizeof(xmlSchemaInclude);
3542     else
3543 	size = sizeof(xmlSchemaImport);
3544     ret = (xmlSchemaBucketPtr) xmlMalloc(size);
3545     if (ret == NULL) {
3546 	xmlSchemaPErrMemory(NULL, "allocating schema bucket", NULL);
3547 	return(NULL);
3548     }
3549     memset(ret, 0, size);
3550     ret->targetNamespace = targetNamespace;
3551     ret->type = type;
3552     ret->globals = xmlSchemaItemListCreate();
3553     if (ret->globals == NULL) {
3554 	xmlFree(ret);
3555 	return(NULL);
3556     }
3557     ret->locals = xmlSchemaItemListCreate();
3558     if (ret->locals == NULL) {
3559 	xmlFree(ret);
3560 	return(NULL);
3561     }
3562     /*
3563     * The following will assure that only the first bucket is marked as
3564     * XML_SCHEMA_SCHEMA_MAIN and it points to the *main* schema.
3565     * For each following import buckets an xmlSchema will be created.
3566     * An xmlSchema will be created for every distinct targetNamespace.
3567     * We assign the targetNamespace to the schemata here.
3568     */
3569     if (! WXS_HAS_BUCKETS(pctxt)) {
3570 	if (WXS_IS_BUCKET_INCREDEF(type)) {
3571 	    PERROR_INT("xmlSchemaBucketCreate",
3572 		"first bucket but it's an include or redefine");
3573 	    xmlSchemaBucketFree(ret);
3574 	    return(NULL);
3575 	}
3576 	/* Force the type to be XML_SCHEMA_SCHEMA_MAIN. */
3577 	ret->type = XML_SCHEMA_SCHEMA_MAIN;
3578 	/* Point to the *main* schema. */
3579 	WXS_CONSTRUCTOR(pctxt)->mainBucket = ret;
3580 	WXS_IMPBUCKET(ret)->schema = mainSchema;
3581 	/*
3582 	* Ensure that the main schema gets a targetNamespace.
3583 	*/
3584 	mainSchema->targetNamespace = targetNamespace;
3585     } else {
3586 	if (type == XML_SCHEMA_SCHEMA_MAIN) {
3587 	    PERROR_INT("xmlSchemaBucketCreate",
3588 		"main bucket but it's not the first one");
3589 	    xmlSchemaBucketFree(ret);
3590 	    return(NULL);
3591 	} else if (type == XML_SCHEMA_SCHEMA_IMPORT) {
3592 	    /*
3593 	    * Create a schema for imports and assign the
3594 	    * targetNamespace.
3595 	    */
3596 	    WXS_IMPBUCKET(ret)->schema = xmlSchemaNewSchema(pctxt);
3597 	    if (WXS_IMPBUCKET(ret)->schema == NULL) {
3598 		xmlSchemaBucketFree(ret);
3599 		return(NULL);
3600 	    }
3601 	    WXS_IMPBUCKET(ret)->schema->targetNamespace = targetNamespace;
3602 	}
3603     }
3604     if (WXS_IS_BUCKET_IMPMAIN(type)) {
3605 	int res;
3606 	/*
3607 	* Imports go into the "schemasImports" slot of the main *schema*.
3608 	* Note that we create an import entry for the main schema as well; i.e.,
3609 	* even if there's only one schema, we'll get an import.
3610 	*/
3611 	if (mainSchema->schemasImports == NULL) {
3612 	    mainSchema->schemasImports = xmlHashCreateDict(5,
3613 		WXS_CONSTRUCTOR(pctxt)->dict);
3614 	    if (mainSchema->schemasImports == NULL) {
3615 		xmlSchemaBucketFree(ret);
3616 		return(NULL);
3617 	    }
3618 	}
3619 	if (targetNamespace == NULL)
3620 	    res = xmlHashAddEntry(mainSchema->schemasImports,
3621 		XML_SCHEMAS_NO_NAMESPACE, ret);
3622 	else
3623 	    res = xmlHashAddEntry(mainSchema->schemasImports,
3624 		targetNamespace, ret);
3625 	if (res != 0) {
3626 	    PERROR_INT("xmlSchemaBucketCreate",
3627 		"failed to add the schema bucket to the hash");
3628 	    xmlSchemaBucketFree(ret);
3629 	    return(NULL);
3630 	}
3631     } else {
3632 	/* Set the @ownerImport of an include bucket. */
3633 	if (WXS_IS_BUCKET_IMPMAIN(WXS_CONSTRUCTOR(pctxt)->bucket->type))
3634 	    WXS_INCBUCKET(ret)->ownerImport =
3635 		WXS_IMPBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket);
3636 	else
3637 	    WXS_INCBUCKET(ret)->ownerImport =
3638 		WXS_INCBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket)->ownerImport;
3639 
3640 	/* Includes got into the "includes" slot of the *main* schema. */
3641 	if (mainSchema->includes == NULL) {
3642 	    mainSchema->includes = xmlSchemaItemListCreate();
3643 	    if (mainSchema->includes == NULL) {
3644 		xmlSchemaBucketFree(ret);
3645 		return(NULL);
3646 	    }
3647 	}
3648 	xmlSchemaItemListAdd(mainSchema->includes, ret);
3649     }
3650     /*
3651     * Add to list of all buckets; this is used for lookup
3652     * during schema construction time only.
3653     */
3654     if (xmlSchemaItemListAdd(WXS_CONSTRUCTOR(pctxt)->buckets, ret) == -1)
3655 	return(NULL);
3656     return(ret);
3657 }
3658 
3659 static int
xmlSchemaAddItemSize(xmlSchemaItemListPtr * list,int initialSize,void * item)3660 xmlSchemaAddItemSize(xmlSchemaItemListPtr *list, int initialSize, void *item)
3661 {
3662     if (*list == NULL) {
3663 	*list = xmlSchemaItemListCreate();
3664 	if (*list == NULL)
3665 	    return(-1);
3666     }
3667     xmlSchemaItemListAddSize(*list, initialSize, item);
3668     return(0);
3669 }
3670 
3671 /**
3672  * xmlSchemaFreeAnnot:
3673  * @annot:  a schema type structure
3674  *
3675  * Deallocate a annotation structure
3676  */
3677 static void
xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)3678 xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
3679 {
3680     if (annot == NULL)
3681         return;
3682     if (annot->next == NULL) {
3683 	xmlFree(annot);
3684     } else {
3685 	xmlSchemaAnnotPtr prev;
3686 
3687 	do {
3688 	    prev = annot;
3689 	    annot = annot->next;
3690 	    xmlFree(prev);
3691 	} while (annot != NULL);
3692     }
3693 }
3694 
3695 /**
3696  * xmlSchemaFreeNotation:
3697  * @schema:  a schema notation structure
3698  *
3699  * Deallocate a Schema Notation structure.
3700  */
3701 static void
xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)3702 xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
3703 {
3704     if (nota == NULL)
3705         return;
3706     xmlFree(nota);
3707 }
3708 
3709 /**
3710  * xmlSchemaFreeAttribute:
3711  * @attr:  an attribute declaration
3712  *
3713  * Deallocates an attribute declaration structure.
3714  */
3715 static void
xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)3716 xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
3717 {
3718     if (attr == NULL)
3719         return;
3720     if (attr->annot != NULL)
3721 	xmlSchemaFreeAnnot(attr->annot);
3722     if (attr->defVal != NULL)
3723 	xmlSchemaFreeValue(attr->defVal);
3724     xmlFree(attr);
3725 }
3726 
3727 /**
3728  * xmlSchemaFreeAttributeUse:
3729  * @use:  an attribute use
3730  *
3731  * Deallocates an attribute use structure.
3732  */
3733 static void
xmlSchemaFreeAttributeUse(xmlSchemaAttributeUsePtr use)3734 xmlSchemaFreeAttributeUse(xmlSchemaAttributeUsePtr use)
3735 {
3736     if (use == NULL)
3737         return;
3738     if (use->annot != NULL)
3739 	xmlSchemaFreeAnnot(use->annot);
3740     if (use->defVal != NULL)
3741 	xmlSchemaFreeValue(use->defVal);
3742     xmlFree(use);
3743 }
3744 
3745 /**
3746  * xmlSchemaFreeAttributeUseProhib:
3747  * @prohib:  an attribute use prohibition
3748  *
3749  * Deallocates an attribute use structure.
3750  */
3751 static void
xmlSchemaFreeAttributeUseProhib(xmlSchemaAttributeUseProhibPtr prohib)3752 xmlSchemaFreeAttributeUseProhib(xmlSchemaAttributeUseProhibPtr prohib)
3753 {
3754     if (prohib == NULL)
3755         return;
3756     xmlFree(prohib);
3757 }
3758 
3759 /**
3760  * xmlSchemaFreeWildcardNsSet:
3761  * set:  a schema wildcard namespace
3762  *
3763  * Deallocates a list of wildcard constraint structures.
3764  */
3765 static void
xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)3766 xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
3767 {
3768     xmlSchemaWildcardNsPtr next;
3769 
3770     while (set != NULL) {
3771 	next = set->next;
3772 	xmlFree(set);
3773 	set = next;
3774     }
3775 }
3776 
3777 /**
3778  * xmlSchemaFreeWildcard:
3779  * @wildcard:  a wildcard structure
3780  *
3781  * Deallocates a wildcard structure.
3782  */
3783 void
xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)3784 xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
3785 {
3786     if (wildcard == NULL)
3787         return;
3788     if (wildcard->annot != NULL)
3789         xmlSchemaFreeAnnot(wildcard->annot);
3790     if (wildcard->nsSet != NULL)
3791 	xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
3792     if (wildcard->negNsSet != NULL)
3793 	xmlFree(wildcard->negNsSet);
3794     xmlFree(wildcard);
3795 }
3796 
3797 /**
3798  * xmlSchemaFreeAttributeGroup:
3799  * @schema:  a schema attribute group structure
3800  *
3801  * Deallocate a Schema Attribute Group structure.
3802  */
3803 static void
xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attrGr)3804 xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attrGr)
3805 {
3806     if (attrGr == NULL)
3807         return;
3808     if (attrGr->annot != NULL)
3809         xmlSchemaFreeAnnot(attrGr->annot);
3810     if (attrGr->attrUses != NULL)
3811 	xmlSchemaItemListFree(WXS_LIST_CAST attrGr->attrUses);
3812     xmlFree(attrGr);
3813 }
3814 
3815 /**
3816  * xmlSchemaFreeQNameRef:
3817  * @item: a QName reference structure
3818  *
3819  * Deallocatea a QName reference structure.
3820  */
3821 static void
xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)3822 xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3823 {
3824     xmlFree(item);
3825 }
3826 
3827 /**
3828  * xmlSchemaFreeTypeLinkList:
3829  * @alink: a type link
3830  *
3831  * Deallocate a list of types.
3832  */
3833 static void
xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)3834 xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3835 {
3836     xmlSchemaTypeLinkPtr next;
3837 
3838     while (link != NULL) {
3839 	next = link->next;
3840 	xmlFree(link);
3841 	link = next;
3842     }
3843 }
3844 
3845 static void
xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)3846 xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3847 {
3848     xmlSchemaIDCStateObjPtr next;
3849     while (sto != NULL) {
3850 	next = sto->next;
3851 	if (sto->history != NULL)
3852 	    xmlFree(sto->history);
3853 	if (sto->xpathCtxt != NULL)
3854 	    xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3855 	xmlFree(sto);
3856 	sto = next;
3857     }
3858 }
3859 
3860 /**
3861  * xmlSchemaFreeIDC:
3862  * @idc: a identity-constraint definition
3863  *
3864  * Deallocates an identity-constraint definition.
3865  */
3866 static void
xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)3867 xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3868 {
3869     xmlSchemaIDCSelectPtr cur, prev;
3870 
3871     if (idcDef == NULL)
3872 	return;
3873     if (idcDef->annot != NULL)
3874         xmlSchemaFreeAnnot(idcDef->annot);
3875     /* Selector */
3876     if (idcDef->selector != NULL) {
3877 	if (idcDef->selector->xpathComp != NULL)
3878 	    xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3879 	xmlFree(idcDef->selector);
3880     }
3881     /* Fields */
3882     if (idcDef->fields != NULL) {
3883 	cur = idcDef->fields;
3884 	do {
3885 	    prev = cur;
3886 	    cur = cur->next;
3887 	    if (prev->xpathComp != NULL)
3888 		xmlFreePattern((xmlPatternPtr) prev->xpathComp);
3889 	    xmlFree(prev);
3890 	} while (cur != NULL);
3891     }
3892     xmlFree(idcDef);
3893 }
3894 
3895 /**
3896  * xmlSchemaFreeElement:
3897  * @schema:  a schema element structure
3898  *
3899  * Deallocate a Schema Element structure.
3900  */
3901 static void
xmlSchemaFreeElement(xmlSchemaElementPtr elem)3902 xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3903 {
3904     if (elem == NULL)
3905         return;
3906     if (elem->annot != NULL)
3907         xmlSchemaFreeAnnot(elem->annot);
3908     if (elem->contModel != NULL)
3909         xmlRegFreeRegexp(elem->contModel);
3910     if (elem->defVal != NULL)
3911 	xmlSchemaFreeValue(elem->defVal);
3912     xmlFree(elem);
3913 }
3914 
3915 /**
3916  * xmlSchemaFreeFacet:
3917  * @facet:  a schema facet structure
3918  *
3919  * Deallocate a Schema Facet structure.
3920  */
3921 void
xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)3922 xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
3923 {
3924     if (facet == NULL)
3925         return;
3926     if (facet->val != NULL)
3927         xmlSchemaFreeValue(facet->val);
3928     if (facet->regexp != NULL)
3929         xmlRegFreeRegexp(facet->regexp);
3930     if (facet->annot != NULL)
3931         xmlSchemaFreeAnnot(facet->annot);
3932     xmlFree(facet);
3933 }
3934 
3935 /**
3936  * xmlSchemaFreeType:
3937  * @type:  a schema type structure
3938  *
3939  * Deallocate a Schema Type structure.
3940  */
3941 void
xmlSchemaFreeType(xmlSchemaTypePtr type)3942 xmlSchemaFreeType(xmlSchemaTypePtr type)
3943 {
3944     if (type == NULL)
3945         return;
3946     if (type->annot != NULL)
3947         xmlSchemaFreeAnnot(type->annot);
3948     if (type->facets != NULL) {
3949         xmlSchemaFacetPtr facet, next;
3950 
3951         facet = type->facets;
3952         while (facet != NULL) {
3953             next = facet->next;
3954             xmlSchemaFreeFacet(facet);
3955             facet = next;
3956         }
3957     }
3958     if (type->attrUses != NULL)
3959 	xmlSchemaItemListFree((xmlSchemaItemListPtr) type->attrUses);
3960     if (type->memberTypes != NULL)
3961 	xmlSchemaFreeTypeLinkList(type->memberTypes);
3962     if (type->facetSet != NULL) {
3963 	xmlSchemaFacetLinkPtr next, link;
3964 
3965 	link = type->facetSet;
3966 	do {
3967 	    next = link->next;
3968 	    xmlFree(link);
3969 	    link = next;
3970 	} while (link != NULL);
3971     }
3972     if (type->contModel != NULL)
3973         xmlRegFreeRegexp(type->contModel);
3974     xmlFree(type);
3975 }
3976 
3977 /**
3978  * xmlSchemaFreeModelGroupDef:
3979  * @item:  a schema model group definition
3980  *
3981  * Deallocates a schema model group definition.
3982  */
3983 static void
xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)3984 xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
3985 {
3986     if (item->annot != NULL)
3987 	xmlSchemaFreeAnnot(item->annot);
3988     xmlFree(item);
3989 }
3990 
3991 /**
3992  * xmlSchemaFreeModelGroup:
3993  * @item:  a schema model group
3994  *
3995  * Deallocates a schema model group structure.
3996  */
3997 static void
xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)3998 xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
3999 {
4000     if (item->annot != NULL)
4001 	xmlSchemaFreeAnnot(item->annot);
4002     xmlFree(item);
4003 }
4004 
4005 static void
xmlSchemaComponentListFree(xmlSchemaItemListPtr list)4006 xmlSchemaComponentListFree(xmlSchemaItemListPtr list)
4007 {
4008     if ((list == NULL) || (list->nbItems == 0))
4009 	return;
4010     {
4011 	xmlSchemaTreeItemPtr item;
4012 	xmlSchemaTreeItemPtr *items = (xmlSchemaTreeItemPtr *) list->items;
4013 	int i;
4014 
4015 	for (i = 0; i < list->nbItems; i++) {
4016 	    item = items[i];
4017 	    if (item == NULL)
4018 		continue;
4019 	    switch (item->type) {
4020 		case XML_SCHEMA_TYPE_SIMPLE:
4021 		case XML_SCHEMA_TYPE_COMPLEX:
4022 		    xmlSchemaFreeType((xmlSchemaTypePtr) item);
4023 		    break;
4024 		case XML_SCHEMA_TYPE_ATTRIBUTE:
4025 		    xmlSchemaFreeAttribute((xmlSchemaAttributePtr) item);
4026 		    break;
4027 		case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
4028 		    xmlSchemaFreeAttributeUse((xmlSchemaAttributeUsePtr) item);
4029 		    break;
4030 		case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
4031 		    xmlSchemaFreeAttributeUseProhib(
4032 			(xmlSchemaAttributeUseProhibPtr) item);
4033 		    break;
4034 		case XML_SCHEMA_TYPE_ELEMENT:
4035 		    xmlSchemaFreeElement((xmlSchemaElementPtr) item);
4036 		    break;
4037 		case XML_SCHEMA_TYPE_PARTICLE:
4038 		    if (item->annot != NULL)
4039 			xmlSchemaFreeAnnot(item->annot);
4040 		    xmlFree(item);
4041 		    break;
4042 		case XML_SCHEMA_TYPE_SEQUENCE:
4043 		case XML_SCHEMA_TYPE_CHOICE:
4044 		case XML_SCHEMA_TYPE_ALL:
4045 		    xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
4046 		    break;
4047 		case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
4048 		    xmlSchemaFreeAttributeGroup(
4049 			(xmlSchemaAttributeGroupPtr) item);
4050 		    break;
4051 		case XML_SCHEMA_TYPE_GROUP:
4052 		    xmlSchemaFreeModelGroupDef(
4053 			(xmlSchemaModelGroupDefPtr) item);
4054 		    break;
4055 		case XML_SCHEMA_TYPE_ANY:
4056 		case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
4057 		    xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
4058 		    break;
4059 		case XML_SCHEMA_TYPE_IDC_KEY:
4060 		case XML_SCHEMA_TYPE_IDC_UNIQUE:
4061 		case XML_SCHEMA_TYPE_IDC_KEYREF:
4062 		    xmlSchemaFreeIDC((xmlSchemaIDCPtr) item);
4063 		    break;
4064 		case XML_SCHEMA_TYPE_NOTATION:
4065 		    xmlSchemaFreeNotation((xmlSchemaNotationPtr) item);
4066 		    break;
4067 		case XML_SCHEMA_EXTRA_QNAMEREF:
4068 		    xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
4069 		    break;
4070 		default: {
4071 		    /* TODO: This should never be hit. */
4072 		    xmlSchemaPSimpleInternalErr(NULL,
4073 			"Internal error: xmlSchemaComponentListFree, "
4074 			"unexpected component type '%s'\n",
4075 			(const xmlChar *) WXS_ITEM_TYPE_NAME(item));
4076 			 }
4077 		    break;
4078 	    }
4079 	}
4080 	list->nbItems = 0;
4081     }
4082 }
4083 
4084 /**
4085  * xmlSchemaFree:
4086  * @schema:  a schema structure
4087  *
4088  * Deallocate a Schema structure.
4089  */
4090 void
xmlSchemaFree(xmlSchemaPtr schema)4091 xmlSchemaFree(xmlSchemaPtr schema)
4092 {
4093     if (schema == NULL)
4094         return;
4095     /* @volatiles is not used anymore :-/ */
4096     if (schema->volatiles != NULL)
4097 	TODO
4098     /*
4099     * Note that those slots are not responsible for freeing
4100     * schema components anymore; this will now be done by
4101     * the schema buckets.
4102     */
4103     if (schema->notaDecl != NULL)
4104         xmlHashFree(schema->notaDecl, NULL);
4105     if (schema->attrDecl != NULL)
4106         xmlHashFree(schema->attrDecl, NULL);
4107     if (schema->attrgrpDecl != NULL)
4108         xmlHashFree(schema->attrgrpDecl, NULL);
4109     if (schema->elemDecl != NULL)
4110         xmlHashFree(schema->elemDecl, NULL);
4111     if (schema->typeDecl != NULL)
4112         xmlHashFree(schema->typeDecl, NULL);
4113     if (schema->groupDecl != NULL)
4114         xmlHashFree(schema->groupDecl, NULL);
4115     if (schema->idcDef != NULL)
4116         xmlHashFree(schema->idcDef, NULL);
4117 
4118     if (schema->schemasImports != NULL)
4119 	xmlHashFree(schema->schemasImports,
4120 		    (xmlHashDeallocator) xmlSchemaBucketFree);
4121     if (schema->includes != NULL) {
4122 	xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->includes;
4123 	int i;
4124 	for (i = 0; i < list->nbItems; i++) {
4125 	    xmlSchemaBucketFree((xmlSchemaBucketPtr) list->items[i]);
4126 	}
4127 	xmlSchemaItemListFree(list);
4128     }
4129     if (schema->annot != NULL)
4130         xmlSchemaFreeAnnot(schema->annot);
4131     /* Never free the doc here, since this will be done by the buckets. */
4132 
4133     xmlDictFree(schema->dict);
4134     xmlFree(schema);
4135 }
4136 
4137 /************************************************************************
4138  * 									*
4139  * 			Debug functions					*
4140  * 									*
4141  ************************************************************************/
4142 
4143 #ifdef LIBXML_OUTPUT_ENABLED
4144 
4145 static void
4146 xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output); /* forward */
4147 
4148 /**
4149  * xmlSchemaElementDump:
4150  * @elem:  an element
4151  * @output:  the file output
4152  *
4153  * Dump the element
4154  */
4155 static void
xmlSchemaElementDump(xmlSchemaElementPtr elem,FILE * output,const xmlChar * name ATTRIBUTE_UNUSED,const xmlChar * namespace ATTRIBUTE_UNUSED,const xmlChar * context ATTRIBUTE_UNUSED)4156 xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
4157                      const xmlChar * name ATTRIBUTE_UNUSED,
4158 		     const xmlChar * namespace ATTRIBUTE_UNUSED,
4159                      const xmlChar * context ATTRIBUTE_UNUSED)
4160 {
4161     if (elem == NULL)
4162         return;
4163 
4164 
4165     fprintf(output, "Element");
4166     if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
4167 	fprintf(output, " (global)");
4168     fprintf(output, ": '%s' ", elem->name);
4169     if (namespace != NULL)
4170 	fprintf(output, "ns '%s'", namespace);
4171     fprintf(output, "\n");
4172 #if 0
4173     if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
4174 	fprintf(output, "  min %d ", elem->minOccurs);
4175         if (elem->maxOccurs >= UNBOUNDED)
4176             fprintf(output, "max: unbounded\n");
4177         else if (elem->maxOccurs != 1)
4178             fprintf(output, "max: %d\n", elem->maxOccurs);
4179         else
4180             fprintf(output, "\n");
4181     }
4182 #endif
4183     /*
4184     * Misc other properties.
4185     */
4186     if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
4187 	(elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
4188 	(elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
4189 	(elem->flags & XML_SCHEMAS_ELEM_DEFAULT)) {
4190 	fprintf(output, "  props: ");
4191 	if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
4192 	    fprintf(output, "[fixed] ");
4193 	if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
4194 	    fprintf(output, "[default] ");
4195 	if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
4196 	    fprintf(output, "[abstract] ");
4197 	if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
4198 	    fprintf(output, "[nillable] ");
4199 	fprintf(output, "\n");
4200     }
4201     /*
4202     * Default/fixed value.
4203     */
4204     if (elem->value != NULL)
4205 	fprintf(output, "  value: '%s'\n", elem->value);
4206     /*
4207     * Type.
4208     */
4209     if (elem->namedType != NULL) {
4210 	fprintf(output, "  type: '%s' ", elem->namedType);
4211 	if (elem->namedTypeNs != NULL)
4212 	    fprintf(output, "ns '%s'\n", elem->namedTypeNs);
4213 	else
4214 	    fprintf(output, "\n");
4215     } else if (elem->subtypes != NULL) {
4216 	/*
4217 	* Dump local types.
4218 	*/
4219 	xmlSchemaTypeDump(elem->subtypes, output);
4220     }
4221     /*
4222     * Substitution group.
4223     */
4224     if (elem->substGroup != NULL) {
4225 	fprintf(output, "  substitutionGroup: '%s' ", elem->substGroup);
4226 	if (elem->substGroupNs != NULL)
4227 	    fprintf(output, "ns '%s'\n", elem->substGroupNs);
4228 	else
4229 	    fprintf(output, "\n");
4230     }
4231 }
4232 
4233 /**
4234  * xmlSchemaAnnotDump:
4235  * @output:  the file output
4236  * @annot:  a annotation
4237  *
4238  * Dump the annotation
4239  */
4240 static void
xmlSchemaAnnotDump(FILE * output,xmlSchemaAnnotPtr annot)4241 xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
4242 {
4243     xmlChar *content;
4244 
4245     if (annot == NULL)
4246         return;
4247 
4248     content = xmlNodeGetContent(annot->content);
4249     if (content != NULL) {
4250         fprintf(output, "  Annot: %s\n", content);
4251         xmlFree(content);
4252     } else
4253         fprintf(output, "  Annot: empty\n");
4254 }
4255 
4256 /**
4257  * xmlSchemaContentModelDump:
4258  * @particle: the schema particle
4259  * @output: the file output
4260  * @depth: the depth used for intentation
4261  *
4262  * Dump a SchemaType structure
4263  */
4264 static void
xmlSchemaContentModelDump(xmlSchemaParticlePtr particle,FILE * output,int depth)4265 xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
4266 {
4267     xmlChar *str = NULL;
4268     xmlSchemaTreeItemPtr term;
4269     char shift[100];
4270     int i;
4271 
4272     if (particle == NULL)
4273 	return;
4274     for (i = 0;((i < depth) && (i < 25));i++)
4275         shift[2 * i] = shift[2 * i + 1] = ' ';
4276     shift[2 * i] = shift[2 * i + 1] = 0;
4277     fprintf(output, shift);
4278     if (particle->children == NULL) {
4279 	fprintf(output, "MISSING particle term\n");
4280 	return;
4281     }
4282     term = particle->children;
4283     if (term == NULL) {
4284 	fprintf(output, "(NULL)");
4285     } else {
4286 	switch (term->type) {
4287 	    case XML_SCHEMA_TYPE_ELEMENT:
4288 		fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
4289 		    ((xmlSchemaElementPtr)term)->targetNamespace,
4290 		    ((xmlSchemaElementPtr)term)->name));
4291 		FREE_AND_NULL(str);
4292 		break;
4293 	    case XML_SCHEMA_TYPE_SEQUENCE:
4294 		fprintf(output, "SEQUENCE");
4295 		break;
4296 	    case XML_SCHEMA_TYPE_CHOICE:
4297 		fprintf(output, "CHOICE");
4298 		break;
4299 	    case XML_SCHEMA_TYPE_ALL:
4300 		fprintf(output, "ALL");
4301 		break;
4302 	    case XML_SCHEMA_TYPE_ANY:
4303 		fprintf(output, "ANY");
4304 		break;
4305 	    default:
4306 		fprintf(output, "UNKNOWN\n");
4307 		return;
4308 	}
4309     }
4310     if (particle->minOccurs != 1)
4311 	fprintf(output, " min: %d", particle->minOccurs);
4312     if (particle->maxOccurs >= UNBOUNDED)
4313 	fprintf(output, " max: unbounded");
4314     else if (particle->maxOccurs != 1)
4315 	fprintf(output, " max: %d", particle->maxOccurs);
4316     fprintf(output, "\n");
4317     if (term &&
4318 	((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
4319 	 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
4320 	 (term->type == XML_SCHEMA_TYPE_ALL)) &&
4321 	 (term->children != NULL)) {
4322 	xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
4323 	    output, depth +1);
4324     }
4325     if (particle->next != NULL)
4326 	xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
4327 		output, depth);
4328 }
4329 
4330 /**
4331  * xmlSchemaAttrUsesDump:
4332  * @uses:  attribute uses list
4333  * @output:  the file output
4334  *
4335  * Dumps a list of attribute use components.
4336  */
4337 static void
xmlSchemaAttrUsesDump(xmlSchemaItemListPtr uses,FILE * output)4338 xmlSchemaAttrUsesDump(xmlSchemaItemListPtr uses, FILE * output)
4339 {
4340     xmlSchemaAttributeUsePtr use;
4341     xmlSchemaAttributeUseProhibPtr prohib;
4342     xmlSchemaQNameRefPtr ref;
4343     const xmlChar *name, *tns;
4344     xmlChar *str = NULL;
4345     int i;
4346 
4347     if ((uses == NULL) || (uses->nbItems == 0))
4348         return;
4349 
4350     fprintf(output, "  attributes:\n");
4351     for (i = 0; i < uses->nbItems; i++) {
4352 	use = uses->items[i];
4353 	if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
4354 	    fprintf(output, "  [prohibition] ");
4355 	    prohib = (xmlSchemaAttributeUseProhibPtr) use;
4356 	    name = prohib->name;
4357 	    tns = prohib->targetNamespace;
4358 	} else if (use->type == XML_SCHEMA_EXTRA_QNAMEREF) {
4359 	    fprintf(output, "  [reference] ");
4360 	    ref = (xmlSchemaQNameRefPtr) use;
4361 	    name = ref->name;
4362 	    tns = ref->targetNamespace;
4363 	} else {
4364 	    fprintf(output, "  [use] ");
4365 	    name = WXS_ATTRUSE_DECL_NAME(use);
4366 	    tns = WXS_ATTRUSE_DECL_TNS(use);
4367 	}
4368 	fprintf(output, "'%s'\n",
4369 	    (const char *) xmlSchemaFormatQName(&str, tns, name));
4370 	FREE_AND_NULL(str);
4371     }
4372 }
4373 
4374 /**
4375  * xmlSchemaTypeDump:
4376  * @output:  the file output
4377  * @type:  a type structure
4378  *
4379  * Dump a SchemaType structure
4380  */
4381 static void
xmlSchemaTypeDump(xmlSchemaTypePtr type,FILE * output)4382 xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
4383 {
4384     if (type == NULL) {
4385         fprintf(output, "Type: NULL\n");
4386         return;
4387     }
4388     fprintf(output, "Type: ");
4389     if (type->name != NULL)
4390         fprintf(output, "'%s' ", type->name);
4391     else
4392         fprintf(output, "(no name) ");
4393     if (type->targetNamespace != NULL)
4394 	fprintf(output, "ns '%s' ", type->targetNamespace);
4395     switch (type->type) {
4396         case XML_SCHEMA_TYPE_BASIC:
4397             fprintf(output, "[basic] ");
4398             break;
4399         case XML_SCHEMA_TYPE_SIMPLE:
4400             fprintf(output, "[simple] ");
4401             break;
4402         case XML_SCHEMA_TYPE_COMPLEX:
4403             fprintf(output, "[complex] ");
4404             break;
4405         case XML_SCHEMA_TYPE_SEQUENCE:
4406             fprintf(output, "[sequence] ");
4407             break;
4408         case XML_SCHEMA_TYPE_CHOICE:
4409             fprintf(output, "[choice] ");
4410             break;
4411         case XML_SCHEMA_TYPE_ALL:
4412             fprintf(output, "[all] ");
4413             break;
4414         case XML_SCHEMA_TYPE_UR:
4415             fprintf(output, "[ur] ");
4416             break;
4417         case XML_SCHEMA_TYPE_RESTRICTION:
4418             fprintf(output, "[restriction] ");
4419             break;
4420         case XML_SCHEMA_TYPE_EXTENSION:
4421             fprintf(output, "[extension] ");
4422             break;
4423         default:
4424             fprintf(output, "[unknown type %d] ", type->type);
4425             break;
4426     }
4427     fprintf(output, "content: ");
4428     switch (type->contentType) {
4429         case XML_SCHEMA_CONTENT_UNKNOWN:
4430             fprintf(output, "[unknown] ");
4431             break;
4432         case XML_SCHEMA_CONTENT_EMPTY:
4433             fprintf(output, "[empty] ");
4434             break;
4435         case XML_SCHEMA_CONTENT_ELEMENTS:
4436             fprintf(output, "[element] ");
4437             break;
4438         case XML_SCHEMA_CONTENT_MIXED:
4439             fprintf(output, "[mixed] ");
4440             break;
4441         case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
4442 	/* not used. */
4443             break;
4444         case XML_SCHEMA_CONTENT_BASIC:
4445             fprintf(output, "[basic] ");
4446             break;
4447         case XML_SCHEMA_CONTENT_SIMPLE:
4448             fprintf(output, "[simple] ");
4449             break;
4450         case XML_SCHEMA_CONTENT_ANY:
4451             fprintf(output, "[any] ");
4452             break;
4453     }
4454     fprintf(output, "\n");
4455     if (type->base != NULL) {
4456         fprintf(output, "  base type: '%s'", type->base);
4457 	if (type->baseNs != NULL)
4458 	    fprintf(output, " ns '%s'\n", type->baseNs);
4459 	else
4460 	    fprintf(output, "\n");
4461     }
4462     if (type->attrUses != NULL)
4463 	xmlSchemaAttrUsesDump(type->attrUses, output);
4464     if (type->annot != NULL)
4465         xmlSchemaAnnotDump(output, type->annot);
4466 #ifdef DUMP_CONTENT_MODEL
4467     if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
4468 	(type->subtypes != NULL)) {
4469 	xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
4470 	    output, 1);
4471     }
4472 #endif
4473 }
4474 
4475 /**
4476  * xmlSchemaDump:
4477  * @output:  the file output
4478  * @schema:  a schema structure
4479  *
4480  * Dump a Schema structure.
4481  */
4482 void
xmlSchemaDump(FILE * output,xmlSchemaPtr schema)4483 xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
4484 {
4485     if (output == NULL)
4486         return;
4487     if (schema == NULL) {
4488         fprintf(output, "Schemas: NULL\n");
4489         return;
4490     }
4491     fprintf(output, "Schemas: ");
4492     if (schema->name != NULL)
4493         fprintf(output, "%s, ", schema->name);
4494     else
4495         fprintf(output, "no name, ");
4496     if (schema->targetNamespace != NULL)
4497         fprintf(output, "%s", (const char *) schema->targetNamespace);
4498     else
4499         fprintf(output, "no target namespace");
4500     fprintf(output, "\n");
4501     if (schema->annot != NULL)
4502         xmlSchemaAnnotDump(output, schema->annot);
4503     xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
4504                 output);
4505     xmlHashScanFull(schema->elemDecl,
4506                     (xmlHashScannerFull) xmlSchemaElementDump, output);
4507 }
4508 
4509 #ifdef DEBUG_IDC_NODE_TABLE
4510 /**
4511  * xmlSchemaDebugDumpIDCTable:
4512  * @vctxt: the WXS validation context
4513  *
4514  * Displays the current IDC table for debug purposes.
4515  */
4516 static void
xmlSchemaDebugDumpIDCTable(FILE * output,const xmlChar * namespaceName,const xmlChar * localName,xmlSchemaPSVIIDCBindingPtr bind)4517 xmlSchemaDebugDumpIDCTable(FILE * output,
4518 			   const xmlChar *namespaceName,
4519 			   const xmlChar *localName,
4520 			   xmlSchemaPSVIIDCBindingPtr bind)
4521 {
4522     xmlChar *str = NULL;
4523     const xmlChar *value;
4524     xmlSchemaPSVIIDCNodePtr tab;
4525     xmlSchemaPSVIIDCKeyPtr key;
4526     int i, j, res;
4527 
4528     fprintf(output, "IDC: TABLES on '%s'\n",
4529 	xmlSchemaFormatQName(&str, namespaceName, localName));
4530     FREE_AND_NULL(str)
4531 
4532     if (bind == NULL)
4533 	return;
4534     do {
4535 	fprintf(output, "IDC:   BINDING '%s' (%d)\n",
4536 	    xmlSchemaGetComponentQName(&str,
4537 		bind->definition), bind->nbNodes);
4538 	FREE_AND_NULL(str)
4539 	for (i = 0; i < bind->nbNodes; i++) {
4540 	    tab = bind->nodeTable[i];
4541 	    fprintf(output, "         ( ");
4542 	    for (j = 0; j < bind->definition->nbFields; j++) {
4543 		key = tab->keys[j];
4544 		if ((key != NULL) && (key->val != NULL)) {
4545 		    res = xmlSchemaGetCanonValue(key->val, &value);
4546 		    if (res >= 0)
4547 			fprintf(output, "'%s' ", value);
4548 		    else
4549 			fprintf(output, "CANON-VALUE-FAILED ");
4550 		    if (res == 0)
4551 			FREE_AND_NULL(value)
4552 		} else if (key != NULL)
4553 		    fprintf(output, "(no val), ");
4554 		else
4555 		    fprintf(output, "(key missing), ");
4556 	    }
4557 	    fprintf(output, ")\n");
4558 	}
4559 	if (bind->dupls && bind->dupls->nbItems) {
4560 	    fprintf(output, "IDC:     dupls (%d):\n", bind->dupls->nbItems);
4561 	    for (i = 0; i < bind->dupls->nbItems; i++) {
4562 		tab = bind->dupls->items[i];
4563 		fprintf(output, "         ( ");
4564 		for (j = 0; j < bind->definition->nbFields; j++) {
4565 		    key = tab->keys[j];
4566 		    if ((key != NULL) && (key->val != NULL)) {
4567 			res = xmlSchemaGetCanonValue(key->val, &value);
4568 			if (res >= 0)
4569 			    fprintf(output, "'%s' ", value);
4570 			else
4571 			    fprintf(output, "CANON-VALUE-FAILED ");
4572 			if (res == 0)
4573 			    FREE_AND_NULL(value)
4574 		    } else if (key != NULL)
4575 		    fprintf(output, "(no val), ");
4576 			else
4577 			    fprintf(output, "(key missing), ");
4578 		}
4579 		fprintf(output, ")\n");
4580 	    }
4581 	}
4582 	bind = bind->next;
4583     } while (bind != NULL);
4584 }
4585 #endif /* DEBUG_IDC */
4586 #endif /* LIBXML_OUTPUT_ENABLED */
4587 
4588 /************************************************************************
4589  *									*
4590  * 			Utilities					*
4591  *									*
4592  ************************************************************************/
4593 
4594 /**
4595  * xmlSchemaGetPropNode:
4596  * @node: the element node
4597  * @name: the name of the attribute
4598  *
4599  * Seeks an attribute with a name of @name in
4600  * no namespace.
4601  *
4602  * Returns the attribute or NULL if not present.
4603  */
4604 static xmlAttrPtr
xmlSchemaGetPropNode(xmlNodePtr node,const char * name)4605 xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
4606 {
4607     xmlAttrPtr prop;
4608 
4609     if ((node == NULL) || (name == NULL))
4610 	return(NULL);
4611     prop = node->properties;
4612     while (prop != NULL) {
4613         if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
4614 	    return(prop);
4615 	prop = prop->next;
4616     }
4617     return (NULL);
4618 }
4619 
4620 /**
4621  * xmlSchemaGetPropNodeNs:
4622  * @node: the element node
4623  * @uri: the uri
4624  * @name: the name of the attribute
4625  *
4626  * Seeks an attribute with a local name of @name and
4627  * a namespace URI of @uri.
4628  *
4629  * Returns the attribute or NULL if not present.
4630  */
4631 static xmlAttrPtr
xmlSchemaGetPropNodeNs(xmlNodePtr node,const char * uri,const char * name)4632 xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
4633 {
4634     xmlAttrPtr prop;
4635 
4636     if ((node == NULL) || (name == NULL))
4637 	return(NULL);
4638     prop = node->properties;
4639     while (prop != NULL) {
4640 	if ((prop->ns != NULL) &&
4641 	    xmlStrEqual(prop->name, BAD_CAST name) &&
4642 	    xmlStrEqual(prop->ns->href, BAD_CAST uri))
4643 	    return(prop);
4644 	prop = prop->next;
4645     }
4646     return (NULL);
4647 }
4648 
4649 static const xmlChar *
xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node)4650 xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
4651 {
4652     xmlChar *val;
4653     const xmlChar *ret;
4654 
4655     val = xmlNodeGetContent(node);
4656     if (val == NULL)
4657 	val = xmlStrdup((xmlChar *)"");
4658     ret = xmlDictLookup(ctxt->dict, val, -1);
4659     xmlFree(val);
4660     return(ret);
4661 }
4662 
4663 static const xmlChar *
xmlSchemaGetNodeContentNoDict(xmlNodePtr node)4664 xmlSchemaGetNodeContentNoDict(xmlNodePtr node)
4665 {
4666     return((const xmlChar*) xmlNodeGetContent(node));
4667 }
4668 
4669 /**
4670  * xmlSchemaGetProp:
4671  * @ctxt: the parser context
4672  * @node: the node
4673  * @name: the property name
4674  *
4675  * Read a attribute value and internalize the string
4676  *
4677  * Returns the string or NULL if not present.
4678  */
4679 static const xmlChar *
xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,const char * name)4680 xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4681                  const char *name)
4682 {
4683     xmlChar *val;
4684     const xmlChar *ret;
4685 
4686     val = xmlGetNoNsProp(node, BAD_CAST name);
4687     if (val == NULL)
4688         return(NULL);
4689     ret = xmlDictLookup(ctxt->dict, val, -1);
4690     xmlFree(val);
4691     return(ret);
4692 }
4693 
4694 /************************************************************************
4695  * 									*
4696  * 			Parsing functions				*
4697  * 									*
4698  ************************************************************************/
4699 
4700 #define WXS_FIND_GLOBAL_ITEM(slot)			\
4701     if (xmlStrEqual(nsName, schema->targetNamespace)) { \
4702 	ret = xmlHashLookup(schema->slot, name); \
4703 	if (ret != NULL) goto exit; \
4704     } \
4705     if (xmlHashSize(schema->schemasImports) > 1) { \
4706 	xmlSchemaImportPtr import; \
4707 	if (nsName == NULL) \
4708 	    import = xmlHashLookup(schema->schemasImports, \
4709 		XML_SCHEMAS_NO_NAMESPACE); \
4710 	else \
4711 	    import = xmlHashLookup(schema->schemasImports, nsName); \
4712 	if (import == NULL) \
4713 	    goto exit; \
4714 	ret = xmlHashLookup(import->schema->slot, name); \
4715     }
4716 
4717 /**
4718  * xmlSchemaGetElem:
4719  * @schema:  the schema context
4720  * @name:  the element name
4721  * @ns:  the element namespace
4722  *
4723  * Lookup a global element declaration in the schema.
4724  *
4725  * Returns the element declaration or NULL if not found.
4726  */
4727 static xmlSchemaElementPtr
xmlSchemaGetElem(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4728 xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
4729                  const xmlChar * nsName)
4730 {
4731     xmlSchemaElementPtr ret = NULL;
4732 
4733     if ((name == NULL) || (schema == NULL))
4734         return(NULL);
4735     if (schema != NULL) {
4736 	WXS_FIND_GLOBAL_ITEM(elemDecl)
4737     }
4738 exit:
4739 #ifdef DEBUG
4740     if (ret == NULL) {
4741         if (nsName == NULL)
4742             fprintf(stderr, "Unable to lookup element decl. %s", name);
4743         else
4744             fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
4745                     nsName);
4746     }
4747 #endif
4748     return (ret);
4749 }
4750 
4751 /**
4752  * xmlSchemaGetType:
4753  * @schema:  the main schema
4754  * @name:  the type's name
4755  * nsName:  the type's namespace
4756  *
4757  * Lookup a type in the schemas or the predefined types
4758  *
4759  * Returns the group definition or NULL if not found.
4760  */
4761 static xmlSchemaTypePtr
xmlSchemaGetType(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4762 xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
4763                  const xmlChar * nsName)
4764 {
4765     xmlSchemaTypePtr ret = NULL;
4766 
4767     if (name == NULL)
4768         return (NULL);
4769     /* First try the built-in types. */
4770     if ((nsName != NULL) && xmlStrEqual(nsName, xmlSchemaNs)) {
4771 	ret = xmlSchemaGetPredefinedType(name, nsName);
4772 	if (ret != NULL)
4773 	    goto exit;
4774 	/*
4775 	* Note that we try the parsed schemas as well here
4776 	* since one might have parsed the S4S, which contain more
4777 	* than the built-in types.
4778 	* TODO: Can we optimize this?
4779 	*/
4780     }
4781     if (schema != NULL) {
4782 	WXS_FIND_GLOBAL_ITEM(typeDecl)
4783     }
4784 exit:
4785 
4786 #ifdef DEBUG
4787     if (ret == NULL) {
4788         if (nsName == NULL)
4789             fprintf(stderr, "Unable to lookup type %s", name);
4790         else
4791             fprintf(stderr, "Unable to lookup type %s:%s", name,
4792                     nsName);
4793     }
4794 #endif
4795     return (ret);
4796 }
4797 
4798 /**
4799  * xmlSchemaGetAttributeDecl:
4800  * @schema:  the context of the schema
4801  * @name:  the name of the attribute
4802  * @ns:  the target namespace of the attribute
4803  *
4804  * Lookup a an attribute in the schema or imported schemas
4805  *
4806  * Returns the attribute declaration or NULL if not found.
4807  */
4808 static xmlSchemaAttributePtr
xmlSchemaGetAttributeDecl(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4809 xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
4810                  const xmlChar * nsName)
4811 {
4812     xmlSchemaAttributePtr ret = NULL;
4813 
4814     if ((name == NULL) || (schema == NULL))
4815         return (NULL);
4816     if (schema != NULL) {
4817 	WXS_FIND_GLOBAL_ITEM(attrDecl)
4818     }
4819 exit:
4820 #ifdef DEBUG
4821     if (ret == NULL) {
4822         if (nsName == NULL)
4823             fprintf(stderr, "Unable to lookup attribute %s", name);
4824         else
4825             fprintf(stderr, "Unable to lookup attribute %s:%s", name,
4826                     nsName);
4827     }
4828 #endif
4829     return (ret);
4830 }
4831 
4832 /**
4833  * xmlSchemaGetAttributeGroup:
4834  * @schema:  the context of the schema
4835  * @name:  the name of the attribute group
4836  * @ns:  the target namespace of the attribute group
4837  *
4838  * Lookup a an attribute group in the schema or imported schemas
4839  *
4840  * Returns the attribute group definition or NULL if not found.
4841  */
4842 static xmlSchemaAttributeGroupPtr
xmlSchemaGetAttributeGroup(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4843 xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
4844                  const xmlChar * nsName)
4845 {
4846     xmlSchemaAttributeGroupPtr ret = NULL;
4847 
4848     if ((name == NULL) || (schema == NULL))
4849         return (NULL);
4850     if (schema != NULL) {
4851 	WXS_FIND_GLOBAL_ITEM(attrgrpDecl)
4852     }
4853 exit:
4854     /* TODO:
4855     if ((ret != NULL) && (ret->redef != NULL)) {
4856 	* Return the last redefinition. *
4857 	ret = ret->redef;
4858     }
4859     */
4860 #ifdef DEBUG
4861     if (ret == NULL) {
4862         if (nsName == NULL)
4863             fprintf(stderr, "Unable to lookup attribute group %s", name);
4864         else
4865             fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
4866                     nsName);
4867     }
4868 #endif
4869     return (ret);
4870 }
4871 
4872 /**
4873  * xmlSchemaGetGroup:
4874  * @schema:  the context of the schema
4875  * @name:  the name of the group
4876  * @ns:  the target namespace of the group
4877  *
4878  * Lookup a group in the schema or imported schemas
4879  *
4880  * Returns the group definition or NULL if not found.
4881  */
4882 static xmlSchemaModelGroupDefPtr
xmlSchemaGetGroup(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4883 xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
4884                  const xmlChar * nsName)
4885 {
4886     xmlSchemaModelGroupDefPtr ret = NULL;
4887 
4888     if ((name == NULL) || (schema == NULL))
4889         return (NULL);
4890     if (schema != NULL) {
4891 	WXS_FIND_GLOBAL_ITEM(groupDecl)
4892     }
4893 exit:
4894 
4895 #ifdef DEBUG
4896     if (ret == NULL) {
4897         if (nsName == NULL)
4898             fprintf(stderr, "Unable to lookup group %s", name);
4899         else
4900             fprintf(stderr, "Unable to lookup group %s:%s", name,
4901                     nsName);
4902     }
4903 #endif
4904     return (ret);
4905 }
4906 
4907 static xmlSchemaNotationPtr
xmlSchemaGetNotation(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4908 xmlSchemaGetNotation(xmlSchemaPtr schema,
4909 		     const xmlChar *name,
4910 		     const xmlChar *nsName)
4911 {
4912     xmlSchemaNotationPtr ret = NULL;
4913 
4914     if ((name == NULL) || (schema == NULL))
4915         return (NULL);
4916     if (schema != NULL) {
4917 	WXS_FIND_GLOBAL_ITEM(notaDecl)
4918     }
4919 exit:
4920     return (ret);
4921 }
4922 
4923 static xmlSchemaIDCPtr
xmlSchemaGetIDC(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4924 xmlSchemaGetIDC(xmlSchemaPtr schema,
4925 		const xmlChar *name,
4926 		const xmlChar *nsName)
4927 {
4928     xmlSchemaIDCPtr ret = NULL;
4929 
4930     if ((name == NULL) || (schema == NULL))
4931         return (NULL);
4932     if (schema != NULL) {
4933 	WXS_FIND_GLOBAL_ITEM(idcDef)
4934     }
4935 exit:
4936     return (ret);
4937 }
4938 
4939 /**
4940  * xmlSchemaGetNamedComponent:
4941  * @schema:  the schema
4942  * @name:  the name of the group
4943  * @ns:  the target namespace of the group
4944  *
4945  * Lookup a group in the schema or imported schemas
4946  *
4947  * Returns the group definition or NULL if not found.
4948  */
4949 static xmlSchemaBasicItemPtr
xmlSchemaGetNamedComponent(xmlSchemaPtr schema,xmlSchemaTypeType itemType,const xmlChar * name,const xmlChar * targetNs)4950 xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
4951 			   xmlSchemaTypeType itemType,
4952 			   const xmlChar *name,
4953 			   const xmlChar *targetNs)
4954 {
4955     switch (itemType) {
4956 	case XML_SCHEMA_TYPE_GROUP:
4957 	    return ((xmlSchemaBasicItemPtr) xmlSchemaGetGroup(schema,
4958 		name, targetNs));
4959 	case XML_SCHEMA_TYPE_ELEMENT:
4960 	    return ((xmlSchemaBasicItemPtr) xmlSchemaGetElem(schema,
4961 		name, targetNs));
4962 	default:
4963 	    TODO
4964 	    return (NULL);
4965     }
4966 }
4967 
4968 /************************************************************************
4969  * 									*
4970  * 			Parsing functions				*
4971  * 									*
4972  ************************************************************************/
4973 
4974 #define IS_BLANK_NODE(n)						\
4975     (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
4976 
4977 /**
4978  * xmlSchemaIsBlank:
4979  * @str:  a string
4980  * @len: the length of the string or -1
4981  *
4982  * Check if a string is ignorable
4983  *
4984  * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
4985  */
4986 static int
xmlSchemaIsBlank(xmlChar * str,int len)4987 xmlSchemaIsBlank(xmlChar * str, int len)
4988 {
4989     if (str == NULL)
4990         return (1);
4991     if (len < 0) {
4992 	while (*str != 0) {
4993 	    if (!(IS_BLANK_CH(*str)))
4994 		return (0);
4995 	    str++;
4996 	}
4997     } else while ((*str != 0) && (len != 0)) {
4998 	if (!(IS_BLANK_CH(*str)))
4999 	    return (0);
5000 	str++;
5001 	len--;
5002     }
5003 
5004     return (1);
5005 }
5006 
5007 #define WXS_COMP_NAME(c, t) ((t) (c))->name
5008 #define WXS_COMP_TNS(c, t) ((t) (c))->targetNamespace
5009 /*
5010 * xmlSchemaFindRedefCompInGraph:
5011 * ATTENTION TODO: This uses pointer comp. for strings.
5012 */
5013 static xmlSchemaBasicItemPtr
xmlSchemaFindRedefCompInGraph(xmlSchemaBucketPtr bucket,xmlSchemaTypeType type,const xmlChar * name,const xmlChar * nsName)5014 xmlSchemaFindRedefCompInGraph(xmlSchemaBucketPtr bucket,
5015 			      xmlSchemaTypeType type,
5016 			      const xmlChar *name,
5017 			      const xmlChar *nsName)
5018 {
5019     xmlSchemaBasicItemPtr ret;
5020     int i;
5021 
5022     if ((bucket == NULL) || (name == NULL))
5023 	return(NULL);
5024     if ((bucket->globals == NULL) ||
5025 	(bucket->globals->nbItems == 0))
5026 	goto subschemas;
5027     /*
5028     * Search in global components.
5029     */
5030     for (i = 0; i < bucket->globals->nbItems; i++) {
5031 	ret = bucket->globals->items[i];
5032 	if (ret->type == type) {
5033 	    switch (type) {
5034 		case XML_SCHEMA_TYPE_COMPLEX:
5035 		case XML_SCHEMA_TYPE_SIMPLE:
5036 		    if ((WXS_COMP_NAME(ret, xmlSchemaTypePtr) == name) &&
5037 			(WXS_COMP_TNS(ret, xmlSchemaTypePtr) ==
5038 			nsName))
5039 		    {
5040 			return(ret);
5041 		    }
5042 		    break;
5043 		case XML_SCHEMA_TYPE_GROUP:
5044 		    if ((WXS_COMP_NAME(ret,
5045 			    xmlSchemaModelGroupDefPtr) == name) &&
5046 			(WXS_COMP_TNS(ret,
5047 			    xmlSchemaModelGroupDefPtr) == nsName))
5048 		    {
5049 			return(ret);
5050 		    }
5051 		    break;
5052 		case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
5053 		    if ((WXS_COMP_NAME(ret,
5054 			    xmlSchemaAttributeGroupPtr) == name) &&
5055 			(WXS_COMP_TNS(ret,
5056 			    xmlSchemaAttributeGroupPtr) == nsName))
5057 		    {
5058 			return(ret);
5059 		    }
5060 		    break;
5061 		default:
5062 		    /* Should not be hit. */
5063 		    return(NULL);
5064 	    }
5065 	}
5066     }
5067 subschemas:
5068     /*
5069     * Process imported/included schemas.
5070     */
5071     if (bucket->relations != NULL) {
5072 	xmlSchemaSchemaRelationPtr rel = bucket->relations;
5073 
5074 	/*
5075 	* TODO: Marking the bucket will not avoid multiple searches
5076 	* in the same schema, but avoids at least circularity.
5077 	*/
5078 	bucket->flags |= XML_SCHEMA_BUCKET_MARKED;
5079 	do {
5080 	    if ((rel->bucket != NULL) &&
5081 		((rel->bucket->flags & XML_SCHEMA_BUCKET_MARKED) == 0)) {
5082 		ret = xmlSchemaFindRedefCompInGraph(rel->bucket,
5083 		    type, name, nsName);
5084 		if (ret != NULL)
5085 		    return(ret);
5086 	    }
5087 	    rel = rel->next;
5088 	} while (rel != NULL);
5089 	 bucket->flags ^= XML_SCHEMA_BUCKET_MARKED;
5090     }
5091     return(NULL);
5092 }
5093 
5094 /**
5095  * xmlSchemaAddNotation:
5096  * @ctxt:  a schema parser context
5097  * @schema:  the schema being built
5098  * @name:  the item name
5099  *
5100  * Add an XML schema annotation declaration
5101  * *WARNING* this interface is highly subject to change
5102  *
5103  * Returns the new struture or NULL in case of error
5104  */
5105 static xmlSchemaNotationPtr
xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node ATTRIBUTE_UNUSED)5106 xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5107                      const xmlChar *name, const xmlChar *nsName,
5108 		     xmlNodePtr node ATTRIBUTE_UNUSED)
5109 {
5110     xmlSchemaNotationPtr ret = NULL;
5111 
5112     if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5113         return (NULL);
5114 
5115     ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
5116     if (ret == NULL) {
5117         xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
5118         return (NULL);
5119     }
5120     memset(ret, 0, sizeof(xmlSchemaNotation));
5121     ret->type = XML_SCHEMA_TYPE_NOTATION;
5122     ret->name = name;
5123     ret->targetNamespace = nsName;
5124     /* TODO: do we need the node to be set?
5125     * ret->node = node;*/
5126     WXS_ADD_GLOBAL(ctxt, ret);
5127     return (ret);
5128 }
5129 
5130 /**
5131  * xmlSchemaAddAttribute:
5132  * @ctxt:  a schema parser context
5133  * @schema:  the schema being built
5134  * @name:  the item name
5135  * @namespace:  the namespace
5136  *
5137  * Add an XML schema Attrribute declaration
5138  * *WARNING* this interface is highly subject to change
5139  *
5140  * Returns the new struture or NULL in case of error
5141  */
5142 static xmlSchemaAttributePtr
xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node,int topLevel)5143 xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5144                       const xmlChar * name, const xmlChar * nsName,
5145 		      xmlNodePtr node, int topLevel)
5146 {
5147     xmlSchemaAttributePtr ret = NULL;
5148 
5149     if ((ctxt == NULL) || (schema == NULL))
5150         return (NULL);
5151 
5152     ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
5153     if (ret == NULL) {
5154         xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
5155         return (NULL);
5156     }
5157     memset(ret, 0, sizeof(xmlSchemaAttribute));
5158     ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
5159     ret->node = node;
5160     ret->name = name;
5161     ret->targetNamespace = nsName;
5162 
5163     if (topLevel)
5164 	WXS_ADD_GLOBAL(ctxt, ret);
5165     else
5166 	WXS_ADD_LOCAL(ctxt, ret);
5167     WXS_ADD_PENDING(ctxt, ret);
5168     return (ret);
5169 }
5170 
5171 /**
5172  * xmlSchemaAddAttributeUse:
5173  * @ctxt:  a schema parser context
5174  * @schema:  the schema being built
5175  * @name:  the item name
5176  * @namespace:  the namespace
5177  *
5178  * Add an XML schema Attrribute declaration
5179  * *WARNING* this interface is highly subject to change
5180  *
5181  * Returns the new struture or NULL in case of error
5182  */
5183 static xmlSchemaAttributeUsePtr
xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt,xmlNodePtr node)5184 xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt,
5185 			 xmlNodePtr node)
5186 {
5187     xmlSchemaAttributeUsePtr ret = NULL;
5188 
5189     if (pctxt == NULL)
5190         return (NULL);
5191 
5192     ret = (xmlSchemaAttributeUsePtr) xmlMalloc(sizeof(xmlSchemaAttributeUse));
5193     if (ret == NULL) {
5194         xmlSchemaPErrMemory(pctxt, "allocating attribute", NULL);
5195         return (NULL);
5196     }
5197     memset(ret, 0, sizeof(xmlSchemaAttributeUse));
5198     ret->type = XML_SCHEMA_TYPE_ATTRIBUTE_USE;
5199     ret->node = node;
5200 
5201     WXS_ADD_LOCAL(pctxt, ret);
5202     return (ret);
5203 }
5204 
5205 /*
5206 * xmlSchemaAddRedef:
5207 *
5208 * Adds a redefinition information. This is used at a later stage to:
5209 * resolve references to the redefined components and to check constraints.
5210 */
5211 static xmlSchemaRedefPtr
xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBucketPtr targetBucket,void * item,const xmlChar * refName,const xmlChar * refTargetNs)5212 xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt,
5213 		  xmlSchemaBucketPtr targetBucket,
5214 		  void *item,
5215 		  const xmlChar *refName,
5216 		  const xmlChar *refTargetNs)
5217 {
5218     xmlSchemaRedefPtr ret;
5219 
5220     ret = (xmlSchemaRedefPtr)
5221 	xmlMalloc(sizeof(xmlSchemaRedef));
5222     if (ret == NULL) {
5223 	xmlSchemaPErrMemory(pctxt,
5224 	    "allocating redefinition info", NULL);
5225 	return (NULL);
5226     }
5227     memset(ret, 0, sizeof(xmlSchemaRedef));
5228     ret->item = item;
5229     ret->targetBucket = targetBucket;
5230     ret->refName = refName;
5231     ret->refTargetNs = refTargetNs;
5232     if (WXS_CONSTRUCTOR(pctxt)->redefs == NULL)
5233 	WXS_CONSTRUCTOR(pctxt)->redefs = ret;
5234     else
5235 	WXS_CONSTRUCTOR(pctxt)->lastRedef->next = ret;
5236     WXS_CONSTRUCTOR(pctxt)->lastRedef = ret;
5237 
5238     return (ret);
5239 }
5240 
5241 /**
5242  * xmlSchemaAddAttributeGroupDefinition:
5243  * @ctxt:  a schema parser context
5244  * @schema:  the schema being built
5245  * @name:  the item name
5246  * @nsName:  the target namespace
5247  * @node: the corresponding node
5248  *
5249  * Add an XML schema Attrribute Group definition.
5250  *
5251  * Returns the new struture or NULL in case of error
5252  */
5253 static xmlSchemaAttributeGroupPtr
xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema ATTRIBUTE_UNUSED,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node)5254 xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
5255                            xmlSchemaPtr schema ATTRIBUTE_UNUSED,
5256 			   const xmlChar *name,
5257 			   const xmlChar *nsName,
5258 			   xmlNodePtr node)
5259 {
5260     xmlSchemaAttributeGroupPtr ret = NULL;
5261 
5262     if ((pctxt == NULL) || (name == NULL))
5263         return (NULL);
5264 
5265     ret = (xmlSchemaAttributeGroupPtr)
5266         xmlMalloc(sizeof(xmlSchemaAttributeGroup));
5267     if (ret == NULL) {
5268 	xmlSchemaPErrMemory(pctxt, "allocating attribute group", NULL);
5269 	return (NULL);
5270     }
5271     memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
5272     ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5273     ret->name = name;
5274     ret->targetNamespace = nsName;
5275     ret->node = node;
5276 
5277     /* TODO: Remove the flag. */
5278     ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5279     if (pctxt->isRedefine) {
5280 	pctxt->redef = xmlSchemaAddRedef(pctxt, pctxt->redefined,
5281 	    ret, name, nsName);
5282 	if (pctxt->redef == NULL) {
5283 	    xmlFree(ret);
5284 	    return(NULL);
5285 	}
5286 	pctxt->redefCounter = 0;
5287     }
5288     WXS_ADD_GLOBAL(pctxt, ret);
5289     WXS_ADD_PENDING(pctxt, ret);
5290     return (ret);
5291 }
5292 
5293 /**
5294  * xmlSchemaAddElement:
5295  * @ctxt:  a schema parser context
5296  * @schema:  the schema being built
5297  * @name:  the type name
5298  * @namespace:  the type namespace
5299  *
5300  * Add an XML schema Element declaration
5301  * *WARNING* this interface is highly subject to change
5302  *
5303  * Returns the new struture or NULL in case of error
5304  */
5305 static xmlSchemaElementPtr
xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node,int topLevel)5306 xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt,
5307                     const xmlChar * name, const xmlChar * nsName,
5308 		    xmlNodePtr node, int topLevel)
5309 {
5310     xmlSchemaElementPtr ret = NULL;
5311 
5312     if ((ctxt == NULL) || (name == NULL))
5313         return (NULL);
5314 
5315     ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
5316     if (ret == NULL) {
5317         xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
5318         return (NULL);
5319     }
5320     memset(ret, 0, sizeof(xmlSchemaElement));
5321     ret->type = XML_SCHEMA_TYPE_ELEMENT;
5322     ret->name = name;
5323     ret->targetNamespace = nsName;
5324     ret->node = node;
5325 
5326     if (topLevel)
5327 	WXS_ADD_GLOBAL(ctxt, ret);
5328     else
5329 	WXS_ADD_LOCAL(ctxt, ret);
5330     WXS_ADD_PENDING(ctxt, ret);
5331     return (ret);
5332 }
5333 
5334 /**
5335  * xmlSchemaAddType:
5336  * @ctxt:  a schema parser context
5337  * @schema:  the schema being built
5338  * @name:  the item name
5339  * @namespace:  the namespace
5340  *
5341  * Add an XML schema item
5342  * *WARNING* this interface is highly subject to change
5343  *
5344  * Returns the new struture or NULL in case of error
5345  */
5346 static xmlSchemaTypePtr
xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaTypeType type,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node,int topLevel)5347 xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5348 		 xmlSchemaTypeType type,
5349                  const xmlChar * name, const xmlChar * nsName,
5350 		 xmlNodePtr node, int topLevel)
5351 {
5352     xmlSchemaTypePtr ret = NULL;
5353 
5354     if ((ctxt == NULL) || (schema == NULL))
5355         return (NULL);
5356 
5357     ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
5358     if (ret == NULL) {
5359         xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
5360         return (NULL);
5361     }
5362     memset(ret, 0, sizeof(xmlSchemaType));
5363     ret->type = type;
5364     ret->name = name;
5365     ret->targetNamespace = nsName;
5366     ret->node = node;
5367     if (topLevel) {
5368 	if (ctxt->isRedefine) {
5369 	    ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5370 		ret, name, nsName);
5371 	    if (ctxt->redef == NULL) {
5372 		xmlFree(ret);
5373 		return(NULL);
5374 	    }
5375 	    ctxt->redefCounter = 0;
5376 	}
5377 	WXS_ADD_GLOBAL(ctxt, ret);
5378     } else
5379 	WXS_ADD_LOCAL(ctxt, ret);
5380     WXS_ADD_PENDING(ctxt, ret);
5381     return (ret);
5382 }
5383 
5384 static xmlSchemaQNameRefPtr
xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypeType refType,const xmlChar * refName,const xmlChar * refNs)5385 xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt,
5386 		     xmlSchemaTypeType refType,
5387 		     const xmlChar *refName,
5388 		     const xmlChar *refNs)
5389 {
5390     xmlSchemaQNameRefPtr ret;
5391 
5392     ret = (xmlSchemaQNameRefPtr)
5393 	xmlMalloc(sizeof(xmlSchemaQNameRef));
5394     if (ret == NULL) {
5395 	xmlSchemaPErrMemory(pctxt,
5396 	    "allocating QName reference item", NULL);
5397 	return (NULL);
5398     }
5399     ret->node = NULL;
5400     ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
5401     ret->name = refName;
5402     ret->targetNamespace = refNs;
5403     ret->item = NULL;
5404     ret->itemType = refType;
5405     /*
5406     * Store the reference item in the schema.
5407     */
5408     WXS_ADD_LOCAL(pctxt, ret);
5409     return (ret);
5410 }
5411 
5412 static xmlSchemaAttributeUseProhibPtr
xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt)5413 xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt)
5414 {
5415     xmlSchemaAttributeUseProhibPtr ret;
5416 
5417     ret = (xmlSchemaAttributeUseProhibPtr)
5418 	xmlMalloc(sizeof(xmlSchemaAttributeUseProhib));
5419     if (ret == NULL) {
5420 	xmlSchemaPErrMemory(pctxt,
5421 	    "allocating attribute use prohibition", NULL);
5422 	return (NULL);
5423     }
5424     memset(ret, 0, sizeof(xmlSchemaAttributeUseProhib));
5425     ret->type = XML_SCHEMA_EXTRA_ATTR_USE_PROHIB;
5426     WXS_ADD_LOCAL(pctxt, ret);
5427     return (ret);
5428 }
5429 
5430 
5431 /**
5432  * xmlSchemaAddModelGroup:
5433  * @ctxt:  a schema parser context
5434  * @schema:  the schema being built
5435  * @type: the "compositor" type of the model group
5436  * @node: the node in the schema doc
5437  *
5438  * Adds a schema model group
5439  * *WARNING* this interface is highly subject to change
5440  *
5441  * Returns the new struture or NULL in case of error
5442  */
5443 static xmlSchemaModelGroupPtr
xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaTypeType type,xmlNodePtr node)5444 xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt,
5445 		       xmlSchemaPtr schema,
5446 		       xmlSchemaTypeType type,
5447 		       xmlNodePtr node)
5448 {
5449     xmlSchemaModelGroupPtr ret = NULL;
5450 
5451     if ((ctxt == NULL) || (schema == NULL))
5452         return (NULL);
5453 
5454     ret = (xmlSchemaModelGroupPtr)
5455 	xmlMalloc(sizeof(xmlSchemaModelGroup));
5456     if (ret == NULL) {
5457 	xmlSchemaPErrMemory(ctxt, "allocating model group component",
5458 	    NULL);
5459 	return (NULL);
5460     }
5461     memset(ret, 0, sizeof(xmlSchemaModelGroup));
5462     ret->type = type;
5463     ret->node = node;
5464     WXS_ADD_LOCAL(ctxt, ret);
5465     if ((type == XML_SCHEMA_TYPE_SEQUENCE) ||
5466 	(type == XML_SCHEMA_TYPE_CHOICE))
5467 	WXS_ADD_PENDING(ctxt, ret);
5468     return (ret);
5469 }
5470 
5471 
5472 /**
5473  * xmlSchemaAddParticle:
5474  * @ctxt:  a schema parser context
5475  * @schema:  the schema being built
5476  * @node: the corresponding node in the schema doc
5477  * @min: the minOccurs
5478  * @max: the maxOccurs
5479  *
5480  * Adds an XML schema particle component.
5481  * *WARNING* this interface is highly subject to change
5482  *
5483  * Returns the new struture or NULL in case of error
5484  */
5485 static xmlSchemaParticlePtr
xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int min,int max)5486 xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt,
5487 		     xmlNodePtr node, int min, int max)
5488 {
5489     xmlSchemaParticlePtr ret = NULL;
5490     if (ctxt == NULL)
5491         return (NULL);
5492 
5493 #ifdef DEBUG
5494     fprintf(stderr, "Adding particle component\n");
5495 #endif
5496     ret = (xmlSchemaParticlePtr)
5497 	xmlMalloc(sizeof(xmlSchemaParticle));
5498     if (ret == NULL) {
5499 	xmlSchemaPErrMemory(ctxt, "allocating particle component",
5500 	    NULL);
5501 	return (NULL);
5502     }
5503     ret->type = XML_SCHEMA_TYPE_PARTICLE;
5504     ret->annot = NULL;
5505     ret->node = node;
5506     ret->minOccurs = min;
5507     ret->maxOccurs = max;
5508     ret->next = NULL;
5509     ret->children = NULL;
5510 
5511     WXS_ADD_LOCAL(ctxt, ret);
5512     /*
5513     * Note that addition to pending components will be done locally
5514     * to the specific parsing function, since the most particles
5515     * need not to be fixed up (i.e. the reference to be resolved).
5516     * REMOVED: WXS_ADD_PENDING(ctxt, ret);
5517     */
5518     return (ret);
5519 }
5520 
5521 /**
5522  * xmlSchemaAddModelGroupDefinition:
5523  * @ctxt:  a schema validation context
5524  * @schema:  the schema being built
5525  * @name:  the group name
5526  *
5527  * Add an XML schema Group definition
5528  *
5529  * Returns the new struture or NULL in case of error
5530  */
5531 static xmlSchemaModelGroupDefPtr
xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node)5532 xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
5533 				 xmlSchemaPtr schema,
5534 				 const xmlChar *name,
5535 				 const xmlChar *nsName,
5536 				 xmlNodePtr node)
5537 {
5538     xmlSchemaModelGroupDefPtr ret = NULL;
5539 
5540     if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5541         return (NULL);
5542 
5543     ret = (xmlSchemaModelGroupDefPtr)
5544 	xmlMalloc(sizeof(xmlSchemaModelGroupDef));
5545     if (ret == NULL) {
5546         xmlSchemaPErrMemory(ctxt, "adding group", NULL);
5547         return (NULL);
5548     }
5549     memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
5550     ret->name = name;
5551     ret->type = XML_SCHEMA_TYPE_GROUP;
5552     ret->node = node;
5553     ret->targetNamespace = nsName;
5554 
5555     if (ctxt->isRedefine) {
5556 	ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5557 	    ret, name, nsName);
5558 	if (ctxt->redef == NULL) {
5559 	    xmlFree(ret);
5560 	    return(NULL);
5561 	}
5562 	ctxt->redefCounter = 0;
5563     }
5564     WXS_ADD_GLOBAL(ctxt, ret);
5565     WXS_ADD_PENDING(ctxt, ret);
5566     return (ret);
5567 }
5568 
5569 /**
5570  * xmlSchemaNewWildcardNs:
5571  * @ctxt:  a schema validation context
5572  *
5573  * Creates a new wildcard namespace constraint.
5574  *
5575  * Returns the new struture or NULL in case of error
5576  */
5577 static xmlSchemaWildcardNsPtr
xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)5578 xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
5579 {
5580     xmlSchemaWildcardNsPtr ret;
5581 
5582     ret = (xmlSchemaWildcardNsPtr)
5583 	xmlMalloc(sizeof(xmlSchemaWildcardNs));
5584     if (ret == NULL) {
5585 	xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
5586 	return (NULL);
5587     }
5588     ret->value = NULL;
5589     ret->next = NULL;
5590     return (ret);
5591 }
5592 
5593 static xmlSchemaIDCPtr
xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName,int category,xmlNodePtr node)5594 xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5595                   const xmlChar *name, const xmlChar *nsName,
5596 		  int category, xmlNodePtr node)
5597 {
5598     xmlSchemaIDCPtr ret = NULL;
5599 
5600     if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5601         return (NULL);
5602 
5603     ret = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
5604     if (ret == NULL) {
5605         xmlSchemaPErrMemory(ctxt,
5606 	    "allocating an identity-constraint definition", NULL);
5607         return (NULL);
5608     }
5609     memset(ret, 0, sizeof(xmlSchemaIDC));
5610     /* The target namespace of the parent element declaration. */
5611     ret->targetNamespace = nsName;
5612     ret->name = name;
5613     ret->type = category;
5614     ret->node = node;
5615 
5616     WXS_ADD_GLOBAL(ctxt, ret);
5617     /*
5618     * Only keyrefs need to be fixup up.
5619     */
5620     if (category == XML_SCHEMA_TYPE_IDC_KEYREF)
5621 	WXS_ADD_PENDING(ctxt, ret);
5622     return (ret);
5623 }
5624 
5625 /**
5626  * xmlSchemaAddWildcard:
5627  * @ctxt:  a schema validation context
5628  * @schema: a schema
5629  *
5630  * Adds a wildcard.
5631  * It corresponds to a xsd:anyAttribute and xsd:any.
5632  *
5633  * Returns the new struture or NULL in case of error
5634  */
5635 static xmlSchemaWildcardPtr
xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaTypeType type,xmlNodePtr node)5636 xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5637 		     xmlSchemaTypeType type, xmlNodePtr node)
5638 {
5639     xmlSchemaWildcardPtr ret = NULL;
5640 
5641     if ((ctxt == NULL) || (schema == NULL))
5642         return (NULL);
5643 
5644     ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
5645     if (ret == NULL) {
5646         xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
5647         return (NULL);
5648     }
5649     memset(ret, 0, sizeof(xmlSchemaWildcard));
5650     ret->type = type;
5651     ret->node = node;
5652     WXS_ADD_LOCAL(ctxt, ret);
5653     return (ret);
5654 }
5655 
5656 static void
xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group)5657 xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group)
5658 {
5659     if (group == NULL)
5660 	return;
5661     if (group->members != NULL)
5662 	xmlSchemaItemListFree(group->members);
5663     xmlFree(group);
5664 }
5665 
5666 static xmlSchemaSubstGroupPtr
xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt,xmlSchemaElementPtr head)5667 xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt,
5668 		       xmlSchemaElementPtr head)
5669 {
5670     xmlSchemaSubstGroupPtr ret;
5671 
5672     /* Init subst group hash. */
5673     if (WXS_SUBST_GROUPS(pctxt) == NULL) {
5674 	WXS_SUBST_GROUPS(pctxt) = xmlHashCreateDict(10, pctxt->dict);
5675 	if (WXS_SUBST_GROUPS(pctxt) == NULL)
5676 	    return(NULL);
5677     }
5678     /* Create a new substitution group. */
5679     ret = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
5680     if (ret == NULL) {
5681 	xmlSchemaPErrMemory(NULL,
5682 	    "allocating a substitution group container", NULL);
5683 	return(NULL);
5684     }
5685     memset(ret, 0, sizeof(xmlSchemaSubstGroup));
5686     ret->head = head;
5687     /* Create list of members. */
5688     ret->members = xmlSchemaItemListCreate();
5689     if (ret->members == NULL) {
5690 	xmlSchemaSubstGroupFree(ret);
5691 	return(NULL);
5692     }
5693     /* Add subst group to hash. */
5694     if (xmlHashAddEntry2(WXS_SUBST_GROUPS(pctxt),
5695 	head->name, head->targetNamespace, ret) != 0) {
5696 	PERROR_INT("xmlSchemaSubstGroupAdd",
5697 	    "failed to add a new substitution container");
5698 	xmlSchemaSubstGroupFree(ret);
5699 	return(NULL);
5700     }
5701     return(ret);
5702 }
5703 
5704 static xmlSchemaSubstGroupPtr
xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt,xmlSchemaElementPtr head)5705 xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt,
5706 		       xmlSchemaElementPtr head)
5707 {
5708     if (WXS_SUBST_GROUPS(pctxt) == NULL)
5709 	return(NULL);
5710     return(xmlHashLookup2(WXS_SUBST_GROUPS(pctxt),
5711 	head->name, head->targetNamespace));
5712 
5713 }
5714 
5715 /**
5716  * xmlSchemaAddElementSubstitutionMember:
5717  * @pctxt:  a schema parser context
5718  * @head:  the head of the substitution group
5719  * @member: the new member of the substitution group
5720  *
5721  * Allocate a new annotation structure.
5722  *
5723  * Returns the newly allocated structure or NULL in case or error
5724  */
5725 static int
xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,xmlSchemaElementPtr head,xmlSchemaElementPtr member)5726 xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
5727 				      xmlSchemaElementPtr head,
5728 				      xmlSchemaElementPtr member)
5729 {
5730     xmlSchemaSubstGroupPtr substGroup = NULL;
5731 
5732     if ((pctxt == NULL) || (head == NULL) || (member == NULL))
5733 	return (-1);
5734 
5735     substGroup = xmlSchemaSubstGroupGet(pctxt, head);
5736     if (substGroup == NULL)
5737 	substGroup = xmlSchemaSubstGroupAdd(pctxt, head);
5738     if (substGroup == NULL)
5739 	return(-1);
5740     if (xmlSchemaItemListAdd(substGroup->members, member) == -1)
5741 	return(-1);
5742     return(0);
5743 }
5744 
5745 /************************************************************************
5746  * 									*
5747  *		Utilities for parsing					*
5748  * 									*
5749  ************************************************************************/
5750 
5751 /**
5752  * xmlSchemaPValAttrNodeQNameValue:
5753  * @ctxt:  a schema parser context
5754  * @schema: the schema context
5755  * @ownerDes: the designation of the parent element
5756  * @ownerItem: the parent as a schema object
5757  * @value:  the QName value
5758  * @local: the resulting local part if found, the attribute value otherwise
5759  * @uri:  the resulting namespace URI if found
5760  *
5761  * Extracts the local name and the URI of a QName value and validates it.
5762  * This one is intended to be used on attribute values that
5763  * should resolve to schema components.
5764  *
5765  * Returns 0, in case the QName is valid, a positive error code
5766  * if not valid and -1 if an internal error occurs.
5767  */
5768 static int
xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,const xmlChar * value,const xmlChar ** uri,const xmlChar ** local)5769 xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
5770 				       xmlSchemaPtr schema,
5771 				       xmlSchemaBasicItemPtr ownerItem,
5772 				       xmlAttrPtr attr,
5773 				       const xmlChar *value,
5774 				       const xmlChar **uri,
5775 				       const xmlChar **local)
5776 {
5777     const xmlChar *pref;
5778     xmlNsPtr ns;
5779     int len, ret;
5780 
5781     *uri = NULL;
5782     *local = NULL;
5783     ret = xmlValidateQName(value, 1);
5784     if (ret > 0) {
5785 	xmlSchemaPSimpleTypeErr(ctxt,
5786 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5787 	    ownerItem, (xmlNodePtr) attr,
5788 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
5789 	    NULL, value, NULL, NULL, NULL);
5790 	*local = value;
5791 	return (ctxt->err);
5792     } else if (ret < 0)
5793 	return (-1);
5794 
5795     if (!strchr((char *) value, ':')) {
5796 	ns = xmlSearchNs(attr->doc, attr->parent, NULL);
5797 	if (ns)
5798 	    *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5799 	else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
5800 	    /* TODO: move XML_SCHEMAS_INCLUDING_CONVERT_NS to the
5801 	    * parser context. */
5802 	    /*
5803 	    * This one takes care of included schemas with no
5804 	    * target namespace.
5805 	    */
5806 	    *uri = ctxt->targetNamespace;
5807 	}
5808 	*local = xmlDictLookup(ctxt->dict, value, -1);
5809 	return (0);
5810     }
5811     /*
5812     * At this point xmlSplitQName3 has to return a local name.
5813     */
5814     *local = xmlSplitQName3(value, &len);
5815     *local = xmlDictLookup(ctxt->dict, *local, -1);
5816     pref = xmlDictLookup(ctxt->dict, value, len);
5817     ns = xmlSearchNs(attr->doc, attr->parent, pref);
5818     if (ns == NULL) {
5819 	xmlSchemaPSimpleTypeErr(ctxt,
5820 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5821 	    ownerItem, (xmlNodePtr) attr,
5822 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
5823 	    "The value '%s' of simple type 'xs:QName' has no "
5824 	    "corresponding namespace declaration in scope", value, NULL);
5825 	return (ctxt->err);
5826     } else {
5827         *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5828     }
5829     return (0);
5830 }
5831 
5832 /**
5833  * xmlSchemaPValAttrNodeQName:
5834  * @ctxt:  a schema parser context
5835  * @schema: the schema context
5836  * @ownerDes: the designation of the owner element
5837  * @ownerItem: the owner as a schema object
5838  * @attr:  the attribute node
5839  * @local: the resulting local part if found, the attribute value otherwise
5840  * @uri:  the resulting namespace URI if found
5841  *
5842  * Extracts and validates the QName of an attribute value.
5843  * This one is intended to be used on attribute values that
5844  * should resolve to schema components.
5845  *
5846  * Returns 0, in case the QName is valid, a positive error code
5847  * if not valid and -1 if an internal error occurs.
5848  */
5849 static int
xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,const xmlChar ** uri,const xmlChar ** local)5850 xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
5851 				       xmlSchemaPtr schema,
5852 				       xmlSchemaBasicItemPtr ownerItem,
5853 				       xmlAttrPtr attr,
5854 				       const xmlChar **uri,
5855 				       const xmlChar **local)
5856 {
5857     const xmlChar *value;
5858 
5859     value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5860     return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
5861 	ownerItem, attr, value, uri, local));
5862 }
5863 
5864 /**
5865  * xmlSchemaPValAttrQName:
5866  * @ctxt:  a schema parser context
5867  * @schema: the schema context
5868  * @ownerDes: the designation of the parent element
5869  * @ownerItem: the owner as a schema object
5870  * @ownerElem:  the parent node of the attribute
5871  * @name:  the name of the attribute
5872  * @local: the resulting local part if found, the attribute value otherwise
5873  * @uri:  the resulting namespace URI if found
5874  *
5875  * Extracts and validates the QName of an attribute value.
5876  *
5877  * Returns 0, in case the QName is valid, a positive error code
5878  * if not valid and -1 if an internal error occurs.
5879  */
5880 static int
xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaBasicItemPtr ownerItem,xmlNodePtr ownerElem,const char * name,const xmlChar ** uri,const xmlChar ** local)5881 xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5882 				   xmlSchemaPtr schema,
5883 				   xmlSchemaBasicItemPtr ownerItem,
5884 				   xmlNodePtr ownerElem,
5885 				   const char *name,
5886 				   const xmlChar **uri,
5887 				   const xmlChar **local)
5888 {
5889     xmlAttrPtr attr;
5890 
5891     attr = xmlSchemaGetPropNode(ownerElem, name);
5892     if (attr == NULL) {
5893 	*local = NULL;
5894 	*uri = NULL;
5895 	return (0);
5896     }
5897     return (xmlSchemaPValAttrNodeQName(ctxt, schema,
5898 	ownerItem, attr, uri, local));
5899 }
5900 
5901 /**
5902  * xmlSchemaPValAttrID:
5903  * @ctxt:  a schema parser context
5904  * @schema: the schema context
5905  * @ownerDes: the designation of the parent element
5906  * @ownerItem: the owner as a schema object
5907  * @ownerElem:  the parent node of the attribute
5908  * @name:  the name of the attribute
5909  *
5910  * Extracts and validates the ID of an attribute value.
5911  *
5912  * Returns 0, in case the ID is valid, a positive error code
5913  * if not valid and -1 if an internal error occurs.
5914  */
5915 static int
xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt,xmlAttrPtr attr)5916 xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr)
5917 {
5918     int ret;
5919     const xmlChar *value;
5920 
5921     if (attr == NULL)
5922 	return(0);
5923     value = xmlSchemaGetNodeContentNoDict((xmlNodePtr) attr);
5924     ret = xmlValidateNCName(value, 1);
5925     if (ret == 0) {
5926 	/*
5927 	* NOTE: the IDness might have already be declared in the DTD
5928 	*/
5929 	if (attr->atype != XML_ATTRIBUTE_ID) {
5930 	    xmlIDPtr res;
5931 	    xmlChar *strip;
5932 
5933 	    /*
5934 	    * TODO: Use xmlSchemaStrip here; it's not exported at this
5935 	    * moment.
5936 	    */
5937 	    strip = xmlSchemaCollapseString(value);
5938 	    if (strip != NULL) {
5939 		xmlFree((xmlChar *) value);
5940 		value = strip;
5941 	    }
5942     	    res = xmlAddID(NULL, attr->doc, value, attr);
5943 	    if (res == NULL) {
5944 		ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
5945 		xmlSchemaPSimpleTypeErr(ctxt,
5946 		    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5947 		    NULL, (xmlNodePtr) attr,
5948 		    xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5949 		    NULL, NULL, "Duplicate value '%s' of simple "
5950 		    "type 'xs:ID'", value, NULL);
5951 	    } else
5952 		attr->atype = XML_ATTRIBUTE_ID;
5953 	}
5954     } else if (ret > 0) {
5955 	ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
5956 	xmlSchemaPSimpleTypeErr(ctxt,
5957 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5958 	    NULL, (xmlNodePtr) attr,
5959 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5960 	    NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
5961 	    "not a valid 'xs:NCName'",
5962 	    value, NULL);
5963     }
5964     if (value != NULL)
5965 	xmlFree((xmlChar *)value);
5966 
5967     return (ret);
5968 }
5969 
5970 static int
xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr ownerElem,const xmlChar * name)5971 xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
5972 		    xmlNodePtr ownerElem,
5973 		    const xmlChar *name)
5974 {
5975     xmlAttrPtr attr;
5976 
5977     attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
5978     if (attr == NULL)
5979 	return(0);
5980     return(xmlSchemaPValAttrNodeID(ctxt, attr));
5981 
5982 }
5983 
5984 /**
5985  * xmlGetMaxOccurs:
5986  * @ctxt:  a schema validation context
5987  * @node:  a subtree containing XML Schema informations
5988  *
5989  * Get the maxOccurs property
5990  *
5991  * Returns the default if not found, or the value
5992  */
5993 static int
xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int min,int max,int def,const char * expected)5994 xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
5995 		int min, int max, int def, const char *expected)
5996 {
5997     const xmlChar *val, *cur;
5998     int ret = 0;
5999     xmlAttrPtr attr;
6000 
6001     attr = xmlSchemaGetPropNode(node, "maxOccurs");
6002     if (attr == NULL)
6003 	return (def);
6004     val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6005 
6006     if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
6007 	if (max != UNBOUNDED) {
6008 	    xmlSchemaPSimpleTypeErr(ctxt,
6009 		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6010 		/* XML_SCHEMAP_INVALID_MINOCCURS, */
6011 		NULL, (xmlNodePtr) attr, NULL, expected,
6012 		val, NULL, NULL, NULL);
6013 	    return (def);
6014 	} else
6015 	    return (UNBOUNDED);  /* encoding it with -1 might be another option */
6016     }
6017 
6018     cur = val;
6019     while (IS_BLANK_CH(*cur))
6020         cur++;
6021     if (*cur == 0) {
6022         xmlSchemaPSimpleTypeErr(ctxt,
6023 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6024 	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
6025 	    NULL, (xmlNodePtr) attr, NULL, expected,
6026 	    val, NULL, NULL, NULL);
6027 	return (def);
6028     }
6029     while ((*cur >= '0') && (*cur <= '9')) {
6030         ret = ret * 10 + (*cur - '0');
6031         cur++;
6032     }
6033     while (IS_BLANK_CH(*cur))
6034         cur++;
6035     /*
6036     * TODO: Restrict the maximal value to Integer.
6037     */
6038     if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
6039 	xmlSchemaPSimpleTypeErr(ctxt,
6040 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6041 	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
6042 	    NULL, (xmlNodePtr) attr, NULL, expected,
6043 	    val, NULL, NULL, NULL);
6044         return (def);
6045     }
6046     return (ret);
6047 }
6048 
6049 /**
6050  * xmlGetMinOccurs:
6051  * @ctxt:  a schema validation context
6052  * @node:  a subtree containing XML Schema informations
6053  *
6054  * Get the minOccurs property
6055  *
6056  * Returns the default if not found, or the value
6057  */
6058 static int
xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int min,int max,int def,const char * expected)6059 xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
6060 		int min, int max, int def, const char *expected)
6061 {
6062     const xmlChar *val, *cur;
6063     int ret = 0;
6064     xmlAttrPtr attr;
6065 
6066     attr = xmlSchemaGetPropNode(node, "minOccurs");
6067     if (attr == NULL)
6068 	return (def);
6069     val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6070     cur = val;
6071     while (IS_BLANK_CH(*cur))
6072         cur++;
6073     if (*cur == 0) {
6074         xmlSchemaPSimpleTypeErr(ctxt,
6075 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6076 	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
6077 	    NULL, (xmlNodePtr) attr, NULL, expected,
6078 	    val, NULL, NULL, NULL);
6079         return (def);
6080     }
6081     while ((*cur >= '0') && (*cur <= '9')) {
6082         ret = ret * 10 + (*cur - '0');
6083         cur++;
6084     }
6085     while (IS_BLANK_CH(*cur))
6086         cur++;
6087     /*
6088     * TODO: Restrict the maximal value to Integer.
6089     */
6090     if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
6091 	xmlSchemaPSimpleTypeErr(ctxt,
6092 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6093 	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
6094 	    NULL, (xmlNodePtr) attr, NULL, expected,
6095 	    val, NULL, NULL, NULL);
6096         return (def);
6097     }
6098     return (ret);
6099 }
6100 
6101 /**
6102  * xmlSchemaPGetBoolNodeValue:
6103  * @ctxt:  a schema validation context
6104  * @ownerDes:  owner designation
6105  * @ownerItem:  the owner as a schema item
6106  * @node: the node holding the value
6107  *
6108  * Converts a boolean string value into 1 or 0.
6109  *
6110  * Returns 0 or 1.
6111  */
6112 static int
xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,xmlSchemaBasicItemPtr ownerItem,xmlNodePtr node)6113 xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
6114 			   xmlSchemaBasicItemPtr ownerItem,
6115 			   xmlNodePtr node)
6116 {
6117     xmlChar *value = NULL;
6118     int res = 0;
6119 
6120     value = xmlNodeGetContent(node);
6121     /*
6122     * 3.2.2.1 Lexical representation
6123     * An instance of a datatype that is defined as �boolean�
6124     * can have the following legal literals {true, false, 1, 0}.
6125     */
6126     if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
6127         res = 1;
6128     else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
6129         res = 0;
6130     else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
6131 	res = 1;
6132     else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
6133         res = 0;
6134     else {
6135         xmlSchemaPSimpleTypeErr(ctxt,
6136 	    XML_SCHEMAP_INVALID_BOOLEAN,
6137 	    ownerItem, node,
6138 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6139 	    NULL, BAD_CAST value,
6140 	    NULL, NULL, NULL);
6141     }
6142     if (value != NULL)
6143 	xmlFree(value);
6144     return (res);
6145 }
6146 
6147 /**
6148  * xmlGetBooleanProp:
6149  * @ctxt:  a schema validation context
6150  * @node:  a subtree containing XML Schema informations
6151  * @name:  the attribute name
6152  * @def:  the default value
6153  *
6154  * Evaluate if a boolean property is set
6155  *
6156  * Returns the default if not found, 0 if found to be false,
6157  * 1 if found to be true
6158  */
6159 static int
xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,const char * name,int def)6160 xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
6161 		  xmlNodePtr node,
6162                   const char *name, int def)
6163 {
6164     const xmlChar *val;
6165 
6166     val = xmlSchemaGetProp(ctxt, node, name);
6167     if (val == NULL)
6168         return (def);
6169     /*
6170     * 3.2.2.1 Lexical representation
6171     * An instance of a datatype that is defined as �boolean�
6172     * can have the following legal literals {true, false, 1, 0}.
6173     */
6174     if (xmlStrEqual(val, BAD_CAST "true"))
6175         def = 1;
6176     else if (xmlStrEqual(val, BAD_CAST "false"))
6177         def = 0;
6178     else if (xmlStrEqual(val, BAD_CAST "1"))
6179 	def = 1;
6180     else if (xmlStrEqual(val, BAD_CAST "0"))
6181         def = 0;
6182     else {
6183         xmlSchemaPSimpleTypeErr(ctxt,
6184 	    XML_SCHEMAP_INVALID_BOOLEAN,
6185 	    NULL,
6186 	    (xmlNodePtr) xmlSchemaGetPropNode(node, name),
6187 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6188 	    NULL, val, NULL, NULL, NULL);
6189     }
6190     return (def);
6191 }
6192 
6193 /************************************************************************
6194  * 									*
6195  *		Shema extraction from an Infoset			*
6196  * 									*
6197  ************************************************************************/
6198 static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
6199                                                  ctxt, xmlSchemaPtr schema,
6200                                                  xmlNodePtr node,
6201 						 int topLevel);
6202 static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
6203                                                   ctxt,
6204                                                   xmlSchemaPtr schema,
6205                                                   xmlNodePtr node,
6206 						  int topLevel);
6207 static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
6208                                                   ctxt,
6209                                                   xmlSchemaPtr schema,
6210                                                   xmlNodePtr node,
6211 						  xmlSchemaTypeType parentType);
6212 static xmlSchemaBasicItemPtr
6213 xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
6214 			     xmlSchemaPtr schema,
6215 			     xmlNodePtr node,
6216 			     xmlSchemaItemListPtr uses,
6217 			     int parentType);
6218 static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
6219                                            xmlSchemaPtr schema,
6220                                            xmlNodePtr node);
6221 static xmlSchemaWildcardPtr
6222 xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6223                            xmlSchemaPtr schema, xmlNodePtr node);
6224 
6225 /**
6226  * xmlSchemaPValAttrNodeValue:
6227  *
6228  * @ctxt:  a schema parser context
6229  * @ownerDes: the designation of the parent element
6230  * @ownerItem: the schema object owner if existent
6231  * @attr:  the schema attribute node being validated
6232  * @value: the value
6233  * @type: the built-in type to be validated against
6234  *
6235  * Validates a value against the given built-in type.
6236  * This one is intended to be used internally for validation
6237  * of schema attribute values during parsing of the schema.
6238  *
6239  * Returns 0 if the value is valid, a positive error code
6240  * number otherwise and -1 in case of an internal or API error.
6241  */
6242 static int
xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,const xmlChar * value,xmlSchemaTypePtr type)6243 xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
6244 			   xmlSchemaBasicItemPtr ownerItem,
6245 			   xmlAttrPtr attr,
6246 			   const xmlChar *value,
6247 			   xmlSchemaTypePtr type)
6248 {
6249 
6250     int ret = 0;
6251 
6252     /*
6253     * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
6254     * one is really meant to be used internally, so better not.
6255     */
6256     if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
6257 	return (-1);
6258     if (type->type != XML_SCHEMA_TYPE_BASIC) {
6259 	PERROR_INT("xmlSchemaPValAttrNodeValue",
6260 	    "the given type is not a built-in type");
6261 	return (-1);
6262     }
6263     switch (type->builtInType) {
6264 	case XML_SCHEMAS_NCNAME:
6265 	case XML_SCHEMAS_QNAME:
6266 	case XML_SCHEMAS_ANYURI:
6267 	case XML_SCHEMAS_TOKEN:
6268 	case XML_SCHEMAS_LANGUAGE:
6269 	    ret = xmlSchemaValPredefTypeNode(type, value, NULL,
6270 		(xmlNodePtr) attr);
6271 	    break;
6272 	default: {
6273 	    PERROR_INT("xmlSchemaPValAttrNodeValue",
6274 		"validation using the given type is not supported while "
6275 		"parsing a schema");
6276 	    return (-1);
6277 	}
6278     }
6279     /*
6280     * TODO: Should we use the S4S error codes instead?
6281     */
6282     if (ret < 0) {
6283 	PERROR_INT("xmlSchemaPValAttrNodeValue",
6284 	    "failed to validate a schema attribute value");
6285 	return (-1);
6286     } else if (ret > 0) {
6287 	if (WXS_IS_LIST(type))
6288 	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
6289 	else
6290 	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
6291 	xmlSchemaPSimpleTypeErr(pctxt,
6292 	    ret, ownerItem, (xmlNodePtr) attr,
6293 	    type, NULL, value, NULL, NULL, NULL);
6294     }
6295     return (ret);
6296 }
6297 
6298 /**
6299  * xmlSchemaPValAttrNode:
6300  *
6301  * @ctxt:  a schema parser context
6302  * @ownerDes: the designation of the parent element
6303  * @ownerItem: the schema object owner if existent
6304  * @attr:  the schema attribute node being validated
6305  * @type: the built-in type to be validated against
6306  * @value: the resulting value if any
6307  *
6308  * Extracts and validates a value against the given built-in type.
6309  * This one is intended to be used internally for validation
6310  * of schema attribute values during parsing of the schema.
6311  *
6312  * Returns 0 if the value is valid, a positive error code
6313  * number otherwise and -1 in case of an internal or API error.
6314  */
6315 static int
xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,xmlSchemaTypePtr type,const xmlChar ** value)6316 xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
6317 			   xmlSchemaBasicItemPtr ownerItem,
6318 			   xmlAttrPtr attr,
6319 			   xmlSchemaTypePtr type,
6320 			   const xmlChar **value)
6321 {
6322     const xmlChar *val;
6323 
6324     if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
6325 	return (-1);
6326 
6327     val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6328     if (value != NULL)
6329 	*value = val;
6330 
6331     return (xmlSchemaPValAttrNodeValue(ctxt, ownerItem, attr,
6332 	val, type));
6333 }
6334 
6335 /**
6336  * xmlSchemaPValAttr:
6337  *
6338  * @ctxt:  a schema parser context
6339  * @node: the element node of the attribute
6340  * @ownerDes: the designation of the parent element
6341  * @ownerItem: the schema object owner if existent
6342  * @ownerElem: the owner element node
6343  * @name:  the name of the schema attribute node
6344  * @type: the built-in type to be validated against
6345  * @value: the resulting value if any
6346  *
6347  * Extracts and validates a value against the given built-in type.
6348  * This one is intended to be used internally for validation
6349  * of schema attribute values during parsing of the schema.
6350  *
6351  * Returns 0 if the value is valid, a positive error code
6352  * number otherwise and -1 in case of an internal or API error.
6353  */
6354 static int
xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,xmlSchemaBasicItemPtr ownerItem,xmlNodePtr ownerElem,const char * name,xmlSchemaTypePtr type,const xmlChar ** value)6355 xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
6356 		       xmlSchemaBasicItemPtr ownerItem,
6357 		       xmlNodePtr ownerElem,
6358 		       const char *name,
6359 		       xmlSchemaTypePtr type,
6360 		       const xmlChar **value)
6361 {
6362     xmlAttrPtr attr;
6363 
6364     if ((ctxt == NULL) || (type == NULL)) {
6365 	if (value != NULL)
6366 	    *value = NULL;
6367 	return (-1);
6368     }
6369     if (type->type != XML_SCHEMA_TYPE_BASIC) {
6370 	if (value != NULL)
6371 	    *value = NULL;
6372 	xmlSchemaPErr(ctxt, ownerElem,
6373 	    XML_SCHEMAP_INTERNAL,
6374 	    "Internal error: xmlSchemaPValAttr, the given "
6375 	    "type '%s' is not a built-in type.\n",
6376 	    type->name, NULL);
6377 	return (-1);
6378     }
6379     attr = xmlSchemaGetPropNode(ownerElem, name);
6380     if (attr == NULL) {
6381 	if (value != NULL)
6382 	    *value = NULL;
6383 	return (0);
6384     }
6385     return (xmlSchemaPValAttrNode(ctxt, ownerItem, attr,
6386 	type, value));
6387 }
6388 
6389 static int
xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema ATTRIBUTE_UNUSED,xmlNodePtr node,xmlAttrPtr attr,const xmlChar * namespaceName)6390 xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
6391 		  xmlSchemaPtr schema ATTRIBUTE_UNUSED,
6392 		  xmlNodePtr node,
6393 		  xmlAttrPtr attr,
6394 		  const xmlChar *namespaceName)
6395 {
6396     /* TODO: Pointer comparison instead? */
6397     if (xmlStrEqual(pctxt->targetNamespace, namespaceName))
6398 	return (0);
6399     if (xmlStrEqual(xmlSchemaNs, namespaceName))
6400 	return (0);
6401     /*
6402     * Check if the referenced namespace was <import>ed.
6403     */
6404     if (WXS_BUCKET(pctxt)->relations != NULL) {
6405 	xmlSchemaSchemaRelationPtr rel;
6406 
6407 	rel = WXS_BUCKET(pctxt)->relations;
6408 	do {
6409 	    if (WXS_IS_BUCKET_IMPMAIN(rel->type) &&
6410 		xmlStrEqual(namespaceName, rel->importNamespace))
6411 		return (0);
6412 	    rel = rel->next;
6413 	} while (rel != NULL);
6414     }
6415     /*
6416     * No matching <import>ed namespace found.
6417     */
6418     {
6419 	xmlNodePtr n = (attr != NULL) ? (xmlNodePtr) attr : node;
6420 
6421 	if (namespaceName == NULL)
6422 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
6423 		XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6424 		"References from this schema to components in no "
6425 		"namespace are not allowed, since not indicated by an "
6426 		"import statement", NULL, NULL);
6427 	else
6428 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
6429 		XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6430 		"References from this schema to components in the "
6431 		"namespace '%s' are not allowed, since not indicated by an "
6432 		"import statement", namespaceName, NULL);
6433     }
6434     return (XML_SCHEMAP_SRC_RESOLVE);
6435 }
6436 
6437 /**
6438  * xmlSchemaParseLocalAttributes:
6439  * @ctxt:  a schema validation context
6440  * @schema:  the schema being built
6441  * @node:  a subtree containing XML Schema informations
6442  * @type:  the hosting type where the attributes will be anchored
6443  *
6444  * Parses attribute uses and attribute declarations and
6445  * attribute group references.
6446  */
6447 static int
xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr * child,xmlSchemaItemListPtr * list,int parentType,int * hasRefs)6448 xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6449                         xmlNodePtr *child, xmlSchemaItemListPtr *list,
6450 			int parentType, int *hasRefs)
6451 {
6452     void *item;
6453 
6454     while ((IS_SCHEMA((*child), "attribute")) ||
6455            (IS_SCHEMA((*child), "attributeGroup"))) {
6456         if (IS_SCHEMA((*child), "attribute")) {
6457 	    item = xmlSchemaParseLocalAttribute(ctxt, schema, *child,
6458 		*list, parentType);
6459         } else {
6460             item = xmlSchemaParseAttributeGroupRef(ctxt, schema, *child);
6461 	    if ((item != NULL) && (hasRefs != NULL))
6462 		*hasRefs = 1;
6463         }
6464 	if (item != NULL) {
6465 	    if (*list == NULL) {
6466 		/* TODO: Customize grow factor. */
6467 		*list = xmlSchemaItemListCreate();
6468 		if (*list == NULL)
6469 		    return(-1);
6470 	    }
6471 	    if (xmlSchemaItemListAddSize(*list, 2, item) == -1)
6472 		return(-1);
6473 	}
6474         *child = (*child)->next;
6475     }
6476     return (0);
6477 }
6478 
6479 /**
6480  * xmlSchemaParseAnnotation:
6481  * @ctxt:  a schema validation context
6482  * @schema:  the schema being built
6483  * @node:  a subtree containing XML Schema informations
6484  *
6485  * parse a XML schema Attrribute declaration
6486  * *WARNING* this interface is highly subject to change
6487  *
6488  * Returns -1 in case of error, 0 if the declaration is improper and
6489  *         1 in case of success.
6490  */
6491 static xmlSchemaAnnotPtr
xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int needed)6492 xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int needed)
6493 {
6494     xmlSchemaAnnotPtr ret;
6495     xmlNodePtr child = NULL;
6496     xmlAttrPtr attr;
6497     int barked = 0;
6498 
6499     /*
6500     * INFO: S4S completed.
6501     */
6502     /*
6503     * id = ID
6504     * {any attributes with non-schema namespace . . .}>
6505     * Content: (appinfo | documentation)*
6506     */
6507     if ((ctxt == NULL) || (node == NULL))
6508         return (NULL);
6509     if (needed)
6510 	ret = xmlSchemaNewAnnot(ctxt, node);
6511     else
6512 	ret = NULL;
6513     attr = node->properties;
6514     while (attr != NULL) {
6515 	if (((attr->ns == NULL) &&
6516 	    (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
6517 	    ((attr->ns != NULL) &&
6518 	    xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
6519 
6520 	    xmlSchemaPIllegalAttrErr(ctxt,
6521 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6522 	}
6523 	attr = attr->next;
6524     }
6525     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6526     /*
6527     * And now for the children...
6528     */
6529     child = node->children;
6530     while (child != NULL) {
6531 	if (IS_SCHEMA(child, "appinfo")) {
6532 	    /* TODO: make available the content of "appinfo". */
6533 	    /*
6534 	    * source = anyURI
6535 	    * {any attributes with non-schema namespace . . .}>
6536 	    * Content: ({any})*
6537 	    */
6538 	    attr = child->properties;
6539 	    while (attr != NULL) {
6540 		if (((attr->ns == NULL) &&
6541 		     (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
6542 		     ((attr->ns != NULL) &&
6543 		      xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
6544 
6545 		    xmlSchemaPIllegalAttrErr(ctxt,
6546 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6547 		}
6548 		attr = attr->next;
6549 	    }
6550 	    xmlSchemaPValAttr(ctxt, NULL, child, "source",
6551 		xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
6552 	    child = child->next;
6553 	} else if (IS_SCHEMA(child, "documentation")) {
6554 	    /* TODO: make available the content of "documentation". */
6555 	    /*
6556 	    * source = anyURI
6557 	    * {any attributes with non-schema namespace . . .}>
6558 	    * Content: ({any})*
6559 	    */
6560 	    attr = child->properties;
6561 	    while (attr != NULL) {
6562 		if (attr->ns == NULL) {
6563 		    if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
6564 			xmlSchemaPIllegalAttrErr(ctxt,
6565 			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6566 		    }
6567 		} else {
6568 		    if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
6569 			(xmlStrEqual(attr->name, BAD_CAST "lang") &&
6570 			(!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
6571 
6572 			xmlSchemaPIllegalAttrErr(ctxt,
6573 			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6574 		    }
6575 		}
6576 		attr = attr->next;
6577 	    }
6578 	    /*
6579 	    * Attribute "xml:lang".
6580 	    */
6581 	    attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
6582 	    if (attr != NULL)
6583 		xmlSchemaPValAttrNode(ctxt, NULL, attr,
6584 		xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
6585 	    child = child->next;
6586 	} else {
6587 	    if (!barked)
6588 		xmlSchemaPContentErr(ctxt,
6589 		    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6590 		    NULL, node, child, NULL, "(appinfo | documentation)*");
6591 	    barked = 1;
6592 	    child = child->next;
6593 	}
6594     }
6595 
6596     return (ret);
6597 }
6598 
6599 /**
6600  * xmlSchemaParseFacet:
6601  * @ctxt:  a schema validation context
6602  * @schema:  the schema being built
6603  * @node:  a subtree containing XML Schema informations
6604  *
6605  * parse a XML schema Facet declaration
6606  * *WARNING* this interface is highly subject to change
6607  *
6608  * Returns the new type structure or NULL in case of error
6609  */
6610 static xmlSchemaFacetPtr
xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)6611 xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6612                     xmlNodePtr node)
6613 {
6614     xmlSchemaFacetPtr facet;
6615     xmlNodePtr child = NULL;
6616     const xmlChar *value;
6617 
6618     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6619         return (NULL);
6620 
6621     facet = xmlSchemaNewFacet();
6622     if (facet == NULL) {
6623         xmlSchemaPErrMemory(ctxt, "allocating facet", node);
6624         return (NULL);
6625     }
6626     facet->node = node;
6627     value = xmlSchemaGetProp(ctxt, node, "value");
6628     if (value == NULL) {
6629         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
6630                        "Facet %s has no value\n", node->name, NULL);
6631         xmlSchemaFreeFacet(facet);
6632         return (NULL);
6633     }
6634     if (IS_SCHEMA(node, "minInclusive")) {
6635         facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
6636     } else if (IS_SCHEMA(node, "minExclusive")) {
6637         facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
6638     } else if (IS_SCHEMA(node, "maxInclusive")) {
6639         facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
6640     } else if (IS_SCHEMA(node, "maxExclusive")) {
6641         facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
6642     } else if (IS_SCHEMA(node, "totalDigits")) {
6643         facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
6644     } else if (IS_SCHEMA(node, "fractionDigits")) {
6645         facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
6646     } else if (IS_SCHEMA(node, "pattern")) {
6647         facet->type = XML_SCHEMA_FACET_PATTERN;
6648     } else if (IS_SCHEMA(node, "enumeration")) {
6649         facet->type = XML_SCHEMA_FACET_ENUMERATION;
6650     } else if (IS_SCHEMA(node, "whiteSpace")) {
6651         facet->type = XML_SCHEMA_FACET_WHITESPACE;
6652     } else if (IS_SCHEMA(node, "length")) {
6653         facet->type = XML_SCHEMA_FACET_LENGTH;
6654     } else if (IS_SCHEMA(node, "maxLength")) {
6655         facet->type = XML_SCHEMA_FACET_MAXLENGTH;
6656     } else if (IS_SCHEMA(node, "minLength")) {
6657         facet->type = XML_SCHEMA_FACET_MINLENGTH;
6658     } else {
6659         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
6660                        "Unknown facet type %s\n", node->name, NULL);
6661         xmlSchemaFreeFacet(facet);
6662         return (NULL);
6663     }
6664     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6665     facet->value = value;
6666     if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
6667 	(facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
6668 	const xmlChar *fixed;
6669 
6670 	fixed = xmlSchemaGetProp(ctxt, node, "fixed");
6671 	if (fixed != NULL) {
6672 	    if (xmlStrEqual(fixed, BAD_CAST "true"))
6673 		facet->fixed = 1;
6674 	}
6675     }
6676     child = node->children;
6677 
6678     if (IS_SCHEMA(child, "annotation")) {
6679         facet->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6680         child = child->next;
6681     }
6682     if (child != NULL) {
6683         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
6684                        "Facet %s has unexpected child content\n",
6685                        node->name, NULL);
6686     }
6687     return (facet);
6688 }
6689 
6690 /**
6691  * xmlSchemaParseWildcardNs:
6692  * @ctxt:  a schema parser context
6693  * @wildc:  the wildcard, already created
6694  * @node:  a subtree containing XML Schema informations
6695  *
6696  * Parses the attribute "processContents" and "namespace"
6697  * of a xsd:anyAttribute and xsd:any.
6698  * *WARNING* this interface is highly subject to change
6699  *
6700  * Returns 0 if everything goes fine, a positive error code
6701  * if something is not valid and -1 if an internal error occurs.
6702  */
6703 static int
xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema ATTRIBUTE_UNUSED,xmlSchemaWildcardPtr wildc,xmlNodePtr node)6704 xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
6705 			 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
6706 			 xmlSchemaWildcardPtr wildc,
6707 			 xmlNodePtr node)
6708 {
6709     const xmlChar *pc, *ns, *dictnsItem;
6710     int ret = 0;
6711     xmlChar *nsItem;
6712     xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
6713     xmlAttrPtr attr;
6714 
6715     pc = xmlSchemaGetProp(ctxt, node, "processContents");
6716     if ((pc == NULL)
6717         || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
6718         wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6719     } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
6720         wildc->processContents = XML_SCHEMAS_ANY_SKIP;
6721     } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
6722         wildc->processContents = XML_SCHEMAS_ANY_LAX;
6723     } else {
6724         xmlSchemaPSimpleTypeErr(ctxt,
6725 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6726 	    NULL, node,
6727 	    NULL, "(strict | skip | lax)", pc,
6728 	    NULL, NULL, NULL);
6729         wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6730 	ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
6731     }
6732     /*
6733      * Build the namespace constraints.
6734      */
6735     attr = xmlSchemaGetPropNode(node, "namespace");
6736     ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6737     if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
6738 	wildc->any = 1;
6739     else if (xmlStrEqual(ns, BAD_CAST "##other")) {
6740 	wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
6741 	if (wildc->negNsSet == NULL) {
6742 	    return (-1);
6743 	}
6744 	wildc->negNsSet->value = ctxt->targetNamespace;
6745     } else {
6746 	const xmlChar *end, *cur;
6747 
6748 	cur = ns;
6749 	do {
6750 	    while (IS_BLANK_CH(*cur))
6751 		cur++;
6752 	    end = cur;
6753 	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6754 		end++;
6755 	    if (end == cur)
6756 		break;
6757 	    nsItem = xmlStrndup(cur, end - cur);
6758 	    if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
6759 		    (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
6760 		xmlSchemaPSimpleTypeErr(ctxt,
6761 		    XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
6762 		    NULL, (xmlNodePtr) attr,
6763 		    NULL,
6764 		    "((##any | ##other) | List of (xs:anyURI | "
6765 		    "(##targetNamespace | ##local)))",
6766 		    nsItem, NULL, NULL, NULL);
6767 		ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
6768 	    } else {
6769 		if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
6770 		    dictnsItem = ctxt->targetNamespace;
6771 		} else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
6772 		    dictnsItem = NULL;
6773 		} else {
6774 		    /*
6775 		    * Validate the item (anyURI).
6776 		    */
6777 		    xmlSchemaPValAttrNodeValue(ctxt, NULL, attr,
6778 			nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
6779 		    dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
6780 		}
6781 		/*
6782 		* Avoid dublicate namespaces.
6783 		*/
6784 		tmp = wildc->nsSet;
6785 		while (tmp != NULL) {
6786 		    if (dictnsItem == tmp->value)
6787 			break;
6788 		    tmp = tmp->next;
6789 		}
6790 		if (tmp == NULL) {
6791 		    tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
6792 		    if (tmp == NULL) {
6793 			xmlFree(nsItem);
6794 			return (-1);
6795 		    }
6796 		    tmp->value = dictnsItem;
6797 		    tmp->next = NULL;
6798 		    if (wildc->nsSet == NULL)
6799 			wildc->nsSet = tmp;
6800 		    else
6801 			lastNs->next = tmp;
6802 		    lastNs = tmp;
6803 		}
6804 
6805 	    }
6806 	    xmlFree(nsItem);
6807 	    cur = end;
6808 	} while (*cur != 0);
6809     }
6810     return (ret);
6811 }
6812 
6813 static int
xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,xmlNodePtr node,int minOccurs,int maxOccurs)6814 xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
6815 				 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
6816 				 xmlNodePtr node,
6817 				 int minOccurs,
6818 				 int maxOccurs) {
6819 
6820     if ((maxOccurs == 0) && ( minOccurs == 0))
6821 	return (0);
6822     if (maxOccurs != UNBOUNDED) {
6823 	/*
6824 	* TODO: Maybe we should better not create the particle,
6825 	* if min/max is invalid, since it could confuse the build of the
6826 	* content model.
6827 	*/
6828 	/*
6829 	* 3.9.6 Schema Component Constraint: Particle Correct
6830 	*
6831 	*/
6832 	if (maxOccurs < 1) {
6833 	    /*
6834 	    * 2.2 {max occurs} must be greater than or equal to 1.
6835 	    */
6836 	    xmlSchemaPCustomAttrErr(ctxt,
6837 		XML_SCHEMAP_P_PROPS_CORRECT_2_2,
6838 		NULL, NULL,
6839 		xmlSchemaGetPropNode(node, "maxOccurs"),
6840 		"The value must be greater than or equal to 1");
6841 	    return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6842 	} else if (minOccurs > maxOccurs) {
6843 	    /*
6844 	    * 2.1 {min occurs} must not be greater than {max occurs}.
6845 	    */
6846 	    xmlSchemaPCustomAttrErr(ctxt,
6847 		XML_SCHEMAP_P_PROPS_CORRECT_2_1,
6848 		NULL, NULL,
6849 		xmlSchemaGetPropNode(node, "minOccurs"),
6850 		"The value must not be greater than the value of 'maxOccurs'");
6851 	    return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6852 	}
6853     }
6854     return (0);
6855 }
6856 
6857 /**
6858  * xmlSchemaParseAny:
6859  * @ctxt:  a schema validation context
6860  * @schema:  the schema being built
6861  * @node:  a subtree containing XML Schema informations
6862  *
6863  * Parsea a XML schema <any> element. A particle and wildcard
6864  * will be created (except if minOccurs==maxOccurs==0, in this case
6865  * nothing will be created).
6866  * *WARNING* this interface is highly subject to change
6867  *
6868  * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
6869  */
6870 static xmlSchemaParticlePtr
xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)6871 xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6872                   xmlNodePtr node)
6873 {
6874     xmlSchemaParticlePtr particle;
6875     xmlNodePtr child = NULL;
6876     xmlSchemaWildcardPtr wild;
6877     int min, max;
6878     xmlAttrPtr attr;
6879     xmlSchemaAnnotPtr annot = NULL;
6880 
6881     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6882         return (NULL);
6883     /*
6884     * Check for illegal attributes.
6885     */
6886     attr = node->properties;
6887     while (attr != NULL) {
6888 	if (attr->ns == NULL) {
6889 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6890 		(!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6891 		(!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6892 	        (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6893 		(!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
6894 		xmlSchemaPIllegalAttrErr(ctxt,
6895 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6896 	    }
6897 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6898 	    xmlSchemaPIllegalAttrErr(ctxt,
6899 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6900 	}
6901 	attr = attr->next;
6902     }
6903     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6904     /*
6905     * minOccurs/maxOccurs.
6906     */
6907     max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
6908 	"(xs:nonNegativeInteger | unbounded)");
6909     min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
6910 	"xs:nonNegativeInteger");
6911     xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
6912     /*
6913     * Create & parse the wildcard.
6914     */
6915     wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
6916     if (wild == NULL)
6917 	return (NULL);
6918     xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
6919     /*
6920     * And now for the children...
6921     */
6922     child = node->children;
6923     if (IS_SCHEMA(child, "annotation")) {
6924         annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6925         child = child->next;
6926     }
6927     if (child != NULL) {
6928 	xmlSchemaPContentErr(ctxt,
6929 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6930 	    NULL, node, child,
6931 	    NULL, "(annotation?)");
6932     }
6933     /*
6934     * No component if minOccurs==maxOccurs==0.
6935     */
6936     if ((min == 0) && (max == 0)) {
6937 	/* Don't free the wildcard, since it's already on the list. */
6938 	return (NULL);
6939     }
6940     /*
6941     * Create the particle.
6942     */
6943     particle = xmlSchemaAddParticle(ctxt, node, min, max);
6944     if (particle == NULL)
6945         return (NULL);
6946     particle->annot = annot;
6947     particle->children = (xmlSchemaTreeItemPtr) wild;
6948 
6949     return (particle);
6950 }
6951 
6952 /**
6953  * xmlSchemaParseNotation:
6954  * @ctxt:  a schema validation context
6955  * @schema:  the schema being built
6956  * @node:  a subtree containing XML Schema informations
6957  *
6958  * parse a XML schema Notation declaration
6959  *
6960  * Returns the new structure or NULL in case of error
6961  */
6962 static xmlSchemaNotationPtr
xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)6963 xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6964                        xmlNodePtr node)
6965 {
6966     const xmlChar *name;
6967     xmlSchemaNotationPtr ret;
6968     xmlNodePtr child = NULL;
6969 
6970     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6971         return (NULL);
6972     name = xmlSchemaGetProp(ctxt, node, "name");
6973     if (name == NULL) {
6974         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
6975                        "Notation has no name\n", NULL, NULL);
6976         return (NULL);
6977     }
6978     ret = xmlSchemaAddNotation(ctxt, schema, name,
6979 	ctxt->targetNamespace, node);
6980     if (ret == NULL)
6981         return (NULL);
6982     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6983 
6984     child = node->children;
6985     if (IS_SCHEMA(child, "annotation")) {
6986         ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6987         child = child->next;
6988     }
6989     if (child != NULL) {
6990 	xmlSchemaPContentErr(ctxt,
6991 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6992 	    NULL, node, child,
6993 	    NULL, "(annotation?)");
6994     }
6995 
6996     return (ret);
6997 }
6998 
6999 /**
7000  * xmlSchemaParseAnyAttribute:
7001  * @ctxt:  a schema validation context
7002  * @schema:  the schema being built
7003  * @node:  a subtree containing XML Schema informations
7004  *
7005  * parse a XML schema AnyAttrribute declaration
7006  * *WARNING* this interface is highly subject to change
7007  *
7008  * Returns a wildcard or NULL.
7009  */
7010 static xmlSchemaWildcardPtr
xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)7011 xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
7012                            xmlSchemaPtr schema, xmlNodePtr node)
7013 {
7014     xmlSchemaWildcardPtr ret;
7015     xmlNodePtr child = NULL;
7016     xmlAttrPtr attr;
7017 
7018     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7019         return (NULL);
7020 
7021     ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
7022 	node);
7023     if (ret == NULL) {
7024         return (NULL);
7025     }
7026     /*
7027     * Check for illegal attributes.
7028     */
7029     attr = node->properties;
7030     while (attr != NULL) {
7031 	if (attr->ns == NULL) {
7032 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7033 	        (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
7034 		(!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
7035 		xmlSchemaPIllegalAttrErr(ctxt,
7036 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7037 	    }
7038 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7039 	    xmlSchemaPIllegalAttrErr(ctxt,
7040 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7041 	}
7042 	attr = attr->next;
7043     }
7044     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
7045     /*
7046     * Parse the namespace list.
7047     */
7048     if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
7049 	return (NULL);
7050     /*
7051     * And now for the children...
7052     */
7053     child = node->children;
7054     if (IS_SCHEMA(child, "annotation")) {
7055         ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
7056         child = child->next;
7057     }
7058     if (child != NULL) {
7059 	xmlSchemaPContentErr(ctxt,
7060 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7061 	    NULL, node, child,
7062 	    NULL, "(annotation?)");
7063     }
7064 
7065     return (ret);
7066 }
7067 
7068 
7069 /**
7070  * xmlSchemaParseAttribute:
7071  * @ctxt:  a schema validation context
7072  * @schema:  the schema being built
7073  * @node:  a subtree containing XML Schema informations
7074  *
7075  * parse a XML schema Attrribute declaration
7076  * *WARNING* this interface is highly subject to change
7077  *
7078  * Returns the attribute declaration.
7079  */
7080 static xmlSchemaBasicItemPtr
xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlSchemaItemListPtr uses,int parentType)7081 xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
7082 			     xmlSchemaPtr schema,
7083 			     xmlNodePtr node,
7084 			     xmlSchemaItemListPtr uses,
7085 			     int parentType)
7086 {
7087     const xmlChar *attrValue, *name = NULL, *ns = NULL;
7088     xmlSchemaAttributeUsePtr use = NULL;
7089     xmlNodePtr child = NULL;
7090     xmlAttrPtr attr;
7091     const xmlChar *tmpNs = NULL, *tmpName = NULL, *defValue = NULL;
7092     int isRef = 0, occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7093     int	nberrors, hasForm = 0, defValueType = 0;
7094 
7095 #define WXS_ATTR_DEF_VAL_DEFAULT 1
7096 #define WXS_ATTR_DEF_VAL_FIXED 2
7097 
7098     /*
7099      * 3.2.3 Constraints on XML Representations of Attribute Declarations
7100      */
7101 
7102     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7103         return (NULL);
7104     attr = xmlSchemaGetPropNode(node, "ref");
7105     if (attr != NULL) {
7106 	if (xmlSchemaPValAttrNodeQName(pctxt, schema,
7107 	    NULL, attr, &tmpNs, &tmpName) != 0) {
7108 	    return (NULL);
7109 	}
7110 	if (xmlSchemaCheckReference(pctxt, schema, node, attr, tmpNs) != 0)
7111 	    return(NULL);
7112 	isRef = 1;
7113     }
7114     nberrors = pctxt->nberrors;
7115     /*
7116     * Check for illegal attributes.
7117     */
7118     attr = node->properties;
7119     while (attr != NULL) {
7120 	if (attr->ns == NULL) {
7121 	    if (isRef) {
7122 		if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7123 		    xmlSchemaPValAttrNodeID(pctxt, attr);
7124 		    goto attr_next;
7125 		} else if (xmlStrEqual(attr->name, BAD_CAST "ref")) {
7126 		    goto attr_next;
7127 		}
7128 	    } else {
7129 		if (xmlStrEqual(attr->name, BAD_CAST "name")) {
7130 		    goto attr_next;
7131 		} else if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7132 		    xmlSchemaPValAttrNodeID(pctxt, attr);
7133 		    goto attr_next;
7134 		} else if (xmlStrEqual(attr->name, BAD_CAST "type")) {
7135 		    xmlSchemaPValAttrNodeQName(pctxt, schema, NULL,
7136 			attr, &tmpNs, &tmpName);
7137 		    goto attr_next;
7138 		} else if (xmlStrEqual(attr->name, BAD_CAST "form")) {
7139 		    /*
7140 		    * Evaluate the target namespace
7141 		    */
7142 		    hasForm = 1;
7143 		    attrValue = xmlSchemaGetNodeContent(pctxt,
7144 			(xmlNodePtr) attr);
7145 		    if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
7146 			ns = pctxt->targetNamespace;
7147 		    } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified"))
7148 		    {
7149 			xmlSchemaPSimpleTypeErr(pctxt,
7150 			    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7151 			    NULL, (xmlNodePtr) attr,
7152 			    NULL, "(qualified | unqualified)",
7153 			    attrValue, NULL, NULL, NULL);
7154 		    }
7155 		    goto attr_next;
7156 		}
7157 	    }
7158 	    if (xmlStrEqual(attr->name, BAD_CAST "use")) {
7159 
7160 		attrValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7161 		/* TODO: Maybe we need to normalize the value beforehand. */
7162 		if (xmlStrEqual(attrValue, BAD_CAST "optional"))
7163 		    occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7164 		else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
7165 		    occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
7166 		else if (xmlStrEqual(attrValue, BAD_CAST "required"))
7167 		    occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
7168 		else {
7169 		    xmlSchemaPSimpleTypeErr(pctxt,
7170 			XML_SCHEMAP_INVALID_ATTR_USE,
7171 			NULL, (xmlNodePtr) attr,
7172 			NULL, "(optional | prohibited | required)",
7173 			attrValue, NULL, NULL, NULL);
7174 		}
7175 		goto attr_next;
7176 	    } else if (xmlStrEqual(attr->name, BAD_CAST "default")) {
7177 		/*
7178 		* 3.2.3 : 1
7179 		* default and fixed must not both be present.
7180 		*/
7181 		if (defValue) {
7182 		    xmlSchemaPMutualExclAttrErr(pctxt,
7183 			XML_SCHEMAP_SRC_ATTRIBUTE_1,
7184 			NULL, attr, "default", "fixed");
7185 		} else {
7186 		    defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7187 		    defValueType = WXS_ATTR_DEF_VAL_DEFAULT;
7188 		}
7189 		goto attr_next;
7190 	    } else if (xmlStrEqual(attr->name, BAD_CAST "fixed")) {
7191 		/*
7192 		* 3.2.3 : 1
7193 		* default and fixed must not both be present.
7194 		*/
7195 		if (defValue) {
7196 		    xmlSchemaPMutualExclAttrErr(pctxt,
7197 			XML_SCHEMAP_SRC_ATTRIBUTE_1,
7198 			NULL, attr, "default", "fixed");
7199 		} else {
7200 		    defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7201 		    defValueType = WXS_ATTR_DEF_VAL_FIXED;
7202 		}
7203 		goto attr_next;
7204 	    }
7205 	} else if (! xmlStrEqual(attr->ns->href, xmlSchemaNs))
7206 	    goto attr_next;
7207 
7208 	xmlSchemaPIllegalAttrErr(pctxt,
7209 	    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7210 
7211 attr_next:
7212 	attr = attr->next;
7213     }
7214     /*
7215     * 3.2.3 : 2
7216     * If default and use are both present, use must have
7217     * the actual value optional.
7218     */
7219     if ((defValueType == WXS_ATTR_DEF_VAL_DEFAULT) &&
7220 	(occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
7221 	xmlSchemaPSimpleTypeErr(pctxt,
7222 	    XML_SCHEMAP_SRC_ATTRIBUTE_2,
7223 	    NULL, node, NULL,
7224 	    "(optional | prohibited | required)", NULL,
7225 	    "The value of the attribute 'use' must be 'optional' "
7226 	    "if the attribute 'default' is present",
7227 	    NULL, NULL);
7228     }
7229     /*
7230     * We want correct attributes.
7231     */
7232     if (nberrors != pctxt->nberrors)
7233 	return(NULL);
7234     if (! isRef) {
7235 	xmlSchemaAttributePtr attrDecl;
7236 
7237 	/* TODO: move XML_SCHEMAS_QUALIF_ATTR to the parser. */
7238 	if ((! hasForm) && (schema->flags & XML_SCHEMAS_QUALIF_ATTR))
7239 	    ns = pctxt->targetNamespace;
7240 	/*
7241 	* 3.2.6 Schema Component Constraint: xsi: Not Allowed
7242 	* TODO: Move this to the component layer.
7243 	*/
7244 	if (xmlStrEqual(ns, xmlSchemaInstanceNs)) {
7245 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
7246 		XML_SCHEMAP_NO_XSI,
7247 		node, NULL,
7248 		"The target namespace must not match '%s'",
7249 		xmlSchemaInstanceNs, NULL);
7250 	}
7251 	attr = xmlSchemaGetPropNode(node, "name");
7252 	if (attr == NULL) {
7253 	    xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7254 		NULL, node, "name", NULL);
7255 	    return (NULL);
7256 	}
7257 	if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7258 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7259 	    return (NULL);
7260 	}
7261 	/*
7262 	* 3.2.6 Schema Component Constraint: xmlns Not Allowed
7263 	* TODO: Move this to the component layer.
7264 	*/
7265 	if (xmlStrEqual(name, BAD_CAST "xmlns")) {
7266 	    xmlSchemaPSimpleTypeErr(pctxt,
7267 		XML_SCHEMAP_NO_XMLNS,
7268 		NULL, (xmlNodePtr) attr,
7269 		xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7270 		"The value of the attribute must not match 'xmlns'",
7271 		NULL, NULL);
7272 	    return (NULL);
7273 	}
7274 	if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED)
7275 	    goto check_children;
7276 	/*
7277 	* Create the attribute use component.
7278 	*/
7279 	use = xmlSchemaAddAttributeUse(pctxt, node);
7280 	if (use == NULL)
7281 	    return(NULL);
7282 	use->occurs = occurs;
7283 	/*
7284 	* Create the attribute declaration.
7285 	*/
7286 	attrDecl = xmlSchemaAddAttribute(pctxt, schema, name, ns, node, 0);
7287 	if (attrDecl == NULL)
7288 	    return (NULL);
7289 	if (tmpName != NULL) {
7290 	    attrDecl->typeName = tmpName;
7291 	    attrDecl->typeNs = tmpNs;
7292 	}
7293 	use->attrDecl = attrDecl;
7294 	/*
7295 	* Value constraint.
7296 	*/
7297 	if (defValue != NULL) {
7298 	    attrDecl->defValue = defValue;
7299 	    if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7300 		attrDecl->flags |= XML_SCHEMAS_ATTR_FIXED;
7301 	}
7302     } else if (occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7303 	xmlSchemaQNameRefPtr ref;
7304 
7305 	/*
7306 	* Create the attribute use component.
7307 	*/
7308 	use = xmlSchemaAddAttributeUse(pctxt, node);
7309 	if (use == NULL)
7310 	    return(NULL);
7311 	/*
7312 	* We need to resolve the reference at later stage.
7313 	*/
7314 	WXS_ADD_PENDING(pctxt, use);
7315 	use->occurs = occurs;
7316 	/*
7317 	* Create a QName reference to the attribute declaration.
7318 	*/
7319 	ref = xmlSchemaNewQNameRef(pctxt, XML_SCHEMA_TYPE_ATTRIBUTE,
7320 	    tmpName, tmpNs);
7321 	if (ref == NULL)
7322 	    return(NULL);
7323 	/*
7324 	* Assign the reference. This will be substituted for the
7325 	* referenced attribute declaration when the QName is resolved.
7326 	*/
7327 	use->attrDecl = WXS_ATTR_CAST ref;
7328 	/*
7329 	* Value constraint.
7330 	*/
7331 	if (defValue != NULL)
7332 	    use->defValue = defValue;
7333 	    if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7334 		use->flags |= XML_SCHEMA_ATTR_USE_FIXED;
7335     }
7336 
7337 check_children:
7338     /*
7339     * And now for the children...
7340     */
7341     child = node->children;
7342     if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7343 	xmlSchemaAttributeUseProhibPtr prohib;
7344 
7345 	if (IS_SCHEMA(child, "annotation")) {
7346 	    xmlSchemaParseAnnotation(pctxt, child, 0);
7347 	    child = child->next;
7348 	}
7349 	if (child != NULL) {
7350 	    xmlSchemaPContentErr(pctxt,
7351 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7352 		NULL, node, child, NULL,
7353 		"(annotation?)");
7354 	}
7355 	/*
7356 	* Check for pointlessness of attribute prohibitions.
7357 	*/
7358 	if (parentType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
7359 	    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7360 		XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7361 		node, NULL,
7362 		"Skipping attribute use prohibition, since it is "
7363 		"pointless inside an <attributeGroup>",
7364 		NULL, NULL, NULL);
7365 	    return(NULL);
7366 	} else if (parentType == XML_SCHEMA_TYPE_EXTENSION) {
7367 	    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7368 		XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7369 		node, NULL,
7370 		"Skipping attribute use prohibition, since it is "
7371 		"pointless when extending a type",
7372 		NULL, NULL, NULL);
7373 	    return(NULL);
7374 	}
7375 	if (! isRef) {
7376 	    tmpName = name;
7377 	    tmpNs = ns;
7378 	}
7379 	/*
7380 	* Check for duplicate attribute prohibitions.
7381 	*/
7382 	if (uses) {
7383 	    int i;
7384 
7385 	    for (i = 0; i < uses->nbItems; i++) {
7386 		use = uses->items[i];
7387 		if ((use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) &&
7388 		    (tmpName == (WXS_ATTR_PROHIB_CAST use)->name) &&
7389 		    (tmpNs == (WXS_ATTR_PROHIB_CAST use)->targetNamespace))
7390 		{
7391 		    xmlChar *str = NULL;
7392 
7393 		    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7394 			XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7395 			node, NULL,
7396 			"Skipping duplicate attribute use prohibition '%s'",
7397 			xmlSchemaFormatQName(&str, tmpNs, tmpName),
7398 			NULL, NULL);
7399 		    FREE_AND_NULL(str)
7400 		    return(NULL);
7401 		}
7402 	    }
7403 	}
7404 	/*
7405 	* Create the attribute prohibition helper component.
7406 	*/
7407 	prohib = xmlSchemaAddAttributeUseProhib(pctxt);
7408 	if (prohib == NULL)
7409 	    return(NULL);
7410 	prohib->node = node;
7411 	prohib->name = tmpName;
7412 	prohib->targetNamespace = tmpNs;
7413 	if (isRef) {
7414 	    /*
7415 	    * We need at least to resolve to the attribute declaration.
7416 	    */
7417 	    WXS_ADD_PENDING(pctxt, prohib);
7418 	}
7419 	return(WXS_BASIC_CAST prohib);
7420     } else {
7421 	if (IS_SCHEMA(child, "annotation")) {
7422 	    /*
7423 	    * TODO: Should this go into the attr decl?
7424 	    */
7425 	    use->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7426 	    child = child->next;
7427 	}
7428 	if (isRef) {
7429 	    if (child != NULL) {
7430 		if (IS_SCHEMA(child, "simpleType"))
7431 		    /*
7432 		    * 3.2.3 : 3.2
7433 		    * If ref is present, then all of <simpleType>,
7434 		    * form and type must be absent.
7435 		    */
7436 		    xmlSchemaPContentErr(pctxt,
7437 			XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
7438 			NULL, node, child, NULL,
7439 			"(annotation?)");
7440 		else
7441 		    xmlSchemaPContentErr(pctxt,
7442 			XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7443 			NULL, node, child, NULL,
7444 			"(annotation?)");
7445 	    }
7446 	} else {
7447 	    if (IS_SCHEMA(child, "simpleType")) {
7448 		if (WXS_ATTRUSE_DECL(use)->typeName != NULL) {
7449 		    /*
7450 		    * 3.2.3 : 4
7451 		    * type and <simpleType> must not both be present.
7452 		    */
7453 		    xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7454 			NULL, node, child,
7455 			"The attribute 'type' and the <simpleType> child "
7456 			"are mutually exclusive", NULL);
7457 		} else
7458 		    WXS_ATTRUSE_TYPEDEF(use) =
7459 			xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7460 		child = child->next;
7461 	    }
7462 	    if (child != NULL)
7463 		xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7464 		NULL, node, child, NULL,
7465 		"(annotation?, simpleType?)");
7466 	}
7467     }
7468     return (WXS_BASIC_CAST use);
7469 }
7470 
7471 
7472 static xmlSchemaAttributePtr
xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)7473 xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt,
7474 			      xmlSchemaPtr schema,
7475 			      xmlNodePtr node)
7476 {
7477     const xmlChar *attrValue;
7478     xmlSchemaAttributePtr ret;
7479     xmlNodePtr child = NULL;
7480     xmlAttrPtr attr;
7481 
7482     /*
7483      * Note that the w3c spec assumes the schema to be validated with schema
7484      * for schemas beforehand.
7485      *
7486      * 3.2.3 Constraints on XML Representations of Attribute Declarations
7487      */
7488     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7489         return (NULL);
7490     /*
7491     * 3.2.3 : 3.1
7492     * One of ref or name must be present, but not both
7493     */
7494     attr = xmlSchemaGetPropNode(node, "name");
7495     if (attr == NULL) {
7496 	xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7497 	    NULL, node, "name", NULL);
7498 	return (NULL);
7499     }
7500     if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7501 	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
7502 	return (NULL);
7503     }
7504     /*
7505     * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7506     * TODO: Move this to the component layer.
7507     */
7508     if (xmlStrEqual(attrValue, BAD_CAST "xmlns")) {
7509 	xmlSchemaPSimpleTypeErr(pctxt,
7510 	    XML_SCHEMAP_NO_XMLNS,
7511 	    NULL, (xmlNodePtr) attr,
7512 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7513 	    "The value of the attribute must not match 'xmlns'",
7514 	    NULL, NULL);
7515 	return (NULL);
7516     }
7517     /*
7518     * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7519     * TODO: Move this to the component layer.
7520     *       Or better leave it here and add it to the component layer
7521     *       if we have a schema construction API.
7522     */
7523     if (xmlStrEqual(pctxt->targetNamespace, xmlSchemaInstanceNs)) {
7524 	xmlSchemaCustomErr(ACTXT_CAST pctxt,
7525 	    XML_SCHEMAP_NO_XSI, node, NULL,
7526 	    "The target namespace must not match '%s'",
7527 	    xmlSchemaInstanceNs, NULL);
7528     }
7529 
7530     ret = xmlSchemaAddAttribute(pctxt, schema, attrValue,
7531 	pctxt->targetNamespace, node, 1);
7532     if (ret == NULL)
7533 	return (NULL);
7534     ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
7535 
7536     /*
7537     * Check for illegal attributes.
7538     */
7539     attr = node->properties;
7540     while (attr != NULL) {
7541 	if (attr->ns == NULL) {
7542 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7543 		(!xmlStrEqual(attr->name, BAD_CAST "default")) &&
7544 		(!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
7545 		(!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7546 		(!xmlStrEqual(attr->name, BAD_CAST "type")))
7547 	    {
7548 		xmlSchemaPIllegalAttrErr(pctxt,
7549 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7550 	    }
7551 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7552 	    xmlSchemaPIllegalAttrErr(pctxt,
7553 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7554 	}
7555 	attr = attr->next;
7556     }
7557     xmlSchemaPValAttrQName(pctxt, schema, NULL,
7558 	node, "type", &ret->typeNs, &ret->typeName);
7559 
7560     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7561     /*
7562     * Attribute "fixed".
7563     */
7564     ret->defValue = xmlSchemaGetProp(pctxt, node, "fixed");
7565     if (ret->defValue != NULL)
7566 	ret->flags |= XML_SCHEMAS_ATTR_FIXED;
7567     /*
7568     * Attribute "default".
7569     */
7570     attr = xmlSchemaGetPropNode(node, "default");
7571     if (attr != NULL) {
7572 	/*
7573 	* 3.2.3 : 1
7574 	* default and fixed must not both be present.
7575 	*/
7576 	if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
7577 	    xmlSchemaPMutualExclAttrErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
7578 		WXS_BASIC_CAST ret, attr, "default", "fixed");
7579 	} else
7580 	    ret->defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7581     }
7582     /*
7583     * And now for the children...
7584     */
7585     child = node->children;
7586     if (IS_SCHEMA(child, "annotation")) {
7587         ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7588         child = child->next;
7589     }
7590     if (IS_SCHEMA(child, "simpleType")) {
7591 	if (ret->typeName != NULL) {
7592 	    /*
7593 	    * 3.2.3 : 4
7594 	    * type and <simpleType> must not both be present.
7595 	    */
7596 	    xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7597 		NULL, node, child,
7598 		"The attribute 'type' and the <simpleType> child "
7599 		"are mutually exclusive", NULL);
7600 	} else
7601 	    ret->subtypes = xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7602 	child = child->next;
7603     }
7604     if (child != NULL)
7605 	xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7606 	    NULL, node, child, NULL,
7607 	    "(annotation?, simpleType?)");
7608 
7609     return (ret);
7610 }
7611 
7612 /**
7613  * xmlSchemaParseAttributeGroupRef:
7614  * @ctxt:  a schema validation context
7615  * @schema:  the schema being built
7616  * @node:  a subtree containing XML Schema informations
7617  *
7618  * Parse an attribute group definition reference.
7619  * Note that a reference to an attribute group does not
7620  * correspond to any component at all.
7621  * *WARNING* this interface is highly subject to change
7622  *
7623  * Returns the attribute group or NULL in case of error.
7624  */
7625 static xmlSchemaQNameRefPtr
xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)7626 xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
7627 				xmlSchemaPtr schema,
7628 				xmlNodePtr node)
7629 {
7630     xmlSchemaQNameRefPtr ret;
7631     xmlNodePtr child = NULL;
7632     xmlAttrPtr attr;
7633     const xmlChar *refNs = NULL, *ref = NULL;
7634 
7635     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7636         return (NULL);
7637 
7638     attr = xmlSchemaGetPropNode(node, "ref");
7639     if (attr == NULL) {
7640 	xmlSchemaPMissingAttrErr(pctxt,
7641 	    XML_SCHEMAP_S4S_ATTR_MISSING,
7642 	    NULL, node, "ref", NULL);
7643 	return (NULL);
7644     }
7645     xmlSchemaPValAttrNodeQName(pctxt, schema,
7646 	NULL, attr, &refNs, &ref);
7647     if (xmlSchemaCheckReference(pctxt, schema, node, attr, refNs) != 0)
7648 	return(NULL);
7649 
7650     /*
7651     * Check for illegal attributes.
7652     */
7653     attr = node->properties;
7654     while (attr != NULL) {
7655 	if (attr->ns == NULL) {
7656 	    if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
7657 		(!xmlStrEqual(attr->name, BAD_CAST "id")))
7658 	    {
7659 		xmlSchemaPIllegalAttrErr(pctxt,
7660 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7661 	    }
7662 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7663 	    xmlSchemaPIllegalAttrErr(pctxt,
7664 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7665 	}
7666 	attr = attr->next;
7667     }
7668     /* Attribute ID */
7669     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7670 
7671     /*
7672     * And now for the children...
7673     */
7674     child = node->children;
7675     if (IS_SCHEMA(child, "annotation")) {
7676 	/*
7677 	* TODO: We do not have a place to store the annotation, do we?
7678 	*/
7679         xmlSchemaParseAnnotation(pctxt, child, 0);
7680         child = child->next;
7681     }
7682     if (child != NULL) {
7683 	xmlSchemaPContentErr(pctxt,
7684 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7685 	    NULL, node, child, NULL,
7686 	    "(annotation?)");
7687     }
7688 
7689     /*
7690     * Handle attribute group redefinitions.
7691     */
7692     if (pctxt->isRedefine && pctxt->redef &&
7693 	(pctxt->redef->item->type ==
7694 	    XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
7695 	(ref == pctxt->redef->refName) &&
7696 	(refNs == pctxt->redef->refTargetNs))
7697     {
7698 	/*
7699 	* SPEC src-redefine:
7700 	* (7.1) "If it has an <attributeGroup> among its contents
7701 	* the �actual value� of whose ref [attribute] is the same
7702 	* as the �actual value� of its own name attribute plus
7703 	* target namespace, then it must have exactly one such group."
7704 	*/
7705 	if (pctxt->redefCounter != 0) {
7706 	    xmlChar *str = NULL;
7707 
7708 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
7709 		XML_SCHEMAP_SRC_REDEFINE, node, NULL,
7710 		"The redefining attribute group definition "
7711 		"'%s' must not contain more than one "
7712 		"reference to the redefined definition",
7713 		xmlSchemaFormatQName(&str, refNs, ref), NULL);
7714 	    FREE_AND_NULL(str);
7715 	    return(NULL);
7716 	}
7717 	pctxt->redefCounter++;
7718 	/*
7719 	* URGENT TODO: How to ensure that the reference will not be
7720 	* handled by the normal component resolution mechanism?
7721 	*/
7722 	ret = xmlSchemaNewQNameRef(pctxt,
7723 	    XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7724 	if (ret == NULL)
7725 	    return(NULL);
7726 	ret->node = node;
7727 	pctxt->redef->reference = WXS_BASIC_CAST ret;
7728     } else {
7729 	/*
7730 	* Create a QName-reference helper component. We will substitute this
7731 	* component for the attribute uses of the referenced attribute group
7732 	* definition.
7733 	*/
7734 	ret = xmlSchemaNewQNameRef(pctxt,
7735 	    XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7736 	if (ret == NULL)
7737 	    return(NULL);
7738 	ret->node = node;
7739 	/* Add to pending items, to be able to resolve the reference. */
7740 	WXS_ADD_PENDING(pctxt, ret);
7741     }
7742     return (ret);
7743 }
7744 
7745 /**
7746  * xmlSchemaParseAttributeGroupDefinition:
7747  * @pctxt:  a schema validation context
7748  * @schema:  the schema being built
7749  * @node:  a subtree containing XML Schema informations
7750  *
7751  * parse a XML schema Attribute Group declaration
7752  * *WARNING* this interface is highly subject to change
7753  *
7754  * Returns the attribute group definition or NULL in case of error.
7755  */
7756 static xmlSchemaAttributeGroupPtr
xmlSchemaParseAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)7757 xmlSchemaParseAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
7758 				       xmlSchemaPtr schema,
7759 				       xmlNodePtr node)
7760 {
7761     const xmlChar *name;
7762     xmlSchemaAttributeGroupPtr ret;
7763     xmlNodePtr child = NULL;
7764     xmlAttrPtr attr;
7765     int hasRefs = 0;
7766 
7767     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7768         return (NULL);
7769 
7770     attr = xmlSchemaGetPropNode(node, "name");
7771     if (attr == NULL) {
7772 	xmlSchemaPMissingAttrErr(pctxt,
7773 	    XML_SCHEMAP_S4S_ATTR_MISSING,
7774 	    NULL, node, "name", NULL);
7775 	return (NULL);
7776     }
7777     /*
7778     * The name is crucial, exit if invalid.
7779     */
7780     if (xmlSchemaPValAttrNode(pctxt,
7781 	NULL, attr,
7782 	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7783 	return (NULL);
7784     }
7785     ret = xmlSchemaAddAttributeGroupDefinition(pctxt, schema,
7786 	name, pctxt->targetNamespace, node);
7787     if (ret == NULL)
7788 	return (NULL);
7789     /*
7790     * Check for illegal attributes.
7791     */
7792     attr = node->properties;
7793     while (attr != NULL) {
7794 	if (attr->ns == NULL) {
7795 	    if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7796 		(!xmlStrEqual(attr->name, BAD_CAST "id")))
7797 	    {
7798 		xmlSchemaPIllegalAttrErr(pctxt,
7799 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7800 	    }
7801 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7802 	    xmlSchemaPIllegalAttrErr(pctxt,
7803 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7804 	}
7805 	attr = attr->next;
7806     }
7807     /* Attribute ID */
7808     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7809     /*
7810     * And now for the children...
7811     */
7812     child = node->children;
7813     if (IS_SCHEMA(child, "annotation")) {
7814         ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7815         child = child->next;
7816     }
7817     /*
7818     * Parse contained attribute decls/refs.
7819     */
7820     if (xmlSchemaParseLocalAttributes(pctxt, schema, &child,
7821 	(xmlSchemaItemListPtr *) &(ret->attrUses),
7822 	XML_SCHEMA_TYPE_ATTRIBUTEGROUP, &hasRefs) == -1)
7823 	return(NULL);
7824     if (hasRefs)
7825 	ret->flags |= XML_SCHEMAS_ATTRGROUP_HAS_REFS;
7826     /*
7827     * Parse the attribute wildcard.
7828     */
7829     if (IS_SCHEMA(child, "anyAttribute")) {
7830 	ret->attributeWildcard = xmlSchemaParseAnyAttribute(pctxt,
7831 	    schema, child);
7832 	child = child->next;
7833     }
7834     if (child != NULL) {
7835 	xmlSchemaPContentErr(pctxt,
7836 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7837 	    NULL, node, child, NULL,
7838 	    "(annotation?, ((attribute | attributeGroup)*, anyAttribute?))");
7839     }
7840     return (ret);
7841 }
7842 
7843 /**
7844  * xmlSchemaPValAttrFormDefault:
7845  * @value:  the value
7846  * @flags: the flags to be modified
7847  * @flagQualified: the specific flag for "qualified"
7848  *
7849  * Returns 0 if the value is valid, 1 otherwise.
7850  */
7851 static int
xmlSchemaPValAttrFormDefault(const xmlChar * value,int * flags,int flagQualified)7852 xmlSchemaPValAttrFormDefault(const xmlChar *value,
7853 			     int *flags,
7854 			     int flagQualified)
7855 {
7856     if (xmlStrEqual(value, BAD_CAST "qualified")) {
7857 	if  ((*flags & flagQualified) == 0)
7858 	    *flags |= flagQualified;
7859     } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
7860 	return (1);
7861 
7862     return (0);
7863 }
7864 
7865 /**
7866  * xmlSchemaPValAttrBlockFinal:
7867  * @value:  the value
7868  * @flags: the flags to be modified
7869  * @flagAll: the specific flag for "#all"
7870  * @flagExtension: the specific flag for "extension"
7871  * @flagRestriction: the specific flag for "restriction"
7872  * @flagSubstitution: the specific flag for "substitution"
7873  * @flagList: the specific flag for "list"
7874  * @flagUnion: the specific flag for "union"
7875  *
7876  * Validates the value of the attribute "final" and "block". The value
7877  * is converted into the specified flag values and returned in @flags.
7878  *
7879  * Returns 0 if the value is valid, 1 otherwise.
7880  */
7881 
7882 static int
xmlSchemaPValAttrBlockFinal(const xmlChar * value,int * flags,int flagAll,int flagExtension,int flagRestriction,int flagSubstitution,int flagList,int flagUnion)7883 xmlSchemaPValAttrBlockFinal(const xmlChar *value,
7884 			    int *flags,
7885 			    int flagAll,
7886 			    int flagExtension,
7887 			    int flagRestriction,
7888 			    int flagSubstitution,
7889 			    int flagList,
7890 			    int flagUnion)
7891 {
7892     int ret = 0;
7893 
7894     /*
7895     * TODO: This does not check for dublicate entries.
7896     */
7897     if ((flags == NULL) || (value == NULL))
7898 	return (-1);
7899     if (value[0] == 0)
7900 	return (0);
7901     if (xmlStrEqual(value, BAD_CAST "#all")) {
7902 	if (flagAll != -1)
7903 	    *flags |= flagAll;
7904 	else {
7905 	    if (flagExtension != -1)
7906 		*flags |= flagExtension;
7907 	    if (flagRestriction != -1)
7908 		*flags |= flagRestriction;
7909 	    if (flagSubstitution != -1)
7910 		*flags |= flagSubstitution;
7911 	    if (flagList != -1)
7912 		*flags |= flagList;
7913 	    if (flagUnion != -1)
7914 		*flags |= flagUnion;
7915 	}
7916     } else {
7917 	const xmlChar *end, *cur = value;
7918 	xmlChar *item;
7919 
7920 	do {
7921 	    while (IS_BLANK_CH(*cur))
7922 		cur++;
7923 	    end = cur;
7924 	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7925 		end++;
7926 	    if (end == cur)
7927 		break;
7928 	    item = xmlStrndup(cur, end - cur);
7929 	    if (xmlStrEqual(item, BAD_CAST "extension")) {
7930 		if (flagExtension != -1) {
7931 		    if ((*flags & flagExtension) == 0)
7932 			*flags |= flagExtension;
7933 		} else
7934 		    ret = 1;
7935 	    } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
7936 		if (flagRestriction != -1) {
7937 		    if ((*flags & flagRestriction) == 0)
7938 			*flags |= flagRestriction;
7939 		} else
7940 		    ret = 1;
7941 	    } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
7942 		if (flagSubstitution != -1) {
7943 		    if ((*flags & flagSubstitution) == 0)
7944 			*flags |= flagSubstitution;
7945 		} else
7946 		    ret = 1;
7947 	    } else if (xmlStrEqual(item, BAD_CAST "list")) {
7948 		if (flagList != -1) {
7949 		    if ((*flags & flagList) == 0)
7950 			*flags |= flagList;
7951 		} else
7952 		    ret = 1;
7953 	    } else if (xmlStrEqual(item, BAD_CAST "union")) {
7954 		if (flagUnion != -1) {
7955 		    if ((*flags & flagUnion) == 0)
7956 			*flags |= flagUnion;
7957 		} else
7958 		    ret = 1;
7959 	    } else
7960 		ret = 1;
7961 	    if (item != NULL)
7962 		xmlFree(item);
7963 	    cur = end;
7964 	} while ((ret == 0) && (*cur != 0));
7965     }
7966 
7967     return (ret);
7968 }
7969 
7970 static int
xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,xmlSchemaIDCPtr idc,xmlSchemaIDCSelectPtr selector,xmlAttrPtr attr,int isField)7971 xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
7972 			     xmlSchemaIDCPtr idc,
7973 			     xmlSchemaIDCSelectPtr selector,
7974 			     xmlAttrPtr attr,
7975 			     int isField)
7976 {
7977     xmlNodePtr node;
7978 
7979     /*
7980     * c-selector-xpath:
7981     * Schema Component Constraint: Selector Value OK
7982     *
7983     * TODO: 1 The {selector} must be a valid XPath expression, as defined
7984     * in [XPath].
7985     */
7986     if (selector == NULL) {
7987 	xmlSchemaPErr(ctxt, idc->node,
7988 	    XML_SCHEMAP_INTERNAL,
7989 	    "Internal error: xmlSchemaCheckCSelectorXPath, "
7990 	    "the selector is not specified.\n", NULL, NULL);
7991 	return (-1);
7992     }
7993     if (attr == NULL)
7994 	node = idc->node;
7995     else
7996 	node = (xmlNodePtr) attr;
7997     if (selector->xpath == NULL) {
7998 	xmlSchemaPCustomErr(ctxt,
7999 	    /* TODO: Adjust error code. */
8000 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8001 	    NULL, node,
8002 	    "The XPath expression of the selector is not valid", NULL);
8003 	return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
8004     } else {
8005 	const xmlChar **nsArray = NULL;
8006 	xmlNsPtr *nsList = NULL;
8007 	/*
8008 	* Compile the XPath expression.
8009 	*/
8010 	/*
8011 	* TODO: We need the array of in-scope namespaces for compilation.
8012 	* TODO: Call xmlPatterncompile with different options for selector/
8013 	* field.
8014 	*/
8015 	if (attr == NULL)
8016 	    nsList = NULL;
8017 	else
8018 	    nsList = xmlGetNsList(attr->doc, attr->parent);
8019 	/*
8020 	* Build an array of prefixes and namespaces.
8021 	*/
8022 	if (nsList != NULL) {
8023 	    int i, count = 0;
8024 
8025 	    for (i = 0; nsList[i] != NULL; i++)
8026 		count++;
8027 
8028 	    nsArray = (const xmlChar **) xmlMalloc(
8029 		(count * 2 + 1) * sizeof(const xmlChar *));
8030 	    if (nsArray == NULL) {
8031 		xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
8032 		    NULL);
8033 		xmlFree(nsList);
8034 		return (-1);
8035 	    }
8036 	    for (i = 0; i < count; i++) {
8037 		nsArray[2 * i] = nsList[i]->href;
8038 		nsArray[2 * i + 1] = nsList[i]->prefix;
8039 	    }
8040 	    nsArray[count * 2] = NULL;
8041 	    xmlFree(nsList);
8042 	}
8043 	/*
8044 	* TODO: Differentiate between "selector" and "field".
8045 	*/
8046 	if (isField)
8047 	    selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
8048 		NULL, XML_PATTERN_XSFIELD, nsArray);
8049 	else
8050 	    selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
8051 		NULL, XML_PATTERN_XSSEL, nsArray);
8052 	if (nsArray != NULL)
8053 	    xmlFree((xmlChar **) nsArray);
8054 
8055 	if (selector->xpathComp == NULL) {
8056 	    xmlSchemaPCustomErr(ctxt,
8057 		/* TODO: Adjust error code? */
8058 		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8059 		NULL, node,
8060 		"The XPath expression '%s' could not be "
8061 		"compiled", selector->xpath);
8062 	    return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
8063 	}
8064     }
8065     return (0);
8066 }
8067 
8068 #define ADD_ANNOTATION(annot)   \
8069     xmlSchemaAnnotPtr cur = item->annot; \
8070     if (item->annot == NULL) {  \
8071 	item->annot = annot;    \
8072 	return (annot);         \
8073     }                           \
8074     cur = item->annot;          \
8075     if (cur->next != NULL) {    \
8076 	cur = cur->next;	\
8077     }                           \
8078     cur->next = annot;
8079 
8080 /**
8081  * xmlSchemaAssignAnnotation:
8082  * @item: the schema component
8083  * @annot: the annotation
8084  *
8085  * Adds the annotation to the given schema component.
8086  *
8087  * Returns the given annotaion.
8088  */
8089 static xmlSchemaAnnotPtr
xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,xmlSchemaAnnotPtr annot)8090 xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
8091 		       xmlSchemaAnnotPtr annot)
8092 {
8093     if ((annItem == NULL) || (annot == NULL))
8094 	return (NULL);
8095     switch (annItem->type) {
8096 	case XML_SCHEMA_TYPE_ELEMENT: {
8097 		xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
8098 		ADD_ANNOTATION(annot)
8099 	    }
8100 	    break;
8101 	case XML_SCHEMA_TYPE_ATTRIBUTE: {
8102 		xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
8103 		ADD_ANNOTATION(annot)
8104 	    }
8105 	    break;
8106 	case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
8107 	case XML_SCHEMA_TYPE_ANY: {
8108 		xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
8109 		ADD_ANNOTATION(annot)
8110 	    }
8111 	    break;
8112 	case XML_SCHEMA_TYPE_PARTICLE:
8113 	case XML_SCHEMA_TYPE_IDC_KEY:
8114 	case XML_SCHEMA_TYPE_IDC_KEYREF:
8115 	case XML_SCHEMA_TYPE_IDC_UNIQUE: {
8116 		xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
8117 		ADD_ANNOTATION(annot)
8118 	    }
8119 	    break;
8120 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
8121 		xmlSchemaAttributeGroupPtr item =
8122 		    (xmlSchemaAttributeGroupPtr) annItem;
8123 		ADD_ANNOTATION(annot)
8124 	    }
8125 	    break;
8126 	case XML_SCHEMA_TYPE_NOTATION: {
8127 		xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
8128 		ADD_ANNOTATION(annot)
8129 	    }
8130 	    break;
8131 	case XML_SCHEMA_FACET_MININCLUSIVE:
8132 	case XML_SCHEMA_FACET_MINEXCLUSIVE:
8133 	case XML_SCHEMA_FACET_MAXINCLUSIVE:
8134 	case XML_SCHEMA_FACET_MAXEXCLUSIVE:
8135 	case XML_SCHEMA_FACET_TOTALDIGITS:
8136 	case XML_SCHEMA_FACET_FRACTIONDIGITS:
8137 	case XML_SCHEMA_FACET_PATTERN:
8138 	case XML_SCHEMA_FACET_ENUMERATION:
8139 	case XML_SCHEMA_FACET_WHITESPACE:
8140 	case XML_SCHEMA_FACET_LENGTH:
8141 	case XML_SCHEMA_FACET_MAXLENGTH:
8142 	case XML_SCHEMA_FACET_MINLENGTH: {
8143 		xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
8144 		ADD_ANNOTATION(annot)
8145 	    }
8146 	    break;
8147 	case XML_SCHEMA_TYPE_SIMPLE:
8148 	case XML_SCHEMA_TYPE_COMPLEX: {
8149 		xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
8150 		ADD_ANNOTATION(annot)
8151 	    }
8152 	    break;
8153 	case XML_SCHEMA_TYPE_GROUP: {
8154 		xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
8155 		ADD_ANNOTATION(annot)
8156 	    }
8157 	    break;
8158 	case XML_SCHEMA_TYPE_SEQUENCE:
8159 	case XML_SCHEMA_TYPE_CHOICE:
8160 	case XML_SCHEMA_TYPE_ALL: {
8161 		xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
8162 		ADD_ANNOTATION(annot)
8163 	    }
8164 	    break;
8165 	default:
8166 	     xmlSchemaPCustomErr(NULL,
8167 		XML_SCHEMAP_INTERNAL,
8168 		NULL, NULL,
8169 		"Internal error: xmlSchemaAddAnnotation, "
8170 		"The item is not a annotated schema component", NULL);
8171 	     break;
8172     }
8173     return (annot);
8174 }
8175 
8176 /**
8177  * xmlSchemaParseIDCSelectorAndField:
8178  * @ctxt:  a schema validation context
8179  * @schema:  the schema being built
8180  * @node:  a subtree containing XML Schema informations
8181  *
8182  * Parses a XML Schema identity-contraint definition's
8183  * <selector> and <field> elements.
8184  *
8185  * Returns the parsed identity-constraint definition.
8186  */
8187 static xmlSchemaIDCSelectPtr
xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,xmlSchemaIDCPtr idc,xmlNodePtr node,int isField)8188 xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
8189 			  xmlSchemaIDCPtr idc,
8190 			  xmlNodePtr node,
8191 			  int isField)
8192 {
8193     xmlSchemaIDCSelectPtr item;
8194     xmlNodePtr child = NULL;
8195     xmlAttrPtr attr;
8196 
8197     /*
8198     * Check for illegal attributes.
8199     */
8200     attr = node->properties;
8201     while (attr != NULL) {
8202 	if (attr->ns == NULL) {
8203 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8204 		(!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
8205 		xmlSchemaPIllegalAttrErr(ctxt,
8206 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8207 	    }
8208 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8209 	    xmlSchemaPIllegalAttrErr(ctxt,
8210 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8211 	}
8212 	attr = attr->next;
8213     }
8214     /*
8215     * Create the item.
8216     */
8217     item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
8218     if (item == NULL) {
8219         xmlSchemaPErrMemory(ctxt,
8220 	    "allocating a 'selector' of an identity-constraint definition",
8221 	    NULL);
8222         return (NULL);
8223     }
8224     memset(item, 0, sizeof(xmlSchemaIDCSelect));
8225     /*
8226     * Attribute "xpath" (mandatory).
8227     */
8228     attr = xmlSchemaGetPropNode(node, "xpath");
8229     if (attr == NULL) {
8230     	xmlSchemaPMissingAttrErr(ctxt,
8231 	    XML_SCHEMAP_S4S_ATTR_MISSING,
8232 	    NULL, node,
8233 	    "name", NULL);
8234     } else {
8235 	item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8236 	/*
8237 	* URGENT TODO: "field"s have an other syntax than "selector"s.
8238 	*/
8239 
8240 	if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
8241 	    isField) == -1) {
8242 	    xmlSchemaPErr(ctxt,
8243 		(xmlNodePtr) attr,
8244 		XML_SCHEMAP_INTERNAL,
8245 		"Internal error: xmlSchemaParseIDCSelectorAndField, "
8246 		"validating the XPath expression of a IDC selector.\n",
8247 		NULL, NULL);
8248 	}
8249 
8250     }
8251     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8252     /*
8253     * And now for the children...
8254     */
8255     child = node->children;
8256     if (IS_SCHEMA(child, "annotation")) {
8257 	/*
8258 	* Add the annotation to the parent IDC.
8259 	*/
8260 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
8261 	    xmlSchemaParseAnnotation(ctxt, child, 1));
8262 	child = child->next;
8263     }
8264     if (child != NULL) {
8265 	xmlSchemaPContentErr(ctxt,
8266 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8267 	    NULL, node, child,
8268 	    NULL, "(annotation?)");
8269     }
8270 
8271     return (item);
8272 }
8273 
8274 /**
8275  * xmlSchemaParseIDC:
8276  * @ctxt:  a schema validation context
8277  * @schema:  the schema being built
8278  * @node:  a subtree containing XML Schema informations
8279  *
8280  * Parses a XML Schema identity-contraint definition.
8281  *
8282  * Returns the parsed identity-constraint definition.
8283  */
8284 static xmlSchemaIDCPtr
xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlSchemaTypeType idcCategory,const xmlChar * targetNamespace)8285 xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
8286 		  xmlSchemaPtr schema,
8287 		  xmlNodePtr node,
8288 		  xmlSchemaTypeType idcCategory,
8289 		  const xmlChar *targetNamespace)
8290 {
8291     xmlSchemaIDCPtr item = NULL;
8292     xmlNodePtr child = NULL;
8293     xmlAttrPtr attr;
8294     const xmlChar *name = NULL;
8295     xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
8296 
8297     /*
8298     * Check for illegal attributes.
8299     */
8300     attr = node->properties;
8301     while (attr != NULL) {
8302 	if (attr->ns == NULL) {
8303 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8304 		(!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8305 		((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
8306 		 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
8307 		xmlSchemaPIllegalAttrErr(ctxt,
8308 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8309 	    }
8310 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8311 	    xmlSchemaPIllegalAttrErr(ctxt,
8312 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8313 	}
8314 	attr = attr->next;
8315     }
8316     /*
8317     * Attribute "name" (mandatory).
8318     */
8319     attr = xmlSchemaGetPropNode(node, "name");
8320     if (attr == NULL) {
8321 	xmlSchemaPMissingAttrErr(ctxt,
8322 	    XML_SCHEMAP_S4S_ATTR_MISSING,
8323 	    NULL, node,
8324 	    "name", NULL);
8325 	return (NULL);
8326     } else if (xmlSchemaPValAttrNode(ctxt,
8327 	NULL, attr,
8328 	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8329 	return (NULL);
8330     }
8331     /* Create the component. */
8332     item = xmlSchemaAddIDC(ctxt, schema, name, targetNamespace,
8333 	idcCategory, node);
8334     if (item == NULL)
8335 	return(NULL);
8336 
8337     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8338     if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
8339 	/*
8340 	* Attribute "refer" (mandatory).
8341 	*/
8342 	attr = xmlSchemaGetPropNode(node, "refer");
8343 	if (attr == NULL) {
8344 	    xmlSchemaPMissingAttrErr(ctxt,
8345 		XML_SCHEMAP_S4S_ATTR_MISSING,
8346 		NULL, node,
8347 		"refer", NULL);
8348 	} else {
8349 	    /*
8350 	    * Create a reference item.
8351 	    */
8352 	    item->ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_IDC_KEY,
8353 		NULL, NULL);
8354 	    if (item->ref == NULL)
8355 		return (NULL);
8356 	    xmlSchemaPValAttrNodeQName(ctxt, schema,
8357 		NULL, attr,
8358 		&(item->ref->targetNamespace),
8359 		&(item->ref->name));
8360 	    xmlSchemaCheckReference(ctxt, schema, node, attr,
8361 		item->ref->targetNamespace);
8362 	}
8363     }
8364     /*
8365     * And now for the children...
8366     */
8367     child = node->children;
8368     if (IS_SCHEMA(child, "annotation")) {
8369 	item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
8370 	child = child->next;
8371     }
8372     if (child == NULL) {
8373 	xmlSchemaPContentErr(ctxt,
8374 		XML_SCHEMAP_S4S_ELEM_MISSING,
8375 		NULL, node, child,
8376 		"A child element is missing",
8377 		"(annotation?, (selector, field+))");
8378     }
8379     /*
8380     * Child element <selector>.
8381     */
8382     if (IS_SCHEMA(child, "selector")) {
8383 	item->selector = xmlSchemaParseIDCSelectorAndField(ctxt,
8384 	    item, child, 0);
8385 	child = child->next;
8386 	/*
8387 	* Child elements <field>.
8388 	*/
8389 	if (IS_SCHEMA(child, "field")) {
8390 	    do {
8391 		field = xmlSchemaParseIDCSelectorAndField(ctxt,
8392 		    item, child, 1);
8393 		if (field != NULL) {
8394 		    field->index = item->nbFields;
8395 		    item->nbFields++;
8396 		    if (lastField != NULL)
8397 			lastField->next = field;
8398 		    else
8399 			item->fields = field;
8400 		    lastField = field;
8401 		}
8402 		child = child->next;
8403 	    } while (IS_SCHEMA(child, "field"));
8404 	} else {
8405 	    xmlSchemaPContentErr(ctxt,
8406 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8407 		NULL, node, child,
8408 		NULL, "(annotation?, (selector, field+))");
8409 	}
8410     }
8411     if (child != NULL) {
8412 	xmlSchemaPContentErr(ctxt,
8413 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8414 	    NULL, node, child,
8415 	    NULL, "(annotation?, (selector, field+))");
8416     }
8417 
8418     return (item);
8419 }
8420 
8421 /**
8422  * xmlSchemaParseElement:
8423  * @ctxt:  a schema validation context
8424  * @schema:  the schema being built
8425  * @node:  a subtree containing XML Schema informations
8426  * @topLevel: indicates if this is global declaration
8427  *
8428  * Parses a XML schema element declaration.
8429  * *WARNING* this interface is highly subject to change
8430  *
8431  * Returns the element declaration or a particle; NULL in case
8432  * of an error or if the particle has minOccurs==maxOccurs==0.
8433  */
8434 static xmlSchemaBasicItemPtr
xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int * isElemRef,int topLevel)8435 xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8436                       xmlNodePtr node, int *isElemRef, int topLevel)
8437 {
8438     xmlSchemaElementPtr decl = NULL;
8439     xmlSchemaParticlePtr particle = NULL;
8440     xmlSchemaAnnotPtr annot = NULL;
8441     xmlNodePtr child = NULL;
8442     xmlAttrPtr attr, nameAttr;
8443     int min, max, isRef = 0;
8444     xmlChar *des = NULL;
8445 
8446     /* 3.3.3 Constraints on XML Representations of Element Declarations */
8447     /* TODO: Complete implementation of 3.3.6 */
8448 
8449     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8450         return (NULL);
8451 
8452     if (isElemRef != NULL)
8453 	*isElemRef = 0;
8454     /*
8455     * If we get a "ref" attribute on a local <element> we will assume it's
8456     * a reference - even if there's a "name" attribute; this seems to be more
8457     * robust.
8458     */
8459     nameAttr = xmlSchemaGetPropNode(node, "name");
8460     attr = xmlSchemaGetPropNode(node, "ref");
8461     if ((topLevel) || (attr == NULL)) {
8462 	if (nameAttr == NULL) {
8463 	    xmlSchemaPMissingAttrErr(ctxt,
8464 		XML_SCHEMAP_S4S_ATTR_MISSING,
8465 		NULL, node, "name", NULL);
8466 	    return (NULL);
8467 	}
8468     } else
8469 	isRef = 1;
8470 
8471     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8472     child = node->children;
8473     if (IS_SCHEMA(child, "annotation")) {
8474 	annot = xmlSchemaParseAnnotation(ctxt, child, 1);
8475 	child = child->next;
8476     }
8477     /*
8478     * Skip particle part if a global declaration.
8479     */
8480     if (topLevel)
8481 	goto declaration_part;
8482     /*
8483     * The particle part ==================================================
8484     */
8485     min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
8486     max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
8487     xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
8488     particle = xmlSchemaAddParticle(ctxt, node, min, max);
8489     if (particle == NULL)
8490 	goto return_null;
8491 
8492     /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
8493 
8494     if (isRef) {
8495 	const xmlChar *refNs = NULL, *ref = NULL;
8496 	xmlSchemaQNameRefPtr refer = NULL;
8497 	/*
8498 	* The reference part =============================================
8499 	*/
8500 	if (isElemRef != NULL)
8501 	    *isElemRef = 1;
8502 
8503 	xmlSchemaPValAttrNodeQName(ctxt, schema,
8504 	    NULL, attr, &refNs, &ref);
8505 	xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
8506 	/*
8507 	* SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
8508 	*/
8509 	if (nameAttr != NULL) {
8510 	    xmlSchemaPMutualExclAttrErr(ctxt,
8511 		XML_SCHEMAP_SRC_ELEMENT_2_1, NULL, nameAttr, "ref", "name");
8512 	}
8513 	/*
8514 	* Check for illegal attributes.
8515 	*/
8516 	attr = node->properties;
8517 	while (attr != NULL) {
8518 	    if (attr->ns == NULL) {
8519 		if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
8520 		    xmlStrEqual(attr->name, BAD_CAST "name") ||
8521 		    xmlStrEqual(attr->name, BAD_CAST "id") ||
8522 		    xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
8523 		    xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
8524 		{
8525 		    attr = attr->next;
8526 		    continue;
8527 		} else {
8528 		    /* SPEC (3.3.3 : 2.2) */
8529 		    xmlSchemaPCustomAttrErr(ctxt,
8530 			XML_SCHEMAP_SRC_ELEMENT_2_2,
8531 			NULL, NULL, attr,
8532 			"Only the attributes 'minOccurs', 'maxOccurs' and "
8533 			"'id' are allowed in addition to 'ref'");
8534 		    break;
8535 		}
8536 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8537 		xmlSchemaPIllegalAttrErr(ctxt,
8538 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8539 	    }
8540 	    attr = attr->next;
8541 	}
8542 	/*
8543 	* No children except <annotation> expected.
8544 	*/
8545 	if (child != NULL) {
8546 	    xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8547 		NULL, node, child, NULL, "(annotation?)");
8548 	}
8549 	if ((min == 0) && (max == 0))
8550 	    goto return_null;
8551 	/*
8552 	* Create the reference item and attach it to the particle.
8553 	*/
8554 	refer = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_ELEMENT,
8555 	    ref, refNs);
8556 	if (refer == NULL)
8557 	    goto return_null;
8558 	particle->children = (xmlSchemaTreeItemPtr) refer;
8559 	particle->annot = annot;
8560 	/*
8561 	* Add the particle to pending components, since the reference
8562 	* need to be resolved.
8563 	*/
8564 	WXS_ADD_PENDING(ctxt, particle);
8565 	return ((xmlSchemaBasicItemPtr) particle);
8566     }
8567     /*
8568     * The declaration part ===============================================
8569     */
8570 declaration_part:
8571     {
8572 	const xmlChar *ns = NULL, *fixed, *name, *attrValue;
8573 	xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
8574 
8575 	if (xmlSchemaPValAttrNode(ctxt, NULL, nameAttr,
8576 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
8577 	    goto return_null;
8578 	/*
8579 	* Evaluate the target namespace.
8580 	*/
8581 	if (topLevel) {
8582 	    ns = ctxt->targetNamespace;
8583 	} else {
8584 	    attr = xmlSchemaGetPropNode(node, "form");
8585 	    if (attr != NULL) {
8586 		attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8587 		if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
8588 		    ns = ctxt->targetNamespace;
8589 		} else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
8590 		    xmlSchemaPSimpleTypeErr(ctxt,
8591 			XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8592 			NULL, (xmlNodePtr) attr,
8593 			NULL, "(qualified | unqualified)",
8594 			attrValue, NULL, NULL, NULL);
8595 		}
8596 	    } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
8597 		ns = ctxt->targetNamespace;
8598 	}
8599 	decl = xmlSchemaAddElement(ctxt, name, ns, node, topLevel);
8600 	if (decl == NULL) {
8601 	    goto return_null;
8602 	}
8603 	/*
8604 	* Check for illegal attributes.
8605 	*/
8606 	attr = node->properties;
8607 	while (attr != NULL) {
8608 	    if (attr->ns == NULL) {
8609 		if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8610 		    (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
8611 		    (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8612 		    (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
8613 		    (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
8614 		    (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
8615 		    (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
8616 		{
8617 		    if (topLevel == 0) {
8618 			if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8619 			    (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
8620 			    (!xmlStrEqual(attr->name, BAD_CAST "form")))
8621 			{
8622 			    xmlSchemaPIllegalAttrErr(ctxt,
8623 				XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8624 			}
8625 		    } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
8626 			(!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
8627 			(!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
8628 
8629 			xmlSchemaPIllegalAttrErr(ctxt,
8630 			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8631 		    }
8632 		}
8633 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8634 
8635 		xmlSchemaPIllegalAttrErr(ctxt,
8636 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8637 	    }
8638 	    attr = attr->next;
8639 	}
8640 	/*
8641 	* Extract/validate attributes.
8642 	*/
8643 	if (topLevel) {
8644 	    /*
8645 	    * Process top attributes of global element declarations here.
8646 	    */
8647 	    decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
8648 	    decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
8649 	    xmlSchemaPValAttrQName(ctxt, schema,
8650 		NULL, node, "substitutionGroup",
8651 		&(decl->substGroupNs), &(decl->substGroup));
8652 	    if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
8653 		decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
8654 	    /*
8655 	    * Attribute "final".
8656 	    */
8657 	    attr = xmlSchemaGetPropNode(node, "final");
8658 	    if (attr == NULL) {
8659 		if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8660 		    decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
8661 		if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8662 		    decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
8663 	    } else {
8664 		attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8665 		if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
8666 		    -1,
8667 		    XML_SCHEMAS_ELEM_FINAL_EXTENSION,
8668 		    XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
8669 		    xmlSchemaPSimpleTypeErr(ctxt,
8670 			XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8671 			NULL, (xmlNodePtr) attr,
8672 			NULL, "(#all | List of (extension | restriction))",
8673 			attrValue, NULL, NULL, NULL);
8674 		}
8675 	    }
8676 	}
8677 	/*
8678 	* Attribute "block".
8679 	*/
8680 	attr = xmlSchemaGetPropNode(node, "block");
8681 	if (attr == NULL) {
8682 	    /*
8683 	    * Apply default "block" values.
8684 	    */
8685 	    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8686 		decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
8687 	    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8688 		decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
8689 	    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8690 		decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
8691 	} else {
8692 	    attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8693 	    if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
8694 		-1,
8695 		XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
8696 		XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
8697 		XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
8698 		xmlSchemaPSimpleTypeErr(ctxt,
8699 		    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8700 		    NULL, (xmlNodePtr) attr,
8701 		    NULL, "(#all | List of (extension | "
8702 		    "restriction | substitution))", attrValue,
8703 		    NULL, NULL, NULL);
8704 	    }
8705 	}
8706 	if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
8707 	    decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
8708 
8709 	attr = xmlSchemaGetPropNode(node, "type");
8710 	if (attr != NULL) {
8711 	    xmlSchemaPValAttrNodeQName(ctxt, schema,
8712 		NULL, attr,
8713 		&(decl->namedTypeNs), &(decl->namedType));
8714 	    xmlSchemaCheckReference(ctxt, schema, node,
8715 		attr, decl->namedTypeNs);
8716 	}
8717 	decl->value = xmlSchemaGetProp(ctxt, node, "default");
8718 	attr = xmlSchemaGetPropNode(node, "fixed");
8719 	if (attr != NULL) {
8720 	    fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8721 	    if (decl->value != NULL) {
8722 		/*
8723 		* 3.3.3 : 1
8724 		* default and fixed must not both be present.
8725 		*/
8726 		xmlSchemaPMutualExclAttrErr(ctxt,
8727 		    XML_SCHEMAP_SRC_ELEMENT_1,
8728 		    NULL, attr, "default", "fixed");
8729 	    } else {
8730 		decl->flags |= XML_SCHEMAS_ELEM_FIXED;
8731 		decl->value = fixed;
8732 	    }
8733 	}
8734 	/*
8735 	* And now for the children...
8736 	*/
8737 	if (IS_SCHEMA(child, "complexType")) {
8738 	    /*
8739 	    * 3.3.3 : 3
8740 	    * "type" and either <simpleType> or <complexType> are mutually
8741 	    * exclusive
8742 	    */
8743 	    if (decl->namedType != NULL) {
8744 		xmlSchemaPContentErr(ctxt,
8745 		    XML_SCHEMAP_SRC_ELEMENT_3,
8746 		    NULL, node, child,
8747 		    "The attribute 'type' and the <complexType> child are "
8748 		    "mutually exclusive", NULL);
8749 	    } else
8750 		WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
8751 	    child = child->next;
8752 	} else if (IS_SCHEMA(child, "simpleType")) {
8753 	    /*
8754 	    * 3.3.3 : 3
8755 	    * "type" and either <simpleType> or <complexType> are
8756 	    * mutually exclusive
8757 	    */
8758 	    if (decl->namedType != NULL) {
8759 		xmlSchemaPContentErr(ctxt,
8760 		    XML_SCHEMAP_SRC_ELEMENT_3,
8761 		    NULL, node, child,
8762 		    "The attribute 'type' and the <simpleType> child are "
8763 		    "mutually exclusive", NULL);
8764 	    } else
8765 		WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8766 	    child = child->next;
8767 	}
8768 	while ((IS_SCHEMA(child, "unique")) ||
8769 	    (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
8770 	    if (IS_SCHEMA(child, "unique")) {
8771 		curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8772 		    XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
8773 	    } else if (IS_SCHEMA(child, "key")) {
8774 		curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8775 		    XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
8776 	    } else if (IS_SCHEMA(child, "keyref")) {
8777 		curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8778 		    XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
8779 	    }
8780 	    if (lastIDC != NULL)
8781 		lastIDC->next = curIDC;
8782 	    else
8783 		decl->idcs = (void *) curIDC;
8784 	    lastIDC = curIDC;
8785 	    child = child->next;
8786 	}
8787 	if (child != NULL) {
8788 	    xmlSchemaPContentErr(ctxt,
8789 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8790 		NULL, node, child,
8791 		NULL, "(annotation?, ((simpleType | complexType)?, "
8792 		"(unique | key | keyref)*))");
8793 	}
8794 	decl->annot = annot;
8795     }
8796     /*
8797     * NOTE: Element Declaration Representation OK 4. will be checked at a
8798     * different layer.
8799     */
8800     FREE_AND_NULL(des)
8801     if (topLevel)
8802 	return ((xmlSchemaBasicItemPtr) decl);
8803     else {
8804 	particle->children = (xmlSchemaTreeItemPtr) decl;
8805 	return ((xmlSchemaBasicItemPtr) particle);
8806     }
8807 
8808 return_null:
8809     FREE_AND_NULL(des);
8810     if (annot != NULL) {
8811 	if (particle != NULL)
8812 	    particle->annot = NULL;
8813 	if (decl != NULL)
8814 	    decl->annot = NULL;
8815 	xmlSchemaFreeAnnot(annot);
8816     }
8817     return (NULL);
8818 }
8819 
8820 /**
8821  * xmlSchemaParseUnion:
8822  * @ctxt:  a schema validation context
8823  * @schema:  the schema being built
8824  * @node:  a subtree containing XML Schema informations
8825  *
8826  * parse a XML schema Union definition
8827  * *WARNING* this interface is highly subject to change
8828  *
8829  * Returns -1 in case of internal error, 0 in case of success and a positive
8830  * error code otherwise.
8831  */
8832 static int
xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)8833 xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8834                     xmlNodePtr node)
8835 {
8836     xmlSchemaTypePtr type;
8837     xmlNodePtr child = NULL;
8838     xmlAttrPtr attr;
8839     const xmlChar *cur = NULL;
8840 
8841     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8842         return (-1);
8843     /* Not a component, don't create it. */
8844     type = ctxt->ctxtType;
8845     /*
8846     * Mark the simple type as being of variety "union".
8847     */
8848     type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
8849     /*
8850     * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
8851     * then the �simple ur-type definition�."
8852     */
8853     type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
8854     /*
8855     * Check for illegal attributes.
8856     */
8857     attr = node->properties;
8858     while (attr != NULL) {
8859 	if (attr->ns == NULL) {
8860 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8861 		(!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
8862 		xmlSchemaPIllegalAttrErr(ctxt,
8863 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8864 	    }
8865 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8866 	    xmlSchemaPIllegalAttrErr(ctxt,
8867 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8868 	}
8869 	attr = attr->next;
8870     }
8871     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8872     /*
8873     * Attribute "memberTypes". This is a list of QNames.
8874     * TODO: Check the value to contain anything.
8875     */
8876     attr = xmlSchemaGetPropNode(node, "memberTypes");
8877     if (attr != NULL) {
8878 	const xmlChar *end;
8879 	xmlChar *tmp;
8880 	const xmlChar *localName, *nsName;
8881 	xmlSchemaTypeLinkPtr link, lastLink = NULL;
8882 	xmlSchemaQNameRefPtr ref;
8883 
8884 	cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8885 	type->base = cur;
8886 	do {
8887 	    while (IS_BLANK_CH(*cur))
8888 		cur++;
8889 	    end = cur;
8890 	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
8891 		end++;
8892 	    if (end == cur)
8893 		break;
8894 	    tmp = xmlStrndup(cur, end - cur);
8895 	    if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
8896 		NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
8897 		/*
8898 		* Create the member type link.
8899 		*/
8900 		link = (xmlSchemaTypeLinkPtr)
8901 		    xmlMalloc(sizeof(xmlSchemaTypeLink));
8902 		if (link == NULL) {
8903 		    xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
8904 			"allocating a type link", NULL);
8905 		    return (-1);
8906 		}
8907 		link->type = NULL;
8908 		link->next = NULL;
8909 		if (lastLink == NULL)
8910 		    type->memberTypes = link;
8911 		else
8912 		    lastLink->next = link;
8913 		lastLink = link;
8914 		/*
8915 		* Create a reference item.
8916 		*/
8917 		ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_SIMPLE,
8918 		    localName, nsName);
8919 		if (ref == NULL) {
8920 		    FREE_AND_NULL(tmp)
8921 		    return (-1);
8922 		}
8923 		/*
8924 		* Assign the reference to the link, it will be resolved
8925 		* later during fixup of the union simple type.
8926 		*/
8927 		link->type = (xmlSchemaTypePtr) ref;
8928 	    }
8929 	    FREE_AND_NULL(tmp)
8930 	    cur = end;
8931 	} while (*cur != 0);
8932 
8933     }
8934     /*
8935     * And now for the children...
8936     */
8937     child = node->children;
8938     if (IS_SCHEMA(child, "annotation")) {
8939 	/*
8940 	* Add the annotation to the simple type ancestor.
8941 	*/
8942 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
8943 	    xmlSchemaParseAnnotation(ctxt, child, 1));
8944         child = child->next;
8945     }
8946     if (IS_SCHEMA(child, "simpleType")) {
8947 	xmlSchemaTypePtr subtype, last = NULL;
8948 
8949 	/*
8950 	* Anchor the member types in the "subtypes" field of the
8951 	* simple type.
8952 	*/
8953 	while (IS_SCHEMA(child, "simpleType")) {
8954 	    subtype = (xmlSchemaTypePtr)
8955 		xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8956 	    if (subtype != NULL) {
8957 		if (last == NULL) {
8958 		    type->subtypes = subtype;
8959 		    last = subtype;
8960 		} else {
8961 		    last->next = subtype;
8962 		    last = subtype;
8963 		}
8964 		last->next = NULL;
8965 	    }
8966 	    child = child->next;
8967 	}
8968     }
8969     if (child != NULL) {
8970 	xmlSchemaPContentErr(ctxt,
8971 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8972 	    NULL, node, child, NULL, "(annotation?, simpleType*)");
8973     }
8974     if ((attr == NULL) && (type->subtypes == NULL)) {
8975 	 /*
8976 	* src-union-memberTypes-or-simpleTypes
8977 	* Either the memberTypes [attribute] of the <union> element must
8978 	* be non-empty or there must be at least one simpleType [child].
8979 	*/
8980 	xmlSchemaPCustomErr(ctxt,
8981 	    XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
8982 	    NULL, node,
8983 	    "Either the attribute 'memberTypes' or "
8984 	    "at least one <simpleType> child must be present", NULL);
8985     }
8986     return (0);
8987 }
8988 
8989 /**
8990  * xmlSchemaParseList:
8991  * @ctxt:  a schema validation context
8992  * @schema:  the schema being built
8993  * @node:  a subtree containing XML Schema informations
8994  *
8995  * parse a XML schema List definition
8996  * *WARNING* this interface is highly subject to change
8997  *
8998  * Returns -1 in case of error, 0 if the declaration is improper and
8999  *         1 in case of success.
9000  */
9001 static xmlSchemaTypePtr
xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)9002 xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9003                    xmlNodePtr node)
9004 {
9005     xmlSchemaTypePtr type;
9006     xmlNodePtr child = NULL;
9007     xmlAttrPtr attr;
9008 
9009     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9010         return (NULL);
9011     /* Not a component, don't create it. */
9012     type = ctxt->ctxtType;
9013     /*
9014     * Mark the type as being of variety "list".
9015     */
9016     type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
9017     /*
9018     * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
9019     * then the �simple ur-type definition�."
9020     */
9021     type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
9022     /*
9023     * Check for illegal attributes.
9024     */
9025     attr = node->properties;
9026     while (attr != NULL) {
9027 	if (attr->ns == NULL) {
9028 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9029 		(!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
9030 		xmlSchemaPIllegalAttrErr(ctxt,
9031 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9032 	    }
9033 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9034 	    xmlSchemaPIllegalAttrErr(ctxt,
9035 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9036 	}
9037 	attr = attr->next;
9038     }
9039 
9040     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9041 
9042     /*
9043     * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
9044     * fields for holding the reference to the itemType.
9045     *
9046     * REVAMP TODO: Use the "base" and "baseNs" fields, since we will remove
9047     * the "ref" fields.
9048     */
9049     xmlSchemaPValAttrQName(ctxt, schema, NULL,
9050 	node, "itemType", &(type->baseNs), &(type->base));
9051     /*
9052     * And now for the children...
9053     */
9054     child = node->children;
9055     if (IS_SCHEMA(child, "annotation")) {
9056 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9057 	    xmlSchemaParseAnnotation(ctxt, child, 1));
9058         child = child->next;
9059     }
9060     if (IS_SCHEMA(child, "simpleType")) {
9061 	/*
9062 	* src-list-itemType-or-simpleType
9063 	* Either the itemType [attribute] or the <simpleType> [child] of
9064 	* the <list> element must be present, but not both.
9065 	*/
9066 	if (type->base != NULL) {
9067 	    xmlSchemaPCustomErr(ctxt,
9068 		XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9069 		NULL, node,
9070 		"The attribute 'itemType' and the <simpleType> child "
9071 		"are mutually exclusive", NULL);
9072 	} else {
9073 	    type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
9074 	}
9075         child = child->next;
9076     } else if (type->base == NULL) {
9077 	xmlSchemaPCustomErr(ctxt,
9078 	    XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9079 	    NULL, node,
9080 	    "Either the attribute 'itemType' or the <simpleType> child "
9081 	    "must be present", NULL);
9082     }
9083     if (child != NULL) {
9084 	xmlSchemaPContentErr(ctxt,
9085 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9086 	    NULL, node, child, NULL, "(annotation?, simpleType?)");
9087     }
9088     if ((type->base == NULL) &&
9089 	(type->subtypes == NULL) &&
9090 	(xmlSchemaGetPropNode(node, "itemType") == NULL)) {
9091 	xmlSchemaPCustomErr(ctxt,
9092 	    XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9093 	    NULL, node,
9094 	    "Either the attribute 'itemType' or the <simpleType> child "
9095 	    "must be present", NULL);
9096     }
9097     return (NULL);
9098 }
9099 
9100 /**
9101  * xmlSchemaParseSimpleType:
9102  * @ctxt:  a schema validation context
9103  * @schema:  the schema being built
9104  * @node:  a subtree containing XML Schema informations
9105  *
9106  * parse a XML schema Simple Type definition
9107  * *WARNING* this interface is highly subject to change
9108  *
9109  * Returns -1 in case of error, 0 if the declaration is improper and
9110  * 1 in case of success.
9111  */
9112 static xmlSchemaTypePtr
xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int topLevel)9113 xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9114                          xmlNodePtr node, int topLevel)
9115 {
9116     xmlSchemaTypePtr type, oldCtxtType;
9117     xmlNodePtr child = NULL;
9118     const xmlChar *attrValue = NULL;
9119     xmlAttrPtr attr;
9120     int hasRestriction = 0;
9121 
9122     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9123         return (NULL);
9124 
9125     if (topLevel) {
9126 	attr = xmlSchemaGetPropNode(node, "name");
9127 	if (attr == NULL) {
9128 	    xmlSchemaPMissingAttrErr(ctxt,
9129 		XML_SCHEMAP_S4S_ATTR_MISSING,
9130 		NULL, node,
9131 		"name", NULL);
9132 	    return (NULL);
9133 	} else {
9134 	    if (xmlSchemaPValAttrNode(ctxt,
9135 		NULL, attr,
9136 		xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
9137 		return (NULL);
9138 	    /*
9139 	    * Skip built-in types.
9140 	    */
9141 	    if (ctxt->isS4S) {
9142 		xmlSchemaTypePtr biType;
9143 
9144 		if (ctxt->isRedefine) {
9145 		    /*
9146 		    * REDEFINE: Disallow redefinition of built-in-types.
9147 		    * TODO: It seems that the spec does not say anything
9148 		    * about this case.
9149 		    */
9150 		    xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
9151 			NULL, node,
9152 			"Redefinition of built-in simple types is not "
9153 			"supported", NULL);
9154 		    return(NULL);
9155 		}
9156 		biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
9157 		if (biType != NULL)
9158 		    return (biType);
9159 	    }
9160 	}
9161     }
9162     /*
9163     * TargetNamespace:
9164     * SPEC "The �actual value� of the targetNamespace [attribute]
9165     * of the <schema> ancestor element information item if present,
9166     * otherwise �absent�.
9167     */
9168     if (topLevel == 0) {
9169 #ifdef ENABLE_NAMED_LOCALS
9170         char buf[40];
9171 #endif
9172 	/*
9173 	* Parse as local simple type definition.
9174 	*/
9175 #ifdef ENABLE_NAMED_LOCALS
9176         snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
9177 	type = xmlSchemaAddType(ctxt, schema,
9178 	    XML_SCHEMA_TYPE_SIMPLE,
9179 	    xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
9180 	    ctxt->targetNamespace, node, 0);
9181 #else
9182 	type = xmlSchemaAddType(ctxt, schema,
9183 	    XML_SCHEMA_TYPE_SIMPLE,
9184 	    NULL, ctxt->targetNamespace, node, 0);
9185 #endif
9186 	if (type == NULL)
9187 	    return (NULL);
9188 	type->type = XML_SCHEMA_TYPE_SIMPLE;
9189 	type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
9190 	/*
9191 	* Check for illegal attributes.
9192 	*/
9193 	attr = node->properties;
9194 	while (attr != NULL) {
9195 	    if (attr->ns == NULL) {
9196 		if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
9197 		    xmlSchemaPIllegalAttrErr(ctxt,
9198 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9199 		}
9200 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9201 		    xmlSchemaPIllegalAttrErr(ctxt,
9202 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9203 	    }
9204 	    attr = attr->next;
9205 	}
9206     } else {
9207 	/*
9208 	* Parse as global simple type definition.
9209 	*
9210 	* Note that attrValue is the value of the attribute "name" here.
9211 	*/
9212 	type = xmlSchemaAddType(ctxt, schema, XML_SCHEMA_TYPE_SIMPLE,
9213 	    attrValue, ctxt->targetNamespace, node, 1);
9214 	if (type == NULL)
9215 	    return (NULL);
9216 	type->type = XML_SCHEMA_TYPE_SIMPLE;
9217 	type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
9218 	type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
9219 	/*
9220 	* Check for illegal attributes.
9221 	*/
9222 	attr = node->properties;
9223 	while (attr != NULL) {
9224 	    if (attr->ns == NULL) {
9225 		if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9226 		    (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
9227 		    (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
9228 		    xmlSchemaPIllegalAttrErr(ctxt,
9229 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9230 		}
9231 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9232 		xmlSchemaPIllegalAttrErr(ctxt,
9233 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9234 	    }
9235 	    attr = attr->next;
9236 	}
9237 	/*
9238 	* Attribute "final".
9239 	*/
9240 	attr = xmlSchemaGetPropNode(node, "final");
9241 	if (attr == NULL) {
9242 	    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9243 		type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
9244 	    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9245 		type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
9246 	    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9247 		type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
9248 	} else {
9249 	    attrValue = xmlSchemaGetProp(ctxt, node, "final");
9250 	    if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
9251 		-1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
9252 		XML_SCHEMAS_TYPE_FINAL_LIST,
9253 		XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
9254 
9255 		xmlSchemaPSimpleTypeErr(ctxt,
9256 		    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9257 		    WXS_BASIC_CAST type, (xmlNodePtr) attr,
9258 		    NULL, "(#all | List of (list | union | restriction)",
9259 		    attrValue, NULL, NULL, NULL);
9260 	    }
9261 	}
9262     }
9263     type->targetNamespace = ctxt->targetNamespace;
9264     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9265     /*
9266     * And now for the children...
9267     */
9268     oldCtxtType = ctxt->ctxtType;
9269 
9270     ctxt->ctxtType = type;
9271 
9272     child = node->children;
9273     if (IS_SCHEMA(child, "annotation")) {
9274         type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9275         child = child->next;
9276     }
9277     if (child == NULL) {
9278 	xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
9279 	    NULL, node, child, NULL,
9280 	    "(annotation?, (restriction | list | union))");
9281     } else if (IS_SCHEMA(child, "restriction")) {
9282         xmlSchemaParseRestriction(ctxt, schema, child,
9283 	    XML_SCHEMA_TYPE_SIMPLE);
9284 	hasRestriction = 1;
9285         child = child->next;
9286     } else if (IS_SCHEMA(child, "list")) {
9287         xmlSchemaParseList(ctxt, schema, child);
9288         child = child->next;
9289     } else if (IS_SCHEMA(child, "union")) {
9290         xmlSchemaParseUnion(ctxt, schema, child);
9291         child = child->next;
9292     }
9293     if (child != NULL) {
9294 	xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9295 	    NULL, node, child, NULL,
9296 	    "(annotation?, (restriction | list | union))");
9297     }
9298     /*
9299     * REDEFINE: SPEC src-redefine (5)
9300     * "Within the [children], each <simpleType> must have a
9301     * <restriction> among its [children] ... the �actual value� of whose
9302     * base [attribute] must be the same as the �actual value� of its own
9303     * name attribute plus target namespace;"
9304     */
9305     if (topLevel && ctxt->isRedefine && (! hasRestriction)) {
9306 	xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
9307 	    NULL, node, "This is a redefinition, thus the "
9308 	    "<simpleType> must have a <restriction> child", NULL);
9309     }
9310 
9311     ctxt->ctxtType = oldCtxtType;
9312     return (type);
9313 }
9314 
9315 /**
9316  * xmlSchemaParseModelGroupDefRef:
9317  * @ctxt:  the parser context
9318  * @schema: the schema being built
9319  * @node:  the node
9320  *
9321  * Parses a reference to a model group definition.
9322  *
9323  * We will return a particle component with a qname-component or
9324  * NULL in case of an error.
9325  */
9326 static xmlSchemaTreeItemPtr
xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)9327 xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
9328 			       xmlSchemaPtr schema,
9329 			       xmlNodePtr node)
9330 {
9331     xmlSchemaParticlePtr item;
9332     xmlNodePtr child = NULL;
9333     xmlAttrPtr attr;
9334     const xmlChar *ref = NULL, *refNs = NULL;
9335     int min, max;
9336 
9337     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9338         return (NULL);
9339 
9340     attr = xmlSchemaGetPropNode(node, "ref");
9341     if (attr == NULL) {
9342 	xmlSchemaPMissingAttrErr(ctxt,
9343 	    XML_SCHEMAP_S4S_ATTR_MISSING,
9344 	    NULL, node, "ref", NULL);
9345 	return (NULL);
9346     } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL,
9347 	attr, &refNs, &ref) != 0) {
9348 	return (NULL);
9349     }
9350     xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
9351     min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
9352     max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
9353 	"(xs:nonNegativeInteger | unbounded)");
9354     /*
9355     * Check for illegal attributes.
9356     */
9357     attr = node->properties;
9358     while (attr != NULL) {
9359 	if (attr->ns == NULL) {
9360 	    if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
9361 		(!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9362 		(!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
9363 		(!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
9364 		xmlSchemaPIllegalAttrErr(ctxt,
9365 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9366 	    }
9367 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9368 	    xmlSchemaPIllegalAttrErr(ctxt,
9369 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9370 	}
9371 	attr = attr->next;
9372     }
9373     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9374     item = xmlSchemaAddParticle(ctxt, node, min, max);
9375     if (item == NULL)
9376 	return (NULL);
9377     /*
9378     * Create a qname-reference and set as the term; it will be substituted
9379     * for the model group after the reference has been resolved.
9380     */
9381     item->children = (xmlSchemaTreeItemPtr)
9382 	xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_GROUP, ref, refNs);
9383     xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
9384     /*
9385     * And now for the children...
9386     */
9387     child = node->children;
9388     /* TODO: Is annotation even allowed for a model group reference? */
9389     if (IS_SCHEMA(child, "annotation")) {
9390 	/*
9391 	* TODO: What to do exactly with the annotation?
9392 	*/
9393 	item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9394 	child = child->next;
9395     }
9396     if (child != NULL) {
9397 	xmlSchemaPContentErr(ctxt,
9398 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9399 	    NULL, node, child, NULL,
9400 	    "(annotation?)");
9401     }
9402     /*
9403     * Corresponds to no component at all if minOccurs==maxOccurs==0.
9404     */
9405     if ((min == 0) && (max == 0))
9406 	return (NULL);
9407 
9408     return ((xmlSchemaTreeItemPtr) item);
9409 }
9410 
9411 /**
9412  * xmlSchemaParseModelGroupDefinition:
9413  * @ctxt:  a schema validation context
9414  * @schema:  the schema being built
9415  * @node:  a subtree containing XML Schema informations
9416  *
9417  * Parses a XML schema model group definition.
9418  *
9419  * Note that the contraint src-redefine (6.2) can't be applied until
9420  * references have been resolved. So we will do this at the
9421  * component fixup level.
9422  *
9423  * *WARNING* this interface is highly subject to change
9424  *
9425  * Returns -1 in case of error, 0 if the declaration is improper and
9426  *         1 in case of success.
9427  */
9428 static xmlSchemaModelGroupDefPtr
xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)9429 xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
9430 				   xmlSchemaPtr schema,
9431 				   xmlNodePtr node)
9432 {
9433     xmlSchemaModelGroupDefPtr item;
9434     xmlNodePtr child = NULL;
9435     xmlAttrPtr attr;
9436     const xmlChar *name;
9437 
9438     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9439         return (NULL);
9440 
9441     attr = xmlSchemaGetPropNode(node, "name");
9442     if (attr == NULL) {
9443 	xmlSchemaPMissingAttrErr(ctxt,
9444 	    XML_SCHEMAP_S4S_ATTR_MISSING,
9445 	    NULL, node,
9446 	    "name", NULL);
9447 	return (NULL);
9448     } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
9449 	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
9450 	return (NULL);
9451     }
9452     item = xmlSchemaAddModelGroupDefinition(ctxt, schema, name,
9453 	ctxt->targetNamespace, node);
9454     if (item == NULL)
9455 	return (NULL);
9456     /*
9457     * Check for illegal attributes.
9458     */
9459     attr = node->properties;
9460     while (attr != NULL) {
9461 	if (attr->ns == NULL) {
9462 	    if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
9463 		(!xmlStrEqual(attr->name, BAD_CAST "id"))) {
9464 		xmlSchemaPIllegalAttrErr(ctxt,
9465 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9466 	    }
9467 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9468 	    xmlSchemaPIllegalAttrErr(ctxt,
9469 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9470 	}
9471 	attr = attr->next;
9472     }
9473     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9474     /*
9475     * And now for the children...
9476     */
9477     child = node->children;
9478     if (IS_SCHEMA(child, "annotation")) {
9479 	item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9480 	child = child->next;
9481     }
9482     if (IS_SCHEMA(child, "all")) {
9483 	item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9484 	    XML_SCHEMA_TYPE_ALL, 0);
9485 	child = child->next;
9486     } else if (IS_SCHEMA(child, "choice")) {
9487 	item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9488 	    XML_SCHEMA_TYPE_CHOICE, 0);
9489 	child = child->next;
9490     } else if (IS_SCHEMA(child, "sequence")) {
9491 	item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9492 	    XML_SCHEMA_TYPE_SEQUENCE, 0);
9493 	child = child->next;
9494     }
9495 
9496 
9497 
9498     if (child != NULL) {
9499 	xmlSchemaPContentErr(ctxt,
9500 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9501 	    NULL, node, child, NULL,
9502 	    "(annotation?, (all | choice | sequence)?)");
9503     }
9504     return (item);
9505 }
9506 
9507 /**
9508  * xmlSchemaCleanupDoc:
9509  * @ctxt:  a schema validation context
9510  * @node:  the root of the document.
9511  *
9512  * removes unwanted nodes in a schemas document tree
9513  */
9514 static void
xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr root)9515 xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
9516 {
9517     xmlNodePtr delete, cur;
9518 
9519     if ((ctxt == NULL) || (root == NULL)) return;
9520 
9521     /*
9522      * Remove all the blank text nodes
9523      */
9524     delete = NULL;
9525     cur = root;
9526     while (cur != NULL) {
9527         if (delete != NULL) {
9528             xmlUnlinkNode(delete);
9529             xmlFreeNode(delete);
9530             delete = NULL;
9531         }
9532         if (cur->type == XML_TEXT_NODE) {
9533             if (IS_BLANK_NODE(cur)) {
9534                 if (xmlNodeGetSpacePreserve(cur) != 1) {
9535                     delete = cur;
9536                 }
9537             }
9538         } else if ((cur->type != XML_ELEMENT_NODE) &&
9539                    (cur->type != XML_CDATA_SECTION_NODE)) {
9540             delete = cur;
9541             goto skip_children;
9542         }
9543 
9544         /*
9545          * Skip to next node
9546          */
9547         if (cur->children != NULL) {
9548             if ((cur->children->type != XML_ENTITY_DECL) &&
9549                 (cur->children->type != XML_ENTITY_REF_NODE) &&
9550                 (cur->children->type != XML_ENTITY_NODE)) {
9551                 cur = cur->children;
9552                 continue;
9553             }
9554         }
9555       skip_children:
9556         if (cur->next != NULL) {
9557             cur = cur->next;
9558             continue;
9559         }
9560 
9561         do {
9562             cur = cur->parent;
9563             if (cur == NULL)
9564                 break;
9565             if (cur == root) {
9566                 cur = NULL;
9567                 break;
9568             }
9569             if (cur->next != NULL) {
9570                 cur = cur->next;
9571                 break;
9572             }
9573         } while (cur != NULL);
9574     }
9575     if (delete != NULL) {
9576         xmlUnlinkNode(delete);
9577         xmlFreeNode(delete);
9578         delete = NULL;
9579     }
9580 }
9581 
9582 
9583 static void
xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)9584 xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
9585 {
9586     if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
9587 	schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
9588 
9589     if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
9590 	schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
9591 
9592     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
9593 	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
9594     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9595 	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
9596     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9597 	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
9598     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9599 	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
9600 
9601     if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
9602 	schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
9603     if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
9604 	schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
9605     if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
9606 	schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
9607 }
9608 
9609 static int
xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)9610 xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt,
9611 			     xmlSchemaPtr schema,
9612 			     xmlNodePtr node)
9613 {
9614     xmlAttrPtr attr;
9615     const xmlChar *val;
9616     int res = 0, oldErrs = ctxt->nberrors;
9617 
9618     /*
9619     * Those flags should be moved to the parser context flags,
9620     * since they are not visible at the component level. I.e.
9621     * they are used if processing schema *documents* only.
9622     */
9623     res = xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9624     HFAILURE;
9625 
9626     /*
9627     * Since the version is of type xs:token, we won't bother to
9628     * check it.
9629     */
9630     /* REMOVED:
9631     attr = xmlSchemaGetPropNode(node, "version");
9632     if (attr != NULL) {
9633 	res = xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9634 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &val);
9635 	HFAILURE;
9636     }
9637     */
9638     attr = xmlSchemaGetPropNode(node, "targetNamespace");
9639     if (attr != NULL) {
9640 	res = xmlSchemaPValAttrNode(ctxt, NULL, attr,
9641 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
9642 	HFAILURE;
9643 	if (res != 0) {
9644 	    ctxt->stop = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
9645 	    goto exit;
9646 	}
9647     }
9648     attr = xmlSchemaGetPropNode(node, "elementFormDefault");
9649     if (attr != NULL) {
9650 	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9651 	res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9652 	    XML_SCHEMAS_QUALIF_ELEM);
9653 	HFAILURE;
9654 	if (res != 0) {
9655 	    xmlSchemaPSimpleTypeErr(ctxt,
9656 		XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
9657 		NULL, (xmlNodePtr) attr, NULL,
9658 		"(qualified | unqualified)", val, NULL, NULL, NULL);
9659 	}
9660     }
9661     attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
9662     if (attr != NULL) {
9663 	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9664 	res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9665 	    XML_SCHEMAS_QUALIF_ATTR);
9666 	HFAILURE;
9667 	if (res != 0) {
9668 	    xmlSchemaPSimpleTypeErr(ctxt,
9669 		XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
9670 		NULL, (xmlNodePtr) attr, NULL,
9671 		"(qualified | unqualified)", val, NULL, NULL, NULL);
9672 	}
9673     }
9674     attr = xmlSchemaGetPropNode(node, "finalDefault");
9675     if (attr != NULL) {
9676 	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9677 	res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
9678 	    XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
9679 	    XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
9680 	    -1,
9681 	    XML_SCHEMAS_FINAL_DEFAULT_LIST,
9682 	    XML_SCHEMAS_FINAL_DEFAULT_UNION);
9683 	HFAILURE;
9684 	if (res != 0) {
9685 	    xmlSchemaPSimpleTypeErr(ctxt,
9686 		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9687 		NULL, (xmlNodePtr) attr, NULL,
9688 		"(#all | List of (extension | restriction | list | union))",
9689 		val, NULL, NULL, NULL);
9690 	}
9691     }
9692     attr = xmlSchemaGetPropNode(node, "blockDefault");
9693     if (attr != NULL) {
9694 	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9695 	res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
9696 	    XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
9697 	    XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
9698 	    XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1);
9699 	HFAILURE;
9700 	if (res != 0) {
9701 	    xmlSchemaPSimpleTypeErr(ctxt,
9702 		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9703 		NULL, (xmlNodePtr) attr, NULL,
9704 		"(#all | List of (extension | restriction | substitution))",
9705 		val, NULL, NULL, NULL);
9706 	}
9707     }
9708 
9709 exit:
9710     if (oldErrs != ctxt->nberrors)
9711 	res = ctxt->err;
9712     return(res);
9713 exit_failure:
9714     return(-1);
9715 }
9716 
9717 /**
9718  * xmlSchemaParseSchemaTopLevel:
9719  * @ctxt:  a schema validation context
9720  * @schema:  the schemas
9721  * @nodes:  the list of top level nodes
9722  *
9723  * Returns the internal XML Schema structure built from the resource or
9724  *         NULL in case of error
9725  */
9726 static int
xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr nodes)9727 xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
9728                              xmlSchemaPtr schema, xmlNodePtr nodes)
9729 {
9730     xmlNodePtr child;
9731     xmlSchemaAnnotPtr annot;
9732     int res = 0, oldErrs, tmpOldErrs;
9733 
9734     if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
9735         return(-1);
9736 
9737     oldErrs = ctxt->nberrors;
9738     child = nodes;
9739     while ((IS_SCHEMA(child, "include")) ||
9740 	   (IS_SCHEMA(child, "import")) ||
9741 	   (IS_SCHEMA(child, "redefine")) ||
9742 	   (IS_SCHEMA(child, "annotation"))) {
9743 	if (IS_SCHEMA(child, "annotation")) {
9744 	    annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9745 	    if (schema->annot == NULL)
9746 		schema->annot = annot;
9747 	    else
9748 		xmlSchemaFreeAnnot(annot);
9749 	} else if (IS_SCHEMA(child, "import")) {
9750 	    tmpOldErrs = ctxt->nberrors;
9751 	    res = xmlSchemaParseImport(ctxt, schema, child);
9752 	    HFAILURE;
9753 	    HSTOP(ctxt);
9754 	    if (tmpOldErrs != ctxt->nberrors)
9755 		goto exit;
9756 	} else if (IS_SCHEMA(child, "include")) {
9757 	    tmpOldErrs = ctxt->nberrors;
9758 	    res = xmlSchemaParseInclude(ctxt, schema, child);
9759 	    HFAILURE;
9760 	    HSTOP(ctxt);
9761 	    if (tmpOldErrs != ctxt->nberrors)
9762 		goto exit;
9763 	} else if (IS_SCHEMA(child, "redefine")) {
9764 	    tmpOldErrs = ctxt->nberrors;
9765 	    res = xmlSchemaParseRedefine(ctxt, schema, child);
9766 	    HFAILURE;
9767 	    HSTOP(ctxt);
9768 	    if (tmpOldErrs != ctxt->nberrors)
9769 		goto exit;
9770 	}
9771 	child = child->next;
9772     }
9773     /*
9774     * URGENT TODO: Change the functions to return int results.
9775     * We need especially to catch internal errors.
9776     */
9777     while (child != NULL) {
9778 	if (IS_SCHEMA(child, "complexType")) {
9779 	    xmlSchemaParseComplexType(ctxt, schema, child, 1);
9780 	    child = child->next;
9781 	} else if (IS_SCHEMA(child, "simpleType")) {
9782 	    xmlSchemaParseSimpleType(ctxt, schema, child, 1);
9783 	    child = child->next;
9784 	} else if (IS_SCHEMA(child, "element")) {
9785 	    xmlSchemaParseElement(ctxt, schema, child, NULL, 1);
9786 	    child = child->next;
9787 	} else if (IS_SCHEMA(child, "attribute")) {
9788 	    xmlSchemaParseGlobalAttribute(ctxt, schema, child);
9789 	    child = child->next;
9790 	} else if (IS_SCHEMA(child, "attributeGroup")) {
9791 	    xmlSchemaParseAttributeGroupDefinition(ctxt, schema, child);
9792 	    child = child->next;
9793 	} else if (IS_SCHEMA(child, "group")) {
9794 	    xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
9795 	    child = child->next;
9796 	} else if (IS_SCHEMA(child, "notation")) {
9797 	    xmlSchemaParseNotation(ctxt, schema, child);
9798 	    child = child->next;
9799 	} else {
9800 	    xmlSchemaPContentErr(ctxt,
9801 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9802 		NULL, child->parent, child,
9803 		NULL, "((include | import | redefine | annotation)*, "
9804 		"(((simpleType | complexType | group | attributeGroup) "
9805 		"| element | attribute | notation), annotation*)*)");
9806 	    child = child->next;
9807 	}
9808 	while (IS_SCHEMA(child, "annotation")) {
9809 	    /*
9810 	    * TODO: We should add all annotations.
9811 	    */
9812 	    annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9813 	    if (schema->annot == NULL)
9814 		schema->annot = annot;
9815 	    else
9816 		xmlSchemaFreeAnnot(annot);
9817 	    child = child->next;
9818 	}
9819     }
9820 exit:
9821     ctxt->ctxtType = NULL;
9822     if (oldErrs != ctxt->nberrors)
9823 	res = ctxt->err;
9824     return(res);
9825 exit_failure:
9826     return(-1);
9827 }
9828 
9829 static xmlSchemaSchemaRelationPtr
xmlSchemaSchemaRelationCreate(void)9830 xmlSchemaSchemaRelationCreate(void)
9831 {
9832     xmlSchemaSchemaRelationPtr ret;
9833 
9834     ret = (xmlSchemaSchemaRelationPtr)
9835 	xmlMalloc(sizeof(xmlSchemaSchemaRelation));
9836     if (ret == NULL) {
9837 	xmlSchemaPErrMemory(NULL, "allocating schema relation", NULL);
9838 	return(NULL);
9839     }
9840     memset(ret, 0, sizeof(xmlSchemaSchemaRelation));
9841     return(ret);
9842 }
9843 
9844 #if 0
9845 static void
9846 xmlSchemaSchemaRelationFree(xmlSchemaSchemaRelationPtr rel)
9847 {
9848     xmlFree(rel);
9849 }
9850 #endif
9851 
9852 static void
xmlSchemaRedefListFree(xmlSchemaRedefPtr redef)9853 xmlSchemaRedefListFree(xmlSchemaRedefPtr redef)
9854 {
9855     xmlSchemaRedefPtr prev;
9856 
9857     while (redef != NULL) {
9858 	prev = redef;
9859 	redef = redef->next;
9860 	xmlFree(prev);
9861     }
9862 }
9863 
9864 static void
xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con)9865 xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con)
9866 {
9867     /*
9868     * After the construction context has been freed, there will be
9869     * no schema graph available any more. Only the schema buckets
9870     * will stay alive, which are put into the "schemasImports" and
9871     * "includes" slots of the xmlSchema.
9872     */
9873     if (con->buckets != NULL)
9874 	xmlSchemaItemListFree(con->buckets);
9875     if (con->pending != NULL)
9876 	xmlSchemaItemListFree(con->pending);
9877     if (con->substGroups != NULL)
9878 	xmlHashFree(con->substGroups,
9879 	    (xmlHashDeallocator) xmlSchemaSubstGroupFree);
9880     if (con->redefs != NULL)
9881 	xmlSchemaRedefListFree(con->redefs);
9882     if (con->dict != NULL)
9883 	xmlDictFree(con->dict);
9884     xmlFree(con);
9885 }
9886 
9887 static xmlSchemaConstructionCtxtPtr
xmlSchemaConstructionCtxtCreate(xmlDictPtr dict)9888 xmlSchemaConstructionCtxtCreate(xmlDictPtr dict)
9889 {
9890     xmlSchemaConstructionCtxtPtr ret;
9891 
9892     ret = (xmlSchemaConstructionCtxtPtr)
9893 	xmlMalloc(sizeof(xmlSchemaConstructionCtxt));
9894     if (ret == NULL) {
9895         xmlSchemaPErrMemory(NULL,
9896 	    "allocating schema construction context", NULL);
9897         return (NULL);
9898     }
9899     memset(ret, 0, sizeof(xmlSchemaConstructionCtxt));
9900 
9901     ret->buckets = xmlSchemaItemListCreate();
9902     if (ret->buckets == NULL) {
9903 	xmlSchemaPErrMemory(NULL,
9904 	    "allocating list of schema buckets", NULL);
9905 	xmlFree(ret);
9906         return (NULL);
9907     }
9908     ret->pending = xmlSchemaItemListCreate();
9909     if (ret->pending == NULL) {
9910 	xmlSchemaPErrMemory(NULL,
9911 	    "allocating list of pending global components", NULL);
9912 	xmlSchemaConstructionCtxtFree(ret);
9913         return (NULL);
9914     }
9915     ret->dict = dict;
9916     xmlDictReference(dict);
9917     return(ret);
9918 }
9919 
9920 static xmlSchemaParserCtxtPtr
xmlSchemaParserCtxtCreate(void)9921 xmlSchemaParserCtxtCreate(void)
9922 {
9923     xmlSchemaParserCtxtPtr ret;
9924 
9925     ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9926     if (ret == NULL) {
9927         xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9928                             NULL);
9929         return (NULL);
9930     }
9931     memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9932     ret->type = XML_SCHEMA_CTXT_PARSER;
9933     ret->attrProhibs = xmlSchemaItemListCreate();
9934     if (ret->attrProhibs == NULL) {
9935 	xmlFree(ret);
9936 	return(NULL);
9937     }
9938     return(ret);
9939 }
9940 
9941 /**
9942  * xmlSchemaNewParserCtxtUseDict:
9943  * @URL:  the location of the schema
9944  * @dict: the dictionary to be used
9945  *
9946  * Create an XML Schemas parse context for that file/resource expected
9947  * to contain an XML Schemas file.
9948  *
9949  * Returns the parser context or NULL in case of error
9950  */
9951 static xmlSchemaParserCtxtPtr
xmlSchemaNewParserCtxtUseDict(const char * URL,xmlDictPtr dict)9952 xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
9953 {
9954     xmlSchemaParserCtxtPtr ret;
9955 
9956     ret = xmlSchemaParserCtxtCreate();
9957     if (ret == NULL)
9958         return (NULL);
9959     ret->dict = dict;
9960     xmlDictReference(dict);
9961     if (URL != NULL)
9962 	ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
9963     return (ret);
9964 }
9965 
9966 static int
xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)9967 xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
9968 {
9969     if (vctxt->pctxt == NULL) {
9970         if (vctxt->schema != NULL)
9971 	    vctxt->pctxt =
9972 		xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
9973 	else
9974 	    vctxt->pctxt = xmlSchemaNewParserCtxt("*");
9975 	if (vctxt->pctxt == NULL) {
9976 	    VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
9977 		"failed to create a temp. parser context");
9978 	    return (-1);
9979 	}
9980 	/* TODO: Pass user data. */
9981 	xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error,
9982 	    vctxt->warning, vctxt->errCtxt);
9983 	xmlSchemaSetParserStructuredErrors(vctxt->pctxt, vctxt->serror,
9984 	    vctxt->errCtxt);
9985     }
9986     return (0);
9987 }
9988 
9989 /**
9990  * xmlSchemaGetSchemaBucket:
9991  * @pctxt: the schema parser context
9992  * @schemaLocation: the URI of the schema document
9993  *
9994  * Returns a schema bucket if it was already parsed.
9995  *
9996  * Returns a schema bucket if it was already parsed from
9997  *         @schemaLocation, NULL otherwise.
9998  */
9999 static xmlSchemaBucketPtr
xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt,const xmlChar * schemaLocation)10000 xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10001 			    const xmlChar *schemaLocation)
10002 {
10003     xmlSchemaBucketPtr cur;
10004     xmlSchemaItemListPtr list;
10005 
10006     list = pctxt->constructor->buckets;
10007     if (list->nbItems == 0)
10008 	return(NULL);
10009     else {
10010 	int i;
10011 	for (i = 0; i < list->nbItems; i++) {
10012 	    cur = (xmlSchemaBucketPtr) list->items[i];
10013 	    /* Pointer comparison! */
10014 	    if (cur->schemaLocation == schemaLocation)
10015 		return(cur);
10016 	}
10017     }
10018     return(NULL);
10019 }
10020 
10021 static xmlSchemaBucketPtr
xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt,const xmlChar * schemaLocation,const xmlChar * targetNamespace)10022 xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10023 				     const xmlChar *schemaLocation,
10024 				     const xmlChar *targetNamespace)
10025 {
10026     xmlSchemaBucketPtr cur;
10027     xmlSchemaItemListPtr list;
10028 
10029     list = pctxt->constructor->buckets;
10030     if (list->nbItems == 0)
10031 	return(NULL);
10032     else {
10033 	int i;
10034 	for (i = 0; i < list->nbItems; i++) {
10035 	    cur = (xmlSchemaBucketPtr) list->items[i];
10036 	    /* Pointer comparison! */
10037 	    if ((cur->origTargetNamespace == NULL) &&
10038 		(cur->schemaLocation == schemaLocation) &&
10039 		(cur->targetNamespace == targetNamespace))
10040 		return(cur);
10041 	}
10042     }
10043     return(NULL);
10044 }
10045 
10046 
10047 #define IS_BAD_SCHEMA_DOC(b) \
10048     (((b)->doc == NULL) && ((b)->schemaLocation != NULL))
10049 
10050 static xmlSchemaBucketPtr
xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt,const xmlChar * targetNamespace,int imported)10051 xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt,
10052 				 const xmlChar *targetNamespace,
10053 				 int imported)
10054 {
10055     xmlSchemaBucketPtr cur;
10056     xmlSchemaItemListPtr list;
10057 
10058     list = pctxt->constructor->buckets;
10059     if (list->nbItems == 0)
10060 	return(NULL);
10061     else {
10062 	int i;
10063 	for (i = 0; i < list->nbItems; i++) {
10064 	    cur = (xmlSchemaBucketPtr) list->items[i];
10065 	    if ((! IS_BAD_SCHEMA_DOC(cur)) &&
10066 		(cur->origTargetNamespace == targetNamespace) &&
10067 		((imported && cur->imported) ||
10068 		 ((!imported) && (!cur->imported))))
10069 		return(cur);
10070 	}
10071     }
10072     return(NULL);
10073 }
10074 
10075 static int
xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlSchemaBucketPtr bucket)10076 xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt,
10077 		     xmlSchemaPtr schema,
10078 		     xmlSchemaBucketPtr bucket)
10079 {
10080     int oldFlags;
10081     xmlDocPtr oldDoc;
10082     xmlNodePtr node;
10083     int ret, oldErrs;
10084     xmlSchemaBucketPtr oldbucket = pctxt->constructor->bucket;
10085 
10086     /*
10087     * Save old values; reset the *main* schema.
10088     * URGENT TODO: This is not good; move the per-document information
10089     * to the parser. Get rid of passing the main schema to the
10090     * parsing functions.
10091     */
10092     oldFlags = schema->flags;
10093     oldDoc = schema->doc;
10094     if (schema->flags != 0)
10095 	xmlSchemaClearSchemaDefaults(schema);
10096     schema->doc = bucket->doc;
10097     pctxt->schema = schema;
10098     /*
10099     * Keep the current target namespace on the parser *not* on the
10100     * main schema.
10101     */
10102     pctxt->targetNamespace = bucket->targetNamespace;
10103     WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
10104 
10105     if ((bucket->targetNamespace != NULL) &&
10106 	xmlStrEqual(bucket->targetNamespace, xmlSchemaNs)) {
10107 	/*
10108 	* We are parsing the schema for schemas!
10109 	*/
10110 	pctxt->isS4S = 1;
10111     }
10112     /* Mark it as parsed, even if parsing fails. */
10113     bucket->parsed++;
10114     /* Compile the schema doc. */
10115     node = xmlDocGetRootElement(bucket->doc);
10116     ret = xmlSchemaParseSchemaElement(pctxt, schema, node);
10117     if (ret != 0)
10118 	goto exit;
10119     /* An empty schema; just get out. */
10120     if (node->children == NULL)
10121 	goto exit;
10122     oldErrs = pctxt->nberrors;
10123     ret = xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
10124     if (ret != 0)
10125 	goto exit;
10126     /*
10127     * TODO: Not nice, but I'm not 100% sure we will get always an error
10128     * as a result of the obove functions; so better rely on pctxt->err
10129     * as well.
10130     */
10131     if ((ret == 0) && (oldErrs != pctxt->nberrors)) {
10132 	ret = pctxt->err;
10133 	goto exit;
10134     }
10135 
10136 exit:
10137     WXS_CONSTRUCTOR(pctxt)->bucket = oldbucket;
10138     /* Restore schema values. */
10139     schema->doc = oldDoc;
10140     schema->flags = oldFlags;
10141     return(ret);
10142 }
10143 
10144 static int
xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlSchemaBucketPtr bucket)10145 xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt,
10146 		     xmlSchemaPtr schema,
10147 		     xmlSchemaBucketPtr bucket)
10148 {
10149     xmlSchemaParserCtxtPtr newpctxt;
10150     int res = 0;
10151 
10152     if (bucket == NULL)
10153 	return(0);
10154     if (bucket->parsed) {
10155 	PERROR_INT("xmlSchemaParseNewDoc",
10156 	    "reparsing a schema doc");
10157 	return(-1);
10158     }
10159     if (bucket->doc == NULL) {
10160 	PERROR_INT("xmlSchemaParseNewDoc",
10161 	    "parsing a schema doc, but there's no doc");
10162 	return(-1);
10163     }
10164     if (pctxt->constructor == NULL) {
10165 	PERROR_INT("xmlSchemaParseNewDoc",
10166 	    "no constructor");
10167 	return(-1);
10168     }
10169     /* Create and init the temporary parser context. */
10170     newpctxt = xmlSchemaNewParserCtxtUseDict(
10171 	(const char *) bucket->schemaLocation, pctxt->dict);
10172     if (newpctxt == NULL)
10173 	return(-1);
10174     newpctxt->constructor = pctxt->constructor;
10175     /*
10176     * TODO: Can we avoid that the parser knows about the main schema?
10177     * It would be better if he knows about the current schema bucket
10178     * only.
10179     */
10180     newpctxt->schema = schema;
10181     xmlSchemaSetParserErrors(newpctxt, pctxt->error, pctxt->warning,
10182 	pctxt->errCtxt);
10183     xmlSchemaSetParserStructuredErrors(newpctxt, pctxt->serror,
10184 	pctxt->errCtxt);
10185     newpctxt->counter = pctxt->counter;
10186 
10187 
10188     res = xmlSchemaParseNewDocWithContext(newpctxt, schema, bucket);
10189 
10190     /* Channel back errors and cleanup the temporary parser context. */
10191     if (res != 0)
10192 	pctxt->err = res;
10193     pctxt->nberrors += newpctxt->nberrors;
10194     pctxt->counter = newpctxt->counter;
10195     newpctxt->constructor = NULL;
10196     /* Free the parser context. */
10197     xmlSchemaFreeParserCtxt(newpctxt);
10198     return(res);
10199 }
10200 
10201 static void
xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket,xmlSchemaSchemaRelationPtr rel)10202 xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket,
10203 				xmlSchemaSchemaRelationPtr rel)
10204 {
10205     xmlSchemaSchemaRelationPtr cur = bucket->relations;
10206 
10207     if (cur == NULL) {
10208 	bucket->relations = rel;
10209 	return;
10210     }
10211     while (cur->next != NULL)
10212 	cur = cur->next;
10213     cur->next = rel;
10214 }
10215 
10216 
10217 static const xmlChar *
xmlSchemaBuildAbsoluteURI(xmlDictPtr dict,const xmlChar * location,xmlNodePtr ctxtNode)10218 xmlSchemaBuildAbsoluteURI(xmlDictPtr dict, const xmlChar* location,
10219 			  xmlNodePtr ctxtNode)
10220 {
10221     /*
10222     * Build an absolue location URI.
10223     */
10224     if (location != NULL) {
10225 	if (ctxtNode == NULL)
10226 	    return(location);
10227 	else {
10228 	    xmlChar *base, *URI;
10229 	    const xmlChar *ret = NULL;
10230 
10231 	    base = xmlNodeGetBase(ctxtNode->doc, ctxtNode);
10232 	    if (base == NULL) {
10233 		URI = xmlBuildURI(location, ctxtNode->doc->URL);
10234 	    } else {
10235 		URI = xmlBuildURI(location, base);
10236 		xmlFree(base);
10237 	    }
10238 	    if (URI != NULL) {
10239 		ret = xmlDictLookup(dict, URI, -1);
10240 		xmlFree(URI);
10241 		return(ret);
10242 	    }
10243 	}
10244     }
10245     return(NULL);
10246 }
10247 
10248 
10249 
10250 /**
10251  * xmlSchemaAddSchemaDoc:
10252  * @pctxt:  a schema validation context
10253  * @schema:  the schema being built
10254  * @node:  a subtree containing XML Schema informations
10255  *
10256  * Parse an included (and to-be-redefined) XML schema document.
10257  *
10258  * Returns 0 on success, a positive error code on errors and
10259  *         -1 in case of an internal or API error.
10260  */
10261 
10262 static int
xmlSchemaAddSchemaDoc(xmlSchemaParserCtxtPtr pctxt,int type,const xmlChar * schemaLocation,xmlDocPtr schemaDoc,const char * schemaBuffer,int schemaBufferLen,xmlNodePtr invokingNode,const xmlChar * sourceTargetNamespace,const xmlChar * importNamespace,xmlSchemaBucketPtr * bucket)10263 xmlSchemaAddSchemaDoc(xmlSchemaParserCtxtPtr pctxt,
10264 		int type, /* import or include or redefine */
10265 		const xmlChar *schemaLocation,
10266 		xmlDocPtr schemaDoc,
10267 		const char *schemaBuffer,
10268 		int schemaBufferLen,
10269 		xmlNodePtr invokingNode,
10270 		const xmlChar *sourceTargetNamespace,
10271 		const xmlChar *importNamespace,
10272 		xmlSchemaBucketPtr *bucket)
10273 {
10274     const xmlChar *targetNamespace = NULL;
10275     xmlSchemaSchemaRelationPtr relation = NULL;
10276     xmlDocPtr doc = NULL;
10277     int res = 0, err = 0, located = 0, preserveDoc = 0;
10278     xmlSchemaBucketPtr bkt = NULL;
10279 
10280     if (bucket != NULL)
10281 	*bucket = NULL;
10282 
10283     switch (type) {
10284 	case XML_SCHEMA_SCHEMA_IMPORT:
10285 	case XML_SCHEMA_SCHEMA_MAIN:
10286 	    err = XML_SCHEMAP_SRC_IMPORT;
10287 	    break;
10288 	case XML_SCHEMA_SCHEMA_INCLUDE:
10289 	    err = XML_SCHEMAP_SRC_INCLUDE;
10290 	    break;
10291 	case XML_SCHEMA_SCHEMA_REDEFINE:
10292 	    err = XML_SCHEMAP_SRC_REDEFINE;
10293 	    break;
10294     }
10295 
10296 
10297     /* Special handling for the main schema:
10298     * skip the location and relation logic and just parse the doc.
10299     * We need just a bucket to be returned in this case.
10300     */
10301     if ((type == XML_SCHEMA_SCHEMA_MAIN) || (! WXS_HAS_BUCKETS(pctxt)))
10302 	goto doc_load;
10303 
10304     /* Note that we expect the location to be an absulute URI. */
10305     if (schemaLocation != NULL) {
10306 	bkt = xmlSchemaGetSchemaBucket(pctxt, schemaLocation);
10307 	if ((bkt != NULL) &&
10308 	    (pctxt->constructor->bucket == bkt)) {
10309 	    /* Report self-imports/inclusions/redefinitions. */
10310 
10311 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10312 		invokingNode, NULL,
10313 		"The schema must not import/include/redefine itself",
10314 		NULL, NULL);
10315 	    goto exit;
10316 	}
10317     }
10318     /*
10319     * Create a relation for the graph of schemas.
10320     */
10321     relation = xmlSchemaSchemaRelationCreate();
10322     if (relation == NULL)
10323 	return(-1);
10324     xmlSchemaSchemaRelationAddChild(pctxt->constructor->bucket,
10325 	relation);
10326     relation->type = type;
10327 
10328     /*
10329     * Save the namespace import information.
10330     */
10331     if (WXS_IS_BUCKET_IMPMAIN(type)) {
10332 	relation->importNamespace = importNamespace;
10333 	if (schemaLocation == NULL) {
10334 	    /*
10335 	    * No location; this is just an import of the namespace.
10336 	    * Note that we don't assign a bucket to the relation
10337 	    * in this case.
10338 	    */
10339 	    goto exit;
10340 	}
10341 	targetNamespace = importNamespace;
10342     }
10343 
10344     /* Did we already fetch the doc? */
10345     if (bkt != NULL) {
10346 	/* TODO: The following nasty cases will produce an error. */
10347 	if ((WXS_IS_BUCKET_IMPMAIN(type)) && (! bkt->imported)) {
10348 	    /* We included/redefined and then try to import a schema. */
10349 	    if (schemaLocation == NULL)
10350 		schemaLocation = BAD_CAST "in_memory_buffer";
10351 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10352 		invokingNode, NULL,
10353 		"The schema document '%s' cannot be imported, since "
10354 		"it was already included or redefined",
10355 		schemaLocation, NULL);
10356 	    goto exit;
10357 	} else if ((! WXS_IS_BUCKET_IMPMAIN(type)) && (bkt->imported)) {
10358 	    /* We imported and then try to include/redefine a schema. */
10359 	    if (schemaLocation == NULL)
10360 		schemaLocation = BAD_CAST "in_memory_buffer";
10361 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10362 		invokingNode, NULL,
10363 		"The schema document '%s' cannot be included or "
10364 		"redefined, since it was already imported",
10365 		schemaLocation, NULL);
10366 	    goto exit;
10367 	}
10368     }
10369 
10370     if (WXS_IS_BUCKET_IMPMAIN(type)) {
10371 	/*
10372 	* Given that the schemaLocation [attribute] is only a hint, it is open
10373 	* to applications to ignore all but the first <import> for a given
10374 	* namespace, regardless of the �actual value� of schemaLocation, but
10375 	* such a strategy risks missing useful information when new
10376 	* schemaLocations are offered.
10377 	*
10378 	* We will use the first <import> that comes with a location.
10379 	* Further <import>s *with* a location, will result in an error.
10380 	* TODO: Better would be to just report a warning here, but
10381 	* we'll try it this way until someone complains.
10382 	*
10383 	* Schema Document Location Strategy:
10384 	* 3 Based on the namespace name, identify an existing schema document,
10385 	* either as a resource which is an XML document or a <schema> element
10386 	* information item, in some local schema repository;
10387 	* 5 Attempt to resolve the namespace name to locate such a resource.
10388 	*
10389 	* NOTE: (3) and (5) are not supported.
10390 	*/
10391 	if (bkt != NULL) {
10392 	    relation->bucket = bkt;
10393 	    goto exit;
10394 	}
10395 	bkt = xmlSchemaGetSchemaBucketByTNS(pctxt,
10396 	    importNamespace, 1);
10397 
10398 	if (bkt != NULL) {
10399 	    relation->bucket = bkt;
10400 	    if (bkt->schemaLocation == NULL) {
10401 		/* First given location of the schema; load the doc. */
10402 		bkt->schemaLocation = schemaLocation;
10403 	    } else {
10404 		if (!xmlStrEqual(schemaLocation,
10405 		    bkt->schemaLocation)) {
10406 		    /*
10407 		    * Additional location given; just skip it.
10408 		    * URGENT TODO: We should report a warning here.
10409 		    * res = XML_SCHEMAP_SRC_IMPORT;
10410 		    */
10411 		    if (schemaLocation == NULL)
10412 			schemaLocation = BAD_CAST "in_memory_buffer";
10413 
10414 		    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10415 			XML_SCHEMAP_WARN_SKIP_SCHEMA,
10416 			invokingNode, NULL,
10417 			"Skipping import of schema located at '%s' for the "
10418 			"namespace '%s', since this namespace was already "
10419 			"imported with the schema located at '%s'",
10420 			schemaLocation, importNamespace, bkt->schemaLocation);
10421 		}
10422 		goto exit;
10423 	    }
10424 	}
10425 	/*
10426 	* No bucket + first location: load the doc and create a
10427 	* bucket.
10428 	*/
10429     } else {
10430 	/* <include> and <redefine> */
10431 	if (bkt != NULL) {
10432 
10433 	    if ((bkt->origTargetNamespace == NULL) &&
10434 		(bkt->targetNamespace != sourceTargetNamespace)) {
10435 		xmlSchemaBucketPtr chamel;
10436 
10437 		/*
10438 		* Chameleon include/redefine: skip loading only if it was
10439 		* aleady build for the targetNamespace of the including
10440 		* schema.
10441 		*/
10442 		/*
10443 		* URGENT TODO: If the schema is a chameleon-include then copy
10444 		* the components into the including schema and modify the
10445 		* targetNamespace of those components, do nothing otherwise.
10446 		* NOTE: This is currently worked-around by compiling the
10447 		* chameleon for every destinct including targetNamespace; thus
10448 		* not performant at the moment.
10449 		* TODO: Check when the namespace in wildcards for chameleons
10450 		* needs to be converted: before we built wildcard intersections
10451 		* or after.
10452 		*   Answer: after!
10453 		*/
10454 		chamel = xmlSchemaGetChameleonSchemaBucket(pctxt,
10455 		    schemaLocation, sourceTargetNamespace);
10456 		if (chamel != NULL) {
10457 		    /* A fitting chameleon was already parsed; NOP. */
10458 		    relation->bucket = chamel;
10459 		    goto exit;
10460 		}
10461 		/*
10462 		* We need to parse the chameleon again for a different
10463 		* targetNamespace.
10464 		* CHAMELEON TODO: Optimize this by only parsing the
10465 		* chameleon once, and then copying the components to
10466 		* the new targetNamespace.
10467 		*/
10468 		bkt = NULL;
10469 	    } else {
10470 		relation->bucket = bkt;
10471 		goto exit;
10472 	    }
10473 	}
10474     }
10475     if ((bkt != NULL) && (bkt->doc != NULL)) {
10476 	PERROR_INT("xmlSchemaAddSchemaDoc",
10477 	    "trying to load a schema doc, but a doc is already "
10478 	    "assigned to the schema bucket");
10479 	goto exit_failure;
10480     }
10481 
10482 doc_load:
10483     /*
10484     * Load the document.
10485     */
10486     if (schemaDoc != NULL) {
10487 	doc = schemaDoc;
10488 	/* Don' free this one, since it was provided by the caller. */
10489 	preserveDoc = 1;
10490 	/* TODO: Does the context or the doc hold the location? */
10491 	if (schemaDoc->URL != NULL)
10492 	    schemaLocation = xmlDictLookup(pctxt->dict,
10493 		schemaDoc->URL, -1);
10494         else
10495 	    schemaLocation = BAD_CAST "in_memory_buffer";
10496     } else if ((schemaLocation != NULL) || (schemaBuffer != NULL)) {
10497 	xmlParserCtxtPtr parserCtxt;
10498 
10499 	parserCtxt = xmlNewParserCtxt();
10500 	if (parserCtxt == NULL) {
10501 	    xmlSchemaPErrMemory(NULL, "xmlSchemaGetDoc, "
10502 		"allocating a parser context", NULL);
10503 	    goto exit_failure;
10504 	}
10505 	if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
10506 	    /*
10507 	    * TODO: Do we have to burden the schema parser dict with all
10508 	    * the content of the schema doc?
10509 	    */
10510 	    xmlDictFree(parserCtxt->dict);
10511 	    parserCtxt->dict = pctxt->dict;
10512 	    xmlDictReference(parserCtxt->dict);
10513 	}
10514 	if (schemaLocation != NULL) {
10515 	    /* Parse from file. */
10516 	    doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
10517 		NULL, SCHEMAS_PARSE_OPTIONS);
10518 	} else if (schemaBuffer != NULL) {
10519 	    /* Parse from memory buffer. */
10520 	    doc = xmlCtxtReadMemory(parserCtxt, schemaBuffer, schemaBufferLen,
10521 		NULL, NULL, SCHEMAS_PARSE_OPTIONS);
10522 	    schemaLocation = xmlStrdup(BAD_CAST "in_memory_buffer");
10523 	    if (doc != NULL)
10524 		doc->URL = schemaLocation;
10525 	}
10526 	/*
10527 	* For <import>:
10528 	* 2.1 The referent is (a fragment of) a resource which is an
10529 	* XML document (see clause 1.1), which in turn corresponds to
10530 	* a <schema> element information item in a well-formed information
10531 	* set, which in turn corresponds to a valid schema.
10532 	* TODO: (2.1) fragments of XML documents are not supported.
10533 	*
10534 	* 2.2 The referent is a <schema> element information item in
10535 	* a well-formed information set, which in turn corresponds
10536 	* to a valid schema.
10537 	* TODO: (2.2) is not supported.
10538 	*/
10539 	if (doc == NULL) {
10540 	    xmlErrorPtr lerr;
10541 	    lerr = xmlGetLastError();
10542 	    /*
10543 	    * Check if this a parser error, or if the document could
10544 	    * just not be located.
10545 	    * TODO: Try to find specific error codes to react only on
10546 	    * localisation failures.
10547 	    */
10548 	    if ((lerr == NULL) || (lerr->domain != XML_FROM_IO)) {
10549 		/*
10550 		* We assume a parser error here.
10551 		*/
10552 		located = 1;
10553 		/* TODO: Error code ?? */
10554 		res = XML_SCHEMAP_SRC_IMPORT_2_1;
10555 		xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10556 		    invokingNode, NULL,
10557 		    "Failed to parse the XML resource '%s'",
10558 		    schemaLocation, NULL);
10559 	    }
10560 	}
10561 	xmlFreeParserCtxt(parserCtxt);
10562 	if ((doc == NULL) && located)
10563 	    goto exit_error;
10564     } else {
10565 	xmlSchemaPErr(pctxt, NULL,
10566 	    XML_SCHEMAP_NOTHING_TO_PARSE,
10567 	    "No information for parsing was provided with the "
10568 	    "given schema parser context.\n",
10569 	    NULL, NULL);
10570 	goto exit_failure;
10571     }
10572     /*
10573     * Preprocess the document.
10574     */
10575     if (doc != NULL) {
10576 	xmlNodePtr docElem = NULL;
10577 
10578 	located = 1;
10579 	docElem = xmlDocGetRootElement(doc);
10580 	if (docElem == NULL) {
10581 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOROOT,
10582 		invokingNode, NULL,
10583 		"The document '%s' has no document element",
10584 		schemaLocation, NULL);
10585 	    goto exit_error;
10586 	}
10587 	/*
10588 	* Remove all the blank text nodes.
10589 	*/
10590 	xmlSchemaCleanupDoc(pctxt, docElem);
10591 	/*
10592 	* Check the schema's top level element.
10593 	*/
10594 	if (!IS_SCHEMA(docElem, "schema")) {
10595 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOT_SCHEMA,
10596 		invokingNode, NULL,
10597 		"The XML document '%s' is not a schema document",
10598 		schemaLocation, NULL);
10599 	    goto exit_error;
10600 	}
10601 	/*
10602 	* Note that we don't apply a type check for the
10603 	* targetNamespace value here.
10604 	*/
10605 	targetNamespace = xmlSchemaGetProp(pctxt, docElem,
10606 	    "targetNamespace");
10607     }
10608 
10609 /* after_doc_loading: */
10610     if ((bkt == NULL) && located) {
10611 	/* Only create a bucket if the schema was located. */
10612         bkt = xmlSchemaBucketCreate(pctxt, type,
10613 	    targetNamespace);
10614 	if (bkt == NULL)
10615 	    goto exit_failure;
10616     }
10617     if (bkt != NULL) {
10618 	bkt->schemaLocation = schemaLocation;
10619 	bkt->located = located;
10620 	if (doc != NULL) {
10621 	    bkt->doc = doc;
10622 	    bkt->targetNamespace = targetNamespace;
10623 	    bkt->origTargetNamespace = targetNamespace;
10624 	    if (preserveDoc)
10625 		bkt->preserveDoc = 1;
10626 	}
10627 	if (WXS_IS_BUCKET_IMPMAIN(type))
10628 	    bkt->imported++;
10629 	    /*
10630 	    * Add it to the graph of schemas.
10631 	    */
10632 	if (relation != NULL)
10633 	    relation->bucket = bkt;
10634     }
10635 
10636 exit:
10637     /*
10638     * Return the bucket explicitely; this is needed for the
10639     * main schema.
10640     */
10641     if (bucket != NULL)
10642 	*bucket = bkt;
10643     return (0);
10644 
10645 exit_error:
10646     if ((doc != NULL) && (! preserveDoc)) {
10647 	xmlFreeDoc(doc);
10648 	if (bkt != NULL)
10649 	    bkt->doc = NULL;
10650     }
10651     return(pctxt->err);
10652 
10653 exit_failure:
10654     if ((doc != NULL) && (! preserveDoc)) {
10655 	xmlFreeDoc(doc);
10656 	if (bkt != NULL)
10657 	    bkt->doc = NULL;
10658     }
10659     return (-1);
10660 }
10661 
10662 /**
10663  * xmlSchemaParseImport:
10664  * @ctxt:  a schema validation context
10665  * @schema:  the schema being built
10666  * @node:  a subtree containing XML Schema informations
10667  *
10668  * parse a XML schema Import definition
10669  * *WARNING* this interface is highly subject to change
10670  *
10671  * Returns 0 in case of success, a positive error code if
10672  * not valid and -1 in case of an internal error.
10673  */
10674 static int
xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)10675 xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
10676                      xmlNodePtr node)
10677 {
10678     xmlNodePtr child;
10679     const xmlChar *namespaceName = NULL, *schemaLocation = NULL;
10680     const xmlChar *thisTargetNamespace;
10681     xmlAttrPtr attr;
10682     int ret = 0;
10683     xmlSchemaBucketPtr bucket = NULL;
10684 
10685     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10686         return (-1);
10687 
10688     /*
10689     * Check for illegal attributes.
10690     */
10691     attr = node->properties;
10692     while (attr != NULL) {
10693 	if (attr->ns == NULL) {
10694 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10695 		(!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
10696 		(!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10697 		xmlSchemaPIllegalAttrErr(pctxt,
10698 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10699 	    }
10700 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10701 	    xmlSchemaPIllegalAttrErr(pctxt,
10702 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10703 	}
10704 	attr = attr->next;
10705     }
10706     /*
10707     * Extract and validate attributes.
10708     */
10709     if (xmlSchemaPValAttr(pctxt, NULL, node,
10710 	"namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10711 	&namespaceName) != 0) {
10712 	xmlSchemaPSimpleTypeErr(pctxt,
10713 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10714 	    NULL, node,
10715 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10716 	    NULL, namespaceName, NULL, NULL, NULL);
10717 	return (pctxt->err);
10718     }
10719 
10720     if (xmlSchemaPValAttr(pctxt, NULL, node,
10721 	"schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10722 	&schemaLocation) != 0) {
10723 	xmlSchemaPSimpleTypeErr(pctxt,
10724 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10725 	    NULL, node,
10726 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10727 	    NULL, namespaceName, NULL, NULL, NULL);
10728 	return (pctxt->err);
10729     }
10730     /*
10731     * And now for the children...
10732     */
10733     child = node->children;
10734     if (IS_SCHEMA(child, "annotation")) {
10735         /*
10736          * the annotation here is simply discarded ...
10737 	 * TODO: really?
10738          */
10739         child = child->next;
10740     }
10741     if (child != NULL) {
10742 	xmlSchemaPContentErr(pctxt,
10743 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10744 	    NULL, node, child, NULL,
10745 	    "(annotation?)");
10746     }
10747     /*
10748     * Apply additional constraints.
10749     *
10750     * Note that it is important to use the original @targetNamespace
10751     * (or none at all), to rule out imports of schemas _with_ a
10752     * @targetNamespace if the importing schema is a chameleon schema
10753     * (with no @targetNamespace).
10754     */
10755     thisTargetNamespace = WXS_BUCKET(pctxt)->origTargetNamespace;
10756     if (namespaceName != NULL) {
10757 	/*
10758 	* 1.1 If the namespace [attribute] is present, then its �actual value�
10759 	* must not match the �actual value� of the enclosing <schema>'s
10760 	* targetNamespace [attribute].
10761 	*/
10762 	if (xmlStrEqual(thisTargetNamespace, namespaceName)) {
10763 	    xmlSchemaPCustomErr(pctxt,
10764 		XML_SCHEMAP_SRC_IMPORT_1_1,
10765 		NULL, node,
10766 		"The value of the attribute 'namespace' must not match "
10767 		"the target namespace '%s' of the importing schema",
10768 		thisTargetNamespace);
10769 	    return (pctxt->err);
10770 	}
10771     } else {
10772 	/*
10773 	* 1.2 If the namespace [attribute] is not present, then the enclosing
10774 	* <schema> must have a targetNamespace [attribute].
10775 	*/
10776 	if (thisTargetNamespace == NULL) {
10777 	    xmlSchemaPCustomErr(pctxt,
10778 		XML_SCHEMAP_SRC_IMPORT_1_2,
10779 		NULL, node,
10780 		"The attribute 'namespace' must be existent if "
10781 		"the importing schema has no target namespace",
10782 		NULL);
10783 	    return (pctxt->err);
10784 	}
10785     }
10786     /*
10787     * Locate and acquire the schema document.
10788     */
10789     if (schemaLocation != NULL)
10790 	schemaLocation = xmlSchemaBuildAbsoluteURI(pctxt->dict,
10791 	    schemaLocation, node);
10792     ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
10793 	schemaLocation, NULL, NULL, 0, node, thisTargetNamespace,
10794 	namespaceName, &bucket);
10795 
10796     if (ret != 0)
10797 	return(ret);
10798 
10799     /*
10800     * For <import>: "It is *not* an error for the application
10801     * schema reference strategy to fail."
10802     * So just don't parse if no schema document was found.
10803     * Note that we will get no bucket if the schema could not be
10804     * located or if there was no schemaLocation.
10805     */
10806     if ((bucket == NULL) && (schemaLocation != NULL)) {
10807 	xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10808 	    XML_SCHEMAP_WARN_UNLOCATED_SCHEMA,
10809 	    node, NULL,
10810 	    "Failed to locate a schema at location '%s'. "
10811 	    "Skipping the import", schemaLocation, NULL, NULL);
10812     }
10813 
10814     if ((bucket != NULL) && CAN_PARSE_SCHEMA(bucket)) {
10815 	ret = xmlSchemaParseNewDoc(pctxt, schema, bucket);
10816     }
10817 
10818     return (ret);
10819 }
10820 
10821 static int
xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlChar ** schemaLocation,int type)10822 xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,
10823 				     xmlSchemaPtr schema,
10824 				     xmlNodePtr node,
10825 				     xmlChar **schemaLocation,
10826 				     int type)
10827 {
10828     xmlAttrPtr attr;
10829 
10830     if ((pctxt == NULL) || (schema == NULL) || (node == NULL) ||
10831 	(schemaLocation == NULL))
10832         return (-1);
10833 
10834     *schemaLocation = NULL;
10835     /*
10836     * Check for illegal attributes.
10837     * Applies for both <include> and <redefine>.
10838     */
10839     attr = node->properties;
10840     while (attr != NULL) {
10841 	if (attr->ns == NULL) {
10842 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10843 		(!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10844 		xmlSchemaPIllegalAttrErr(pctxt,
10845 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10846 	    }
10847 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10848 	    xmlSchemaPIllegalAttrErr(pctxt,
10849 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10850 	}
10851 	attr = attr->next;
10852     }
10853     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
10854     /*
10855     * Preliminary step, extract the URI-Reference and make an URI
10856     * from the base.
10857     */
10858     /*
10859     * Attribute "schemaLocation" is mandatory.
10860     */
10861     attr = xmlSchemaGetPropNode(node, "schemaLocation");
10862     if (attr != NULL) {
10863         xmlChar *base = NULL;
10864         xmlChar *uri = NULL;
10865 
10866 	if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
10867 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10868 	    (const xmlChar **) schemaLocation) != 0)
10869 	    goto exit_error;
10870 	base = xmlNodeGetBase(node->doc, node);
10871 	if (base == NULL) {
10872 	    uri = xmlBuildURI(*schemaLocation, node->doc->URL);
10873 	} else {
10874 	    uri = xmlBuildURI(*schemaLocation, base);
10875 	    xmlFree(base);
10876 	}
10877 	if (uri == NULL) {
10878 	    PERROR_INT("xmlSchemaParseIncludeOrRedefine",
10879 		"could not build an URI from the schemaLocation")
10880 	    goto exit_failure;
10881 	}
10882 	(*schemaLocation) = (xmlChar *) xmlDictLookup(pctxt->dict, uri, -1);
10883 	xmlFree(uri);
10884     } else {
10885 	xmlSchemaPMissingAttrErr(pctxt,
10886 	    XML_SCHEMAP_S4S_ATTR_MISSING,
10887 	    NULL, node, "schemaLocation", NULL);
10888 	goto exit_error;
10889     }
10890     /*
10891     * Report self-inclusion and self-redefinition.
10892     */
10893     if (xmlStrEqual(*schemaLocation, pctxt->URL)) {
10894 	if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
10895 	    xmlSchemaPCustomErr(pctxt,
10896 		XML_SCHEMAP_SRC_REDEFINE,
10897 		NULL, node,
10898 		"The schema document '%s' cannot redefine itself.",
10899 		*schemaLocation);
10900 	} else {
10901 	    xmlSchemaPCustomErr(pctxt,
10902 		XML_SCHEMAP_SRC_INCLUDE,
10903 		NULL, node,
10904 		"The schema document '%s' cannot include itself.",
10905 		*schemaLocation);
10906 	}
10907 	goto exit_error;
10908     }
10909 
10910     return(0);
10911 exit_error:
10912     return(pctxt->err);
10913 exit_failure:
10914     return(-1);
10915 }
10916 
10917 static int
xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node,int type)10918 xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,
10919 				xmlSchemaPtr schema,
10920 				xmlNodePtr node,
10921 				int type)
10922 {
10923     xmlNodePtr child = NULL;
10924     const xmlChar *schemaLocation = NULL;
10925     int res = 0; /* hasRedefinitions = 0 */
10926     int isChameleon = 0, wasChameleon = 0;
10927     xmlSchemaBucketPtr bucket = NULL;
10928 
10929     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10930         return (-1);
10931 
10932     /*
10933     * Parse attributes. Note that the returned schemaLocation will
10934     * be already converted to an absolute URI.
10935     */
10936     res = xmlSchemaParseIncludeOrRedefineAttrs(pctxt, schema,
10937 	node, (xmlChar **) (&schemaLocation), type);
10938     if (res != 0)
10939 	return(res);
10940     /*
10941     * Load and add the schema document.
10942     */
10943     res = xmlSchemaAddSchemaDoc(pctxt, type, schemaLocation, NULL,
10944 	NULL, 0, node, pctxt->targetNamespace, NULL, &bucket);
10945     if (res != 0)
10946 	return(res);
10947     /*
10948     * If we get no schema bucket back, then this means that the schema
10949     * document could not be located or was broken XML or was not
10950     * a schema document.
10951     */
10952     if ((bucket == NULL) || (bucket->doc == NULL)) {
10953 	if (type == XML_SCHEMA_SCHEMA_INCLUDE) {
10954 	    /*
10955 	    * WARNING for <include>:
10956 	    * We will raise an error if the schema cannot be located
10957 	    * for inclusions, since the that was the feedback from the
10958 	    * schema people. I.e. the following spec piece will *not* be
10959 	    * satisfied:
10960 	    * SPEC src-include: "It is not an error for the �actual value� of the
10961 	    * schemaLocation [attribute] to fail to resolve it all, in which
10962 	    * case no corresponding inclusion is performed.
10963 	    * So do we need a warning report here?"
10964 	    */
10965 	    res = XML_SCHEMAP_SRC_INCLUDE;
10966 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10967 		node, NULL,
10968 		"Failed to load the document '%s' for inclusion",
10969 		schemaLocation, NULL);
10970 	} else {
10971 	    /*
10972 	    * NOTE: This was changed to raise an error even if no redefinitions
10973 	    * are specified.
10974 	    *
10975 	    * SPEC src-redefine (1)
10976 	    * "If there are any element information items among the [children]
10977 	    * other than <annotation> then the �actual value� of the
10978 	    * schemaLocation [attribute] must successfully resolve."
10979 	    * TODO: Ask the WG if a the location has always to resolve
10980 	    * here as well!
10981 	    */
10982 	    res = XML_SCHEMAP_SRC_REDEFINE;
10983 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10984 		node, NULL,
10985 		"Failed to load the document '%s' for redefinition",
10986 		schemaLocation, NULL);
10987 	}
10988     } else {
10989 	/*
10990 	* Check targetNamespace sanity before parsing the new schema.
10991 	* TODO: Note that we won't check further content if the
10992 	* targetNamespace was bad.
10993 	*/
10994 	if (bucket->origTargetNamespace != NULL) {
10995 	    /*
10996 	    * SPEC src-include (2.1)
10997 	    * "SII has a targetNamespace [attribute], and its �actual
10998 	    * value� is identical to the �actual value� of the targetNamespace
10999 	    * [attribute] of SII� (which must have such an [attribute])."
11000 	    */
11001 	    if (pctxt->targetNamespace == NULL) {
11002 		xmlSchemaCustomErr(ACTXT_CAST pctxt,
11003 		    XML_SCHEMAP_SRC_INCLUDE,
11004 		    node, NULL,
11005 		    "The target namespace of the included/redefined schema "
11006 		    "'%s' has to be absent, since the including/redefining "
11007 		    "schema has no target namespace",
11008 		    schemaLocation, NULL);
11009 		goto exit_error;
11010 	    } else if (!xmlStrEqual(bucket->origTargetNamespace,
11011 		pctxt->targetNamespace)) {
11012 		/* TODO: Change error function. */
11013 		xmlSchemaPCustomErrExt(pctxt,
11014 		    XML_SCHEMAP_SRC_INCLUDE,
11015 		    NULL, node,
11016 		    "The target namespace '%s' of the included/redefined "
11017 		    "schema '%s' differs from '%s' of the "
11018 		    "including/redefining schema",
11019 		    bucket->origTargetNamespace, schemaLocation,
11020 		    pctxt->targetNamespace);
11021 		goto exit_error;
11022 	    }
11023 	} else if (pctxt->targetNamespace != NULL) {
11024 	    /*
11025 	    * Chameleons: the original target namespace will
11026 	    * differ from the resulting namespace.
11027 	    */
11028 	    isChameleon = 1;
11029 	    if (bucket->parsed &&
11030 		(bucket->targetNamespace != pctxt->targetNamespace)) {
11031 		/*
11032 		* This is a sanity check, I dunno yet if this can happen.
11033 		*/
11034 		PERROR_INT("xmlSchemaParseIncludeOrRedefine",
11035 		    "trying to use an already parsed schema for a "
11036 		    "different targetNamespace");
11037 		return(-1);
11038 	    }
11039 	    bucket->targetNamespace = pctxt->targetNamespace;
11040 	}
11041     }
11042     /*
11043     * Parse the schema.
11044     */
11045     if (bucket && (!bucket->parsed) && (bucket->doc != NULL)) {
11046 	if (isChameleon) {
11047 	    /* TODO: Get rid of this flag on the schema itself. */
11048 	    if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
11049 		schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11050 	    } else
11051 		wasChameleon = 1;
11052 	}
11053 	xmlSchemaParseNewDoc(pctxt, schema, bucket);
11054 	/* Restore chameleon flag. */
11055 	if (isChameleon && (!wasChameleon))
11056 	    schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11057     }
11058     /*
11059     * And now for the children...
11060     */
11061     child = node->children;
11062     if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11063 	/*
11064 	* Parse (simpleType | complexType | group | attributeGroup))*
11065 	*/
11066 	pctxt->redefined = bucket;
11067 	/*
11068 	* How to proceed if the redefined schema was not located?
11069 	*/
11070 	pctxt->isRedefine = 1;
11071 	while (IS_SCHEMA(child, "annotation") ||
11072 	    IS_SCHEMA(child, "simpleType") ||
11073 	    IS_SCHEMA(child, "complexType") ||
11074 	    IS_SCHEMA(child, "group") ||
11075 	    IS_SCHEMA(child, "attributeGroup")) {
11076 	    if (IS_SCHEMA(child, "annotation")) {
11077 		/*
11078 		* TODO: discard or not?
11079 		*/
11080 	    } else if (IS_SCHEMA(child, "simpleType")) {
11081 		xmlSchemaParseSimpleType(pctxt, schema, child, 1);
11082 	    } else if (IS_SCHEMA(child, "complexType")) {
11083 		xmlSchemaParseComplexType(pctxt, schema, child, 1);
11084 		/* hasRedefinitions = 1; */
11085 	    } else if (IS_SCHEMA(child, "group")) {
11086 		/* hasRedefinitions = 1; */
11087 		xmlSchemaParseModelGroupDefinition(pctxt,
11088 		    schema, child);
11089 	    } else if (IS_SCHEMA(child, "attributeGroup")) {
11090 		/* hasRedefinitions = 1; */
11091 		xmlSchemaParseAttributeGroupDefinition(pctxt, schema,
11092 		    child);
11093 	    }
11094 	    child = child->next;
11095 	}
11096 	pctxt->redefined = NULL;
11097 	pctxt->isRedefine = 0;
11098     } else {
11099 	if (IS_SCHEMA(child, "annotation")) {
11100 	    /*
11101 	    * TODO: discard or not?
11102 	    */
11103 	    child = child->next;
11104 	}
11105     }
11106     if (child != NULL) {
11107 	res = XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED;
11108 	if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11109 	    xmlSchemaPContentErr(pctxt, res,
11110 		NULL, node, child, NULL,
11111 		"(annotation | (simpleType | complexType | group | attributeGroup))*");
11112 	} else {
11113 	     xmlSchemaPContentErr(pctxt, res,
11114 		NULL, node, child, NULL,
11115 		"(annotation?)");
11116 	}
11117     }
11118     return(res);
11119 
11120 exit_error:
11121     return(pctxt->err);
11122 }
11123 
11124 static int
xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)11125 xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11126                        xmlNodePtr node)
11127 {
11128     int res;
11129 #ifndef ENABLE_REDEFINE
11130     TODO
11131     return(0);
11132 #endif
11133     res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11134 	XML_SCHEMA_SCHEMA_REDEFINE);
11135     if (res != 0)
11136 	return(res);
11137     return(0);
11138 }
11139 
11140 static int
xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)11141 xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11142                        xmlNodePtr node)
11143 {
11144     int res;
11145 
11146     res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11147 	XML_SCHEMA_SCHEMA_INCLUDE);
11148     if (res != 0)
11149 	return(res);
11150     return(0);
11151 }
11152 
11153 /**
11154  * xmlSchemaParseModelGroup:
11155  * @ctxt:  a schema validation context
11156  * @schema:  the schema being built
11157  * @node:  a subtree containing XML Schema informations
11158  * @type: the "compositor" type
11159  * @particleNeeded: if a a model group with a particle
11160  *
11161  * parse a XML schema Sequence definition.
11162  * Applies parts of:
11163  *   Schema Representation Constraint:
11164  *     Redefinition Constraints and Semantics (src-redefine)
11165  *     (6.1), (6.1.1), (6.1.2)
11166  *
11167  *   Schema Component Constraint:
11168  *     All Group Limited (cos-all-limited) (2)
11169  *     TODO: Actually this should go to component-level checks,
11170  *     but is done here due to performance. Move it to an other layer
11171  *     is schema construction via an API is implemented.
11172  *
11173  * *WARNING* this interface is highly subject to change
11174  *
11175  * Returns -1 in case of error, 0 if the declaration is improper and
11176  *         1 in case of success.
11177  */
11178 static xmlSchemaTreeItemPtr
xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlSchemaTypeType type,int withParticle)11179 xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11180 			 xmlNodePtr node, xmlSchemaTypeType type,
11181 			 int withParticle)
11182 {
11183     xmlSchemaModelGroupPtr item;
11184     xmlSchemaParticlePtr particle = NULL;
11185     xmlNodePtr child = NULL;
11186     xmlAttrPtr attr;
11187     int min = 1, max = 1, isElemRef, hasRefs = 0;
11188 
11189     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11190         return (NULL);
11191     /*
11192     * Create a model group with the given compositor.
11193     */
11194     item = xmlSchemaAddModelGroup(ctxt, schema, type, node);
11195     if (item == NULL)
11196 	return (NULL);
11197 
11198     if (withParticle) {
11199 	if (type == XML_SCHEMA_TYPE_ALL) {
11200 	    min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
11201 	    max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
11202 	} else {
11203 	    /* choice + sequence */
11204 	    min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
11205 	    max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
11206 		"(xs:nonNegativeInteger | unbounded)");
11207 	}
11208 	xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
11209 	/*
11210 	* Create a particle
11211 	*/
11212 	particle = xmlSchemaAddParticle(ctxt, node, min, max);
11213 	if (particle == NULL)
11214 	    return (NULL);
11215 	particle->children = (xmlSchemaTreeItemPtr) item;
11216 	/*
11217 	* Check for illegal attributes.
11218 	*/
11219 	attr = node->properties;
11220 	while (attr != NULL) {
11221 	    if (attr->ns == NULL) {
11222 		if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11223 		    (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
11224 		    (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
11225 		    xmlSchemaPIllegalAttrErr(ctxt,
11226 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11227 		}
11228 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11229 		xmlSchemaPIllegalAttrErr(ctxt,
11230 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11231 	    }
11232 	    attr = attr->next;
11233 	}
11234     } else {
11235 	/*
11236 	* Check for illegal attributes.
11237 	*/
11238 	attr = node->properties;
11239 	while (attr != NULL) {
11240 	    if (attr->ns == NULL) {
11241 		if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
11242 		    xmlSchemaPIllegalAttrErr(ctxt,
11243 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11244 		}
11245 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11246 		xmlSchemaPIllegalAttrErr(ctxt,
11247 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11248 	    }
11249 	    attr = attr->next;
11250 	}
11251     }
11252 
11253     /*
11254     * Extract and validate attributes.
11255     */
11256     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11257     /*
11258     * And now for the children...
11259     */
11260     child = node->children;
11261     if (IS_SCHEMA(child, "annotation")) {
11262         item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
11263         child = child->next;
11264     }
11265     if (type == XML_SCHEMA_TYPE_ALL) {
11266 	xmlSchemaParticlePtr part, last = NULL;
11267 
11268 	while (IS_SCHEMA(child, "element")) {
11269 	    part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
11270 		schema, child, &isElemRef, 0);
11271 	    /*
11272 	    * SPEC cos-all-limited (2)
11273 	    * "The {max occurs} of all the particles in the {particles}
11274 	    * of the ('all') group must be 0 or 1.
11275 	    */
11276 	    if (part != NULL) {
11277 		if (isElemRef)
11278 		    hasRefs++;
11279 		if (part->minOccurs > 1) {
11280 		    xmlSchemaPCustomErr(ctxt,
11281 			XML_SCHEMAP_COS_ALL_LIMITED,
11282 			NULL, child,
11283 			"Invalid value for minOccurs (must be 0 or 1)",
11284 			NULL);
11285 		    /* Reset to 1. */
11286 		    part->minOccurs = 1;
11287 		}
11288 		if (part->maxOccurs > 1) {
11289 		    xmlSchemaPCustomErr(ctxt,
11290 			XML_SCHEMAP_COS_ALL_LIMITED,
11291 			NULL, child,
11292 			"Invalid value for maxOccurs (must be 0 or 1)",
11293 			NULL);
11294 		    /* Reset to 1. */
11295 		    part->maxOccurs = 1;
11296 		}
11297 		if (last == NULL)
11298 		    item->children = (xmlSchemaTreeItemPtr) part;
11299 		else
11300 		    last->next = (xmlSchemaTreeItemPtr) part;
11301 		last = part;
11302 	    }
11303 	    child = child->next;
11304 	}
11305 	if (child != NULL) {
11306 	    xmlSchemaPContentErr(ctxt,
11307 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11308 		NULL, node, child, NULL,
11309 		"(annotation?, (annotation?, element*)");
11310 	}
11311     } else {
11312 	/* choice + sequence */
11313 	xmlSchemaTreeItemPtr part = NULL, last = NULL;
11314 
11315 	while ((IS_SCHEMA(child, "element")) ||
11316 	    (IS_SCHEMA(child, "group")) ||
11317 	    (IS_SCHEMA(child, "any")) ||
11318 	    (IS_SCHEMA(child, "choice")) ||
11319 	    (IS_SCHEMA(child, "sequence"))) {
11320 
11321 	    if (IS_SCHEMA(child, "element")) {
11322 		part = (xmlSchemaTreeItemPtr)
11323 		    xmlSchemaParseElement(ctxt, schema, child, &isElemRef, 0);
11324 		if (part && isElemRef)
11325 		    hasRefs++;
11326 	    } else if (IS_SCHEMA(child, "group")) {
11327 		part =
11328 		    xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11329 		if (part != NULL)
11330 		    hasRefs++;
11331 		/*
11332 		* Handle redefinitions.
11333 		*/
11334 		if (ctxt->isRedefine && ctxt->redef &&
11335 		    (ctxt->redef->item->type == XML_SCHEMA_TYPE_GROUP) &&
11336 		    part && part->children)
11337 		{
11338 		    if ((xmlSchemaGetQNameRefName(part->children) ==
11339 			    ctxt->redef->refName) &&
11340 			(xmlSchemaGetQNameRefTargetNs(part->children) ==
11341 			    ctxt->redef->refTargetNs))
11342 		    {
11343 			/*
11344 			* SPEC src-redefine:
11345 			* (6.1) "If it has a <group> among its contents at
11346 			* some level the �actual value� of whose ref
11347 			* [attribute] is the same as the �actual value� of
11348 			* its own name attribute plus target namespace, then
11349 			* all of the following must be true:"
11350 			* (6.1.1) "It must have exactly one such group."
11351 			*/
11352 			if (ctxt->redefCounter != 0) {
11353 			    xmlChar *str = NULL;
11354 
11355 			    xmlSchemaCustomErr(ACTXT_CAST ctxt,
11356 				XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11357 				"The redefining model group definition "
11358 				"'%s' must not contain more than one "
11359 				"reference to the redefined definition",
11360 				xmlSchemaFormatQName(&str,
11361 				    ctxt->redef->refTargetNs,
11362 				    ctxt->redef->refName),
11363 				NULL);
11364 			    FREE_AND_NULL(str)
11365 			    part = NULL;
11366 			} else if (((WXS_PARTICLE(part))->minOccurs != 1) ||
11367 			    ((WXS_PARTICLE(part))->maxOccurs != 1))
11368 			{
11369 			    xmlChar *str = NULL;
11370 			    /*
11371 			    * SPEC src-redefine:
11372 			    * (6.1.2) "The �actual value� of both that
11373 			    * group's minOccurs and maxOccurs [attribute]
11374 			    * must be 1 (or �absent�).
11375 			    */
11376 			    xmlSchemaCustomErr(ACTXT_CAST ctxt,
11377 				XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11378 				"The redefining model group definition "
11379 				"'%s' must not contain a reference to the "
11380 				"redefined definition with a "
11381 				"maxOccurs/minOccurs other than 1",
11382 				xmlSchemaFormatQName(&str,
11383 				    ctxt->redef->refTargetNs,
11384 				    ctxt->redef->refName),
11385 				NULL);
11386 			    FREE_AND_NULL(str)
11387 			    part = NULL;
11388 			}
11389 			ctxt->redef->reference = WXS_BASIC_CAST part;
11390 			ctxt->redefCounter++;
11391 		    }
11392 		}
11393 	    } else if (IS_SCHEMA(child, "any")) {
11394 		part = (xmlSchemaTreeItemPtr)
11395 		    xmlSchemaParseAny(ctxt, schema, child);
11396 	    } else if (IS_SCHEMA(child, "choice")) {
11397 		part = xmlSchemaParseModelGroup(ctxt, schema, child,
11398 		    XML_SCHEMA_TYPE_CHOICE, 1);
11399 	    } else if (IS_SCHEMA(child, "sequence")) {
11400 		part = xmlSchemaParseModelGroup(ctxt, schema, child,
11401 		    XML_SCHEMA_TYPE_SEQUENCE, 1);
11402 	    }
11403 	    if (part != NULL) {
11404 		if (last == NULL)
11405 		    item->children = part;
11406 		else
11407 		    last->next = part;
11408 		last = part;
11409 	    }
11410 	    child = child->next;
11411 	}
11412 	if (child != NULL) {
11413 	    xmlSchemaPContentErr(ctxt,
11414 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11415 		NULL, node, child, NULL,
11416 		"(annotation?, (element | group | choice | sequence | any)*)");
11417 	}
11418     }
11419     if ((max == 0) && (min == 0))
11420 	return (NULL);
11421     if (hasRefs) {
11422 	/*
11423 	* We need to resolve references.
11424 	*/
11425 	WXS_ADD_PENDING(ctxt, item);
11426     }
11427     if (withParticle)
11428 	return ((xmlSchemaTreeItemPtr) particle);
11429     else
11430 	return ((xmlSchemaTreeItemPtr) item);
11431 }
11432 
11433 /**
11434  * xmlSchemaParseRestriction:
11435  * @ctxt:  a schema validation context
11436  * @schema:  the schema being built
11437  * @node:  a subtree containing XML Schema informations
11438  *
11439  * parse a XML schema Restriction definition
11440  * *WARNING* this interface is highly subject to change
11441  *
11442  * Returns the type definition or NULL in case of error
11443  */
11444 static xmlSchemaTypePtr
xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlSchemaTypeType parentType)11445 xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11446                           xmlNodePtr node, xmlSchemaTypeType parentType)
11447 {
11448     xmlSchemaTypePtr type;
11449     xmlNodePtr child = NULL;
11450     xmlAttrPtr attr;
11451 
11452     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11453         return (NULL);
11454     /* Not a component, don't create it. */
11455     type = ctxt->ctxtType;
11456     type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
11457 
11458     /*
11459     * Check for illegal attributes.
11460     */
11461     attr = node->properties;
11462     while (attr != NULL) {
11463 	if (attr->ns == NULL) {
11464 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11465 		(!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11466 		xmlSchemaPIllegalAttrErr(ctxt,
11467 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11468 	    }
11469 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11470 	    xmlSchemaPIllegalAttrErr(ctxt,
11471 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11472 	}
11473 	attr = attr->next;
11474     }
11475     /*
11476     * Extract and validate attributes.
11477     */
11478     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11479     /*
11480     * Attribute
11481     */
11482     /*
11483     * Extract the base type. The "base" attribute is mandatory if inside
11484     * a complex type or if redefining.
11485     *
11486     * SPEC (1.2) "...otherwise (<restriction> has no <simpleType> "
11487     * among its [children]), the simple type definition which is
11488     * the {content type} of the type definition �resolved� to by
11489     * the �actual value� of the base [attribute]"
11490     */
11491     if (xmlSchemaPValAttrQName(ctxt, schema, NULL, node, "base",
11492 	&(type->baseNs), &(type->base)) == 0)
11493     {
11494 	if ((type->base == NULL) && (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
11495 	    xmlSchemaPMissingAttrErr(ctxt,
11496 		XML_SCHEMAP_S4S_ATTR_MISSING,
11497 		NULL, node, "base", NULL);
11498 	} else if ((ctxt->isRedefine) &&
11499 	    (type->flags & XML_SCHEMAS_TYPE_GLOBAL))
11500 	{
11501 	    if (type->base == NULL) {
11502 		xmlSchemaPMissingAttrErr(ctxt,
11503 		    XML_SCHEMAP_S4S_ATTR_MISSING,
11504 		    NULL, node, "base", NULL);
11505 	    } else if ((! xmlStrEqual(type->base, type->name)) ||
11506 		(! xmlStrEqual(type->baseNs, type->targetNamespace)))
11507 	    {
11508 		xmlChar *str1 = NULL, *str2 = NULL;
11509 		/*
11510 		* REDEFINE: SPEC src-redefine (5)
11511 		* "Within the [children], each <simpleType> must have a
11512 		* <restriction> among its [children] ... the �actual value� of
11513 		* whose base [attribute] must be the same as the �actual value�
11514 		* of its own name attribute plus target namespace;"
11515 		*/
11516 		xmlSchemaPCustomErrExt(ctxt, XML_SCHEMAP_SRC_REDEFINE,
11517 		    NULL, node, "This is a redefinition, but the QName "
11518 		    "value '%s' of the 'base' attribute does not match the "
11519 		    "type's designation '%s'",
11520 		    xmlSchemaFormatQName(&str1, type->baseNs, type->base),
11521 		    xmlSchemaFormatQName(&str2, type->targetNamespace,
11522 			type->name), NULL);
11523 		FREE_AND_NULL(str1);
11524 		FREE_AND_NULL(str2);
11525 		/* Avoid confusion and erase the values. */
11526 		type->base = NULL;
11527 		type->baseNs = NULL;
11528 	    }
11529 	}
11530     }
11531     /*
11532     * And now for the children...
11533     */
11534     child = node->children;
11535     if (IS_SCHEMA(child, "annotation")) {
11536 	/*
11537 	* Add the annotation to the simple type ancestor.
11538 	*/
11539 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11540 	    xmlSchemaParseAnnotation(ctxt, child, 1));
11541         child = child->next;
11542     }
11543     if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
11544 	/*
11545 	* Corresponds to <simpleType><restriction><simpleType>.
11546 	*/
11547 	if (IS_SCHEMA(child, "simpleType")) {
11548 	    if (type->base != NULL) {
11549 		/*
11550 		* src-restriction-base-or-simpleType
11551 		* Either the base [attribute] or the simpleType [child] of the
11552 		* <restriction> element must be present, but not both.
11553 		*/
11554 		xmlSchemaPContentErr(ctxt,
11555 		    XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11556 		    NULL, node, child,
11557 		    "The attribute 'base' and the <simpleType> child are "
11558 		    "mutually exclusive", NULL);
11559 	    } else {
11560 		type->baseType = (xmlSchemaTypePtr)
11561 		    xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11562 	    }
11563 	    child = child->next;
11564 	} else if (type->base == NULL) {
11565 	    xmlSchemaPContentErr(ctxt,
11566 		XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11567 		NULL, node, child,
11568 		"Either the attribute 'base' or a <simpleType> child "
11569 		"must be present", NULL);
11570 	}
11571     } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11572 	/*
11573 	* Corresponds to <complexType><complexContent><restriction>...
11574 	* followed by:
11575 	*
11576 	* Model groups <all>, <choice> and <sequence>.
11577 	*/
11578 	if (IS_SCHEMA(child, "all")) {
11579 	    type->subtypes = (xmlSchemaTypePtr)
11580 		xmlSchemaParseModelGroup(ctxt, schema, child,
11581 		    XML_SCHEMA_TYPE_ALL, 1);
11582 	    child = child->next;
11583 	} else if (IS_SCHEMA(child, "choice")) {
11584 	    type->subtypes = (xmlSchemaTypePtr)
11585 		xmlSchemaParseModelGroup(ctxt,
11586 		    schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
11587 	    child = child->next;
11588 	} else if (IS_SCHEMA(child, "sequence")) {
11589 	    type->subtypes = (xmlSchemaTypePtr)
11590 		xmlSchemaParseModelGroup(ctxt, schema, child,
11591 		    XML_SCHEMA_TYPE_SEQUENCE, 1);
11592 	    child = child->next;
11593 	/*
11594 	* Model group reference <group>.
11595 	*/
11596 	} else if (IS_SCHEMA(child, "group")) {
11597 	    type->subtypes = (xmlSchemaTypePtr)
11598 		xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11599 	    /*
11600 	    * Note that the reference will be resolved in
11601 	    * xmlSchemaResolveTypeReferences();
11602 	    */
11603 	    child = child->next;
11604 	}
11605     } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11606 	/*
11607 	* Corresponds to <complexType><simpleContent><restriction>...
11608 	*
11609 	* "1.1 the simple type definition corresponding to the <simpleType>
11610 	* among the [children] of <restriction> if there is one;"
11611 	*/
11612 	if (IS_SCHEMA(child, "simpleType")) {
11613 	    /*
11614 	    * We will store the to-be-restricted simple type in
11615 	    * type->contentTypeDef *temporarily*.
11616 	    */
11617 	    type->contentTypeDef = (xmlSchemaTypePtr)
11618 		xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11619 	    if ( type->contentTypeDef == NULL)
11620 		return (NULL);
11621 	    child = child->next;
11622 	}
11623     }
11624 
11625     if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
11626 	(parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
11627 	xmlSchemaFacetPtr facet, lastfacet = NULL;
11628 	/*
11629 	* Corresponds to <complexType><simpleContent><restriction>...
11630 	* <simpleType><restriction>...
11631 	*/
11632 
11633 	/*
11634 	* Add the facets to the simple type ancestor.
11635 	*/
11636 	/*
11637 	* TODO: Datatypes: 4.1.3 Constraints on XML Representation of
11638 	* Simple Type Definition Schema Representation Constraint:
11639 	* *Single Facet Value*
11640 	*/
11641 	while ((IS_SCHEMA(child, "minInclusive")) ||
11642 	    (IS_SCHEMA(child, "minExclusive")) ||
11643 	    (IS_SCHEMA(child, "maxInclusive")) ||
11644 	    (IS_SCHEMA(child, "maxExclusive")) ||
11645 	    (IS_SCHEMA(child, "totalDigits")) ||
11646 	    (IS_SCHEMA(child, "fractionDigits")) ||
11647 	    (IS_SCHEMA(child, "pattern")) ||
11648 	    (IS_SCHEMA(child, "enumeration")) ||
11649 	    (IS_SCHEMA(child, "whiteSpace")) ||
11650 	    (IS_SCHEMA(child, "length")) ||
11651 	    (IS_SCHEMA(child, "maxLength")) ||
11652 	    (IS_SCHEMA(child, "minLength"))) {
11653 	    facet = xmlSchemaParseFacet(ctxt, schema, child);
11654 	    if (facet != NULL) {
11655 		if (lastfacet == NULL)
11656 		    type->facets = facet;
11657 		else
11658 		    lastfacet->next = facet;
11659 		lastfacet = facet;
11660 		lastfacet->next = NULL;
11661 	    }
11662 	    child = child->next;
11663 	}
11664 	/*
11665 	* Create links for derivation and validation.
11666 	*/
11667 	if (type->facets != NULL) {
11668 	    xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
11669 
11670 	    facet = type->facets;
11671 	    do {
11672 		facetLink = (xmlSchemaFacetLinkPtr)
11673 		    xmlMalloc(sizeof(xmlSchemaFacetLink));
11674 		if (facetLink == NULL) {
11675 		    xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
11676 		    xmlFree(facetLink);
11677 		    return (NULL);
11678 		}
11679 		facetLink->facet = facet;
11680 		facetLink->next = NULL;
11681 		if (lastFacetLink == NULL)
11682 		    type->facetSet = facetLink;
11683 		else
11684 		    lastFacetLink->next = facetLink;
11685 		lastFacetLink = facetLink;
11686 		facet = facet->next;
11687 	    } while (facet != NULL);
11688 	}
11689     }
11690     if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
11691 	/*
11692 	* Attribute uses/declarations.
11693 	*/
11694 	if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11695 	    (xmlSchemaItemListPtr *) &(type->attrUses),
11696 	    XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
11697 	    return(NULL);
11698 	/*
11699 	* Attribute wildcard.
11700 	*/
11701 	if (IS_SCHEMA(child, "anyAttribute")) {
11702 	    type->attributeWildcard =
11703 		xmlSchemaParseAnyAttribute(ctxt, schema, child);
11704 	    child = child->next;
11705 	}
11706     }
11707     if (child != NULL) {
11708 	if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11709 	    xmlSchemaPContentErr(ctxt,
11710 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11711 		NULL, node, child, NULL,
11712 		"annotation?, (group | all | choice | sequence)?, "
11713 		"((attribute | attributeGroup)*, anyAttribute?))");
11714 	} else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11715 	     xmlSchemaPContentErr(ctxt,
11716 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11717 		NULL, node, child, NULL,
11718 		"(annotation?, (simpleType?, (minExclusive | minInclusive | "
11719 		"maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11720 		"length | minLength | maxLength | enumeration | whiteSpace | "
11721 		"pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
11722 	} else {
11723 	    /* Simple type */
11724 	    xmlSchemaPContentErr(ctxt,
11725 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11726 		NULL, node, child, NULL,
11727 		"(annotation?, (simpleType?, (minExclusive | minInclusive | "
11728 		"maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11729 		"length | minLength | maxLength | enumeration | whiteSpace | "
11730 		"pattern)*))");
11731 	}
11732     }
11733     return (NULL);
11734 }
11735 
11736 /**
11737  * xmlSchemaParseExtension:
11738  * @ctxt:  a schema validation context
11739  * @schema:  the schema being built
11740  * @node:  a subtree containing XML Schema informations
11741  *
11742  * Parses an <extension>, which is found inside a
11743  * <simpleContent> or <complexContent>.
11744  * *WARNING* this interface is highly subject to change.
11745  *
11746  * TODO: Returns the type definition or NULL in case of error
11747  */
11748 static xmlSchemaTypePtr
xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlSchemaTypeType parentType)11749 xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11750                         xmlNodePtr node, xmlSchemaTypeType parentType)
11751 {
11752     xmlSchemaTypePtr type;
11753     xmlNodePtr child = NULL;
11754     xmlAttrPtr attr;
11755 
11756     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11757         return (NULL);
11758     /* Not a component, don't create it. */
11759     type = ctxt->ctxtType;
11760     type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
11761 
11762     /*
11763     * Check for illegal attributes.
11764     */
11765     attr = node->properties;
11766     while (attr != NULL) {
11767 	if (attr->ns == NULL) {
11768 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11769 		(!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11770 		xmlSchemaPIllegalAttrErr(ctxt,
11771 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11772 	    }
11773 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11774 	    xmlSchemaPIllegalAttrErr(ctxt,
11775 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11776 	}
11777 	attr = attr->next;
11778     }
11779 
11780     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11781 
11782     /*
11783     * Attribute "base" - mandatory.
11784     */
11785     if ((xmlSchemaPValAttrQName(ctxt, schema, NULL, node,
11786 	"base", &(type->baseNs), &(type->base)) == 0) &&
11787 	(type->base == NULL)) {
11788 	xmlSchemaPMissingAttrErr(ctxt,
11789 	    XML_SCHEMAP_S4S_ATTR_MISSING,
11790 	    NULL, node, "base", NULL);
11791     }
11792     /*
11793     * And now for the children...
11794     */
11795     child = node->children;
11796     if (IS_SCHEMA(child, "annotation")) {
11797 	/*
11798 	* Add the annotation to the type ancestor.
11799 	*/
11800 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11801 	    xmlSchemaParseAnnotation(ctxt, child, 1));
11802         child = child->next;
11803     }
11804     if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11805 	/*
11806 	* Corresponds to <complexType><complexContent><extension>... and:
11807 	*
11808 	* Model groups <all>, <choice>, <sequence> and <group>.
11809 	*/
11810 	if (IS_SCHEMA(child, "all")) {
11811 	    type->subtypes = (xmlSchemaTypePtr)
11812 		xmlSchemaParseModelGroup(ctxt, schema,
11813 		    child, XML_SCHEMA_TYPE_ALL, 1);
11814 	    child = child->next;
11815 	} else if (IS_SCHEMA(child, "choice")) {
11816 	    type->subtypes = (xmlSchemaTypePtr)
11817 		xmlSchemaParseModelGroup(ctxt, schema,
11818 		    child, XML_SCHEMA_TYPE_CHOICE, 1);
11819 	    child = child->next;
11820 	} else if (IS_SCHEMA(child, "sequence")) {
11821 	    type->subtypes = (xmlSchemaTypePtr)
11822 		xmlSchemaParseModelGroup(ctxt, schema,
11823 		child, XML_SCHEMA_TYPE_SEQUENCE, 1);
11824 	    child = child->next;
11825 	} else if (IS_SCHEMA(child, "group")) {
11826 	    type->subtypes = (xmlSchemaTypePtr)
11827 		xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11828 	    /*
11829 	    * Note that the reference will be resolved in
11830 	    * xmlSchemaResolveTypeReferences();
11831 	    */
11832 	    child = child->next;
11833 	}
11834     }
11835     if (child != NULL) {
11836 	/*
11837 	* Attribute uses/declarations.
11838 	*/
11839 	if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11840 	    (xmlSchemaItemListPtr *) &(type->attrUses),
11841 	    XML_SCHEMA_TYPE_EXTENSION, NULL) == -1)
11842 	    return(NULL);
11843 	/*
11844 	* Attribute wildcard.
11845 	*/
11846 	if (IS_SCHEMA(child, "anyAttribute")) {
11847 	    ctxt->ctxtType->attributeWildcard =
11848 		xmlSchemaParseAnyAttribute(ctxt, schema, child);
11849 	    child = child->next;
11850 	}
11851     }
11852     if (child != NULL) {
11853 	if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11854 	    /* Complex content extension. */
11855 	    xmlSchemaPContentErr(ctxt,
11856 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11857 		NULL, node, child, NULL,
11858 		"(annotation?, ((group | all | choice | sequence)?, "
11859 		"((attribute | attributeGroup)*, anyAttribute?)))");
11860 	} else {
11861 	    /* Simple content extension. */
11862 	    xmlSchemaPContentErr(ctxt,
11863 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11864 		NULL, node, child, NULL,
11865 		"(annotation?, ((attribute | attributeGroup)*, "
11866 		"anyAttribute?))");
11867 	}
11868     }
11869     return (NULL);
11870 }
11871 
11872 /**
11873  * xmlSchemaParseSimpleContent:
11874  * @ctxt:  a schema validation context
11875  * @schema:  the schema being built
11876  * @node:  a subtree containing XML Schema informations
11877  *
11878  * parse a XML schema SimpleContent definition
11879  * *WARNING* this interface is highly subject to change
11880  *
11881  * Returns the type definition or NULL in case of error
11882  */
11883 static int
xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int * hasRestrictionOrExtension)11884 xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
11885                             xmlSchemaPtr schema, xmlNodePtr node,
11886 			    int *hasRestrictionOrExtension)
11887 {
11888     xmlSchemaTypePtr type;
11889     xmlNodePtr child = NULL;
11890     xmlAttrPtr attr;
11891 
11892     if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11893 	(hasRestrictionOrExtension == NULL))
11894         return (-1);
11895     *hasRestrictionOrExtension = 0;
11896     /* Not a component, don't create it. */
11897     type = ctxt->ctxtType;
11898     type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
11899     /*
11900     * Check for illegal attributes.
11901     */
11902     attr = node->properties;
11903     while (attr != NULL) {
11904 	if (attr->ns == NULL) {
11905 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
11906 		xmlSchemaPIllegalAttrErr(ctxt,
11907 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11908 	    }
11909 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11910 	    xmlSchemaPIllegalAttrErr(ctxt,
11911 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11912 	}
11913 	attr = attr->next;
11914     }
11915 
11916     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11917 
11918     /*
11919     * And now for the children...
11920     */
11921     child = node->children;
11922     if (IS_SCHEMA(child, "annotation")) {
11923 	/*
11924 	* Add the annotation to the complex type ancestor.
11925 	*/
11926 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11927 	    xmlSchemaParseAnnotation(ctxt, child, 1));
11928         child = child->next;
11929     }
11930     if (child == NULL) {
11931 	xmlSchemaPContentErr(ctxt,
11932 	    XML_SCHEMAP_S4S_ELEM_MISSING,
11933 	    NULL, node, NULL, NULL,
11934 	    "(annotation?, (restriction | extension))");
11935     }
11936     if (child == NULL) {
11937 	xmlSchemaPContentErr(ctxt,
11938 	    XML_SCHEMAP_S4S_ELEM_MISSING,
11939 	    NULL, node, NULL, NULL,
11940 	    "(annotation?, (restriction | extension))");
11941     }
11942     if (IS_SCHEMA(child, "restriction")) {
11943         xmlSchemaParseRestriction(ctxt, schema, child,
11944 	    XML_SCHEMA_TYPE_SIMPLE_CONTENT);
11945 	(*hasRestrictionOrExtension) = 1;
11946         child = child->next;
11947     } else if (IS_SCHEMA(child, "extension")) {
11948         xmlSchemaParseExtension(ctxt, schema, child,
11949 	    XML_SCHEMA_TYPE_SIMPLE_CONTENT);
11950 	(*hasRestrictionOrExtension) = 1;
11951         child = child->next;
11952     }
11953     if (child != NULL) {
11954 	xmlSchemaPContentErr(ctxt,
11955 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11956 	    NULL, node, child, NULL,
11957 	    "(annotation?, (restriction | extension))");
11958     }
11959     return (0);
11960 }
11961 
11962 /**
11963  * xmlSchemaParseComplexContent:
11964  * @ctxt:  a schema validation context
11965  * @schema:  the schema being built
11966  * @node:  a subtree containing XML Schema informations
11967  *
11968  * parse a XML schema ComplexContent definition
11969  * *WARNING* this interface is highly subject to change
11970  *
11971  * Returns the type definition or NULL in case of error
11972  */
11973 static int
xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int * hasRestrictionOrExtension)11974 xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
11975                              xmlSchemaPtr schema, xmlNodePtr node,
11976 			     int *hasRestrictionOrExtension)
11977 {
11978     xmlSchemaTypePtr type;
11979     xmlNodePtr child = NULL;
11980     xmlAttrPtr attr;
11981 
11982     if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11983 	(hasRestrictionOrExtension == NULL))
11984         return (-1);
11985     *hasRestrictionOrExtension = 0;
11986     /* Not a component, don't create it. */
11987     type = ctxt->ctxtType;
11988     /*
11989     * Check for illegal attributes.
11990     */
11991     attr = node->properties;
11992     while (attr != NULL) {
11993 	if (attr->ns == NULL) {
11994 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11995 		(!xmlStrEqual(attr->name, BAD_CAST "mixed")))
11996 	    {
11997 		xmlSchemaPIllegalAttrErr(ctxt,
11998 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11999 	    }
12000 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12001 	    xmlSchemaPIllegalAttrErr(ctxt,
12002 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12003 	}
12004 	attr = attr->next;
12005     }
12006 
12007     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12008 
12009     /*
12010     * Set the 'mixed' on the complex type ancestor.
12011     */
12012     if (xmlGetBooleanProp(ctxt, node, "mixed", 0))  {
12013 	if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
12014 	    type->flags |= XML_SCHEMAS_TYPE_MIXED;
12015     }
12016     child = node->children;
12017     if (IS_SCHEMA(child, "annotation")) {
12018 	/*
12019 	* Add the annotation to the complex type ancestor.
12020 	*/
12021 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
12022 	    xmlSchemaParseAnnotation(ctxt, child, 1));
12023         child = child->next;
12024     }
12025     if (child == NULL) {
12026 	xmlSchemaPContentErr(ctxt,
12027 	    XML_SCHEMAP_S4S_ELEM_MISSING,
12028 	    NULL, node, NULL,
12029 	    NULL, "(annotation?, (restriction | extension))");
12030     }
12031     if (child == NULL) {
12032 	xmlSchemaPContentErr(ctxt,
12033 	    XML_SCHEMAP_S4S_ELEM_MISSING,
12034 	    NULL, node, NULL,
12035 	    NULL, "(annotation?, (restriction | extension))");
12036     }
12037     if (IS_SCHEMA(child, "restriction")) {
12038         xmlSchemaParseRestriction(ctxt, schema, child,
12039 	    XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12040 	(*hasRestrictionOrExtension) = 1;
12041         child = child->next;
12042     } else if (IS_SCHEMA(child, "extension")) {
12043         xmlSchemaParseExtension(ctxt, schema, child,
12044 	    XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12045 	(*hasRestrictionOrExtension) = 1;
12046         child = child->next;
12047     }
12048     if (child != NULL) {
12049 	xmlSchemaPContentErr(ctxt,
12050 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12051 	    NULL, node, child,
12052 	    NULL, "(annotation?, (restriction | extension))");
12053     }
12054     return (0);
12055 }
12056 
12057 /**
12058  * xmlSchemaParseComplexType:
12059  * @ctxt:  a schema validation context
12060  * @schema:  the schema being built
12061  * @node:  a subtree containing XML Schema informations
12062  *
12063  * parse a XML schema Complex Type definition
12064  * *WARNING* this interface is highly subject to change
12065  *
12066  * Returns the type definition or NULL in case of error
12067  */
12068 static xmlSchemaTypePtr
xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int topLevel)12069 xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
12070                           xmlNodePtr node, int topLevel)
12071 {
12072     xmlSchemaTypePtr type, ctxtType;
12073     xmlNodePtr child = NULL;
12074     const xmlChar *name = NULL;
12075     xmlAttrPtr attr;
12076     const xmlChar *attrValue;
12077 #ifdef ENABLE_NAMED_LOCALS
12078     char buf[40];
12079 #endif
12080     int final = 0, block = 0, hasRestrictionOrExtension = 0;
12081 
12082 
12083     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
12084         return (NULL);
12085 
12086     ctxtType = ctxt->ctxtType;
12087 
12088     if (topLevel) {
12089 	attr = xmlSchemaGetPropNode(node, "name");
12090 	if (attr == NULL) {
12091 	    xmlSchemaPMissingAttrErr(ctxt,
12092 		XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
12093 	    return (NULL);
12094 	} else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
12095 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
12096 	    return (NULL);
12097 	}
12098     }
12099 
12100     if (topLevel == 0) {
12101 	/*
12102 	* Parse as local complex type definition.
12103 	*/
12104 #ifdef ENABLE_NAMED_LOCALS
12105         snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
12106 	type = xmlSchemaAddType(ctxt, schema,
12107 	    XML_SCHEMA_TYPE_COMPLEX,
12108 	    xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
12109 	    ctxt->targetNamespace, node, 0);
12110 #else
12111 	type = xmlSchemaAddType(ctxt, schema,
12112 	    XML_SCHEMA_TYPE_COMPLEX,
12113 	    NULL, ctxt->targetNamespace, node, 0);
12114 #endif
12115 	if (type == NULL)
12116 	    return (NULL);
12117 	name = type->name;
12118 	type->node = node;
12119 	type->type = XML_SCHEMA_TYPE_COMPLEX;
12120 	/*
12121 	* TODO: We need the target namespace.
12122 	*/
12123     } else {
12124 	/*
12125 	* Parse as global complex type definition.
12126 	*/
12127 	type = xmlSchemaAddType(ctxt, schema,
12128 	    XML_SCHEMA_TYPE_COMPLEX,
12129 	    name, ctxt->targetNamespace, node, 1);
12130 	if (type == NULL)
12131 	    return (NULL);
12132 	type->node = node;
12133 	type->type = XML_SCHEMA_TYPE_COMPLEX;
12134 	type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
12135     }
12136     type->targetNamespace = ctxt->targetNamespace;
12137     /*
12138     * Handle attributes.
12139     */
12140     attr = node->properties;
12141     while (attr != NULL) {
12142 	if (attr->ns == NULL) {
12143 	    if (xmlStrEqual(attr->name, BAD_CAST "id")) {
12144 		/*
12145 		* Attribute "id".
12146 		*/
12147 		xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12148 	    } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
12149 		/*
12150 		* Attribute "mixed".
12151 		*/
12152 		if (xmlSchemaPGetBoolNodeValue(ctxt,
12153 			NULL, (xmlNodePtr) attr))
12154 		    type->flags |= XML_SCHEMAS_TYPE_MIXED;
12155 	    } else if (topLevel) {
12156 		/*
12157 		* Attributes of global complex type definitions.
12158 		*/
12159 		if (xmlStrEqual(attr->name, BAD_CAST "name")) {
12160 		    /* Pass. */
12161 		} else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
12162 		    /*
12163 		    * Attribute "abstract".
12164 		    */
12165 		    if (xmlSchemaPGetBoolNodeValue(ctxt,
12166 			    NULL, (xmlNodePtr) attr))
12167 			type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
12168 		} else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
12169 		    /*
12170 		    * Attribute "final".
12171 		    */
12172 		    attrValue = xmlSchemaGetNodeContent(ctxt,
12173 			(xmlNodePtr) attr);
12174 		    if (xmlSchemaPValAttrBlockFinal(attrValue,
12175 			&(type->flags),
12176 			-1,
12177 			XML_SCHEMAS_TYPE_FINAL_EXTENSION,
12178 			XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
12179 			-1, -1, -1) != 0)
12180 		    {
12181 			xmlSchemaPSimpleTypeErr(ctxt,
12182 			    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12183 			    NULL, (xmlNodePtr) attr, NULL,
12184 			    "(#all | List of (extension | restriction))",
12185 			    attrValue, NULL, NULL, NULL);
12186 		    } else
12187 			final = 1;
12188 		} else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
12189 		    /*
12190 		    * Attribute "block".
12191 		    */
12192 		    attrValue = xmlSchemaGetNodeContent(ctxt,
12193 			(xmlNodePtr) attr);
12194 		    if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
12195 			-1,
12196 			XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
12197 			XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
12198 			-1, -1, -1) != 0) {
12199 			xmlSchemaPSimpleTypeErr(ctxt,
12200 			    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12201 			    NULL, (xmlNodePtr) attr, NULL,
12202 			    "(#all | List of (extension | restriction)) ",
12203 			    attrValue, NULL, NULL, NULL);
12204 		    } else
12205 			block = 1;
12206 		} else {
12207 			xmlSchemaPIllegalAttrErr(ctxt,
12208 			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12209 		}
12210 	    } else {
12211 		xmlSchemaPIllegalAttrErr(ctxt,
12212 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12213 	    }
12214 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12215 	    xmlSchemaPIllegalAttrErr(ctxt,
12216 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12217 	}
12218 	attr = attr->next;
12219     }
12220     if (! block) {
12221 	/*
12222 	* Apply default "block" values.
12223 	*/
12224 	if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
12225 	    type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
12226 	if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
12227 	    type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
12228     }
12229     if (! final) {
12230 	/*
12231 	* Apply default "block" values.
12232 	*/
12233 	if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
12234 	    type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
12235 	if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
12236 	    type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
12237     }
12238     /*
12239     * And now for the children...
12240     */
12241     child = node->children;
12242     if (IS_SCHEMA(child, "annotation")) {
12243         type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
12244         child = child->next;
12245     }
12246     ctxt->ctxtType = type;
12247     if (IS_SCHEMA(child, "simpleContent")) {
12248 	/*
12249 	* <complexType><simpleContent>...
12250 	* 3.4.3 : 2.2
12251 	* Specifying mixed='true' when the <simpleContent>
12252 	* alternative is chosen has no effect
12253 	*/
12254 	if (type->flags & XML_SCHEMAS_TYPE_MIXED)
12255 	    type->flags ^= XML_SCHEMAS_TYPE_MIXED;
12256         xmlSchemaParseSimpleContent(ctxt, schema, child,
12257 	    &hasRestrictionOrExtension);
12258         child = child->next;
12259     } else if (IS_SCHEMA(child, "complexContent")) {
12260 	/*
12261 	* <complexType><complexContent>...
12262 	*/
12263 	type->contentType = XML_SCHEMA_CONTENT_EMPTY;
12264         xmlSchemaParseComplexContent(ctxt, schema, child,
12265 	    &hasRestrictionOrExtension);
12266         child = child->next;
12267     } else {
12268 	/*
12269 	* E.g <complexType><sequence>... or <complexType><attribute>... etc.
12270 	*
12271 	* SPEC
12272 	* "...the third alternative (neither <simpleContent> nor
12273 	* <complexContent>) is chosen. This case is understood as shorthand
12274 	* for complex content restricting the �ur-type definition�, and the
12275 	* details of the mappings should be modified as necessary.
12276 	*/
12277 	type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12278 	type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
12279 	/*
12280 	* Parse model groups.
12281 	*/
12282         if (IS_SCHEMA(child, "all")) {
12283             type->subtypes = (xmlSchemaTypePtr)
12284 		xmlSchemaParseModelGroup(ctxt, schema, child,
12285 		    XML_SCHEMA_TYPE_ALL, 1);
12286             child = child->next;
12287         } else if (IS_SCHEMA(child, "choice")) {
12288             type->subtypes = (xmlSchemaTypePtr)
12289 		xmlSchemaParseModelGroup(ctxt, schema, child,
12290 		    XML_SCHEMA_TYPE_CHOICE, 1);
12291             child = child->next;
12292         } else if (IS_SCHEMA(child, "sequence")) {
12293             type->subtypes = (xmlSchemaTypePtr)
12294 		xmlSchemaParseModelGroup(ctxt, schema, child,
12295 		    XML_SCHEMA_TYPE_SEQUENCE, 1);
12296             child = child->next;
12297         } else if (IS_SCHEMA(child, "group")) {
12298             type->subtypes = (xmlSchemaTypePtr)
12299 		xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
12300 	    /*
12301 	    * Note that the reference will be resolved in
12302 	    * xmlSchemaResolveTypeReferences();
12303 	    */
12304             child = child->next;
12305         }
12306 	/*
12307 	* Parse attribute decls/refs.
12308 	*/
12309         if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
12310 	    (xmlSchemaItemListPtr *) &(type->attrUses),
12311 	    XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
12312 	    return(NULL);
12313 	/*
12314 	* Parse attribute wildcard.
12315 	*/
12316 	if (IS_SCHEMA(child, "anyAttribute")) {
12317 	    type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
12318 	    child = child->next;
12319 	}
12320     }
12321     if (child != NULL) {
12322 	xmlSchemaPContentErr(ctxt,
12323 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12324 	    NULL, node, child,
12325 	    NULL, "(annotation?, (simpleContent | complexContent | "
12326 	    "((group | all | choice | sequence)?, ((attribute | "
12327 	    "attributeGroup)*, anyAttribute?))))");
12328     }
12329     /*
12330     * REDEFINE: SPEC src-redefine (5)
12331     */
12332     if (topLevel && ctxt->isRedefine && (! hasRestrictionOrExtension)) {
12333 	xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
12334 	    NULL, node, "This is a redefinition, thus the "
12335 	    "<complexType> must have a <restriction> or <extension> "
12336 	    "grand-child", NULL);
12337     }
12338     ctxt->ctxtType = ctxtType;
12339     return (type);
12340 }
12341 
12342 /************************************************************************
12343  * 									*
12344  * 			Validating using Schemas			*
12345  * 									*
12346  ************************************************************************/
12347 
12348 /************************************************************************
12349  * 									*
12350  * 			Reading/Writing Schemas				*
12351  * 									*
12352  ************************************************************************/
12353 
12354 #if 0 /* Will be enabled if it is clear what options are needed. */
12355 /**
12356  * xmlSchemaParserCtxtSetOptions:
12357  * @ctxt:	a schema parser context
12358  * @options: a combination of xmlSchemaParserOption
12359  *
12360  * Sets the options to be used during the parse.
12361  *
12362  * Returns 0 in case of success, -1 in case of an
12363  * API error.
12364  */
12365 static int
12366 xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
12367 			      int options)
12368 
12369 {
12370     int i;
12371 
12372     if (ctxt == NULL)
12373 	return (-1);
12374     /*
12375     * WARNING: Change the start value if adding to the
12376     * xmlSchemaParseOption.
12377     */
12378     for (i = 1; i < (int) sizeof(int) * 8; i++) {
12379         if (options & 1<<i) {
12380 	    return (-1);
12381         }
12382     }
12383     ctxt->options = options;
12384     return (0);
12385 }
12386 
12387 /**
12388  * xmlSchemaValidCtxtGetOptions:
12389  * @ctxt: a schema parser context
12390  *
12391  * Returns the option combination of the parser context.
12392  */
12393 static int
12394 xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
12395 
12396 {
12397     if (ctxt == NULL)
12398 	return (-1);
12399     else
12400 	return (ctxt->options);
12401 }
12402 #endif
12403 
12404 /**
12405  * xmlSchemaNewParserCtxt:
12406  * @URL:  the location of the schema
12407  *
12408  * Create an XML Schemas parse context for that file/resource expected
12409  * to contain an XML Schemas file.
12410  *
12411  * Returns the parser context or NULL in case of error
12412  */
12413 xmlSchemaParserCtxtPtr
xmlSchemaNewParserCtxt(const char * URL)12414 xmlSchemaNewParserCtxt(const char *URL)
12415 {
12416     xmlSchemaParserCtxtPtr ret;
12417 
12418     if (URL == NULL)
12419         return (NULL);
12420 
12421     ret = xmlSchemaParserCtxtCreate();
12422     if (ret == NULL)
12423 	return(NULL);
12424     ret->dict = xmlDictCreate();
12425     ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
12426     return (ret);
12427 }
12428 
12429 /**
12430  * xmlSchemaNewMemParserCtxt:
12431  * @buffer:  a pointer to a char array containing the schemas
12432  * @size:  the size of the array
12433  *
12434  * Create an XML Schemas parse context for that memory buffer expected
12435  * to contain an XML Schemas file.
12436  *
12437  * Returns the parser context or NULL in case of error
12438  */
12439 xmlSchemaParserCtxtPtr
xmlSchemaNewMemParserCtxt(const char * buffer,int size)12440 xmlSchemaNewMemParserCtxt(const char *buffer, int size)
12441 {
12442     xmlSchemaParserCtxtPtr ret;
12443 
12444     if ((buffer == NULL) || (size <= 0))
12445         return (NULL);
12446     ret = xmlSchemaParserCtxtCreate();
12447     if (ret == NULL)
12448 	return(NULL);
12449     ret->buffer = buffer;
12450     ret->size = size;
12451     ret->dict = xmlDictCreate();
12452     return (ret);
12453 }
12454 
12455 /**
12456  * xmlSchemaNewDocParserCtxt:
12457  * @doc:  a preparsed document tree
12458  *
12459  * Create an XML Schemas parse context for that document.
12460  * NB. The document may be modified during the parsing process.
12461  *
12462  * Returns the parser context or NULL in case of error
12463  */
12464 xmlSchemaParserCtxtPtr
xmlSchemaNewDocParserCtxt(xmlDocPtr doc)12465 xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
12466 {
12467     xmlSchemaParserCtxtPtr ret;
12468 
12469     if (doc == NULL)
12470       return (NULL);
12471     ret = xmlSchemaParserCtxtCreate();
12472     if (ret == NULL)
12473 	return(NULL);
12474     ret->doc = doc;
12475     ret->dict = xmlDictCreate();
12476     /* The application has responsibility for the document */
12477     ret->preserve = 1;
12478 
12479     return (ret);
12480 }
12481 
12482 /**
12483  * xmlSchemaFreeParserCtxt:
12484  * @ctxt:  the schema parser context
12485  *
12486  * Free the resources associated to the schema parser context
12487  */
12488 void
xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)12489 xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
12490 {
12491     if (ctxt == NULL)
12492         return;
12493     if (ctxt->doc != NULL && !ctxt->preserve)
12494         xmlFreeDoc(ctxt->doc);
12495     if (ctxt->vctxt != NULL) {
12496 	xmlSchemaFreeValidCtxt(ctxt->vctxt);
12497     }
12498     if (ctxt->ownsConstructor && (ctxt->constructor != NULL)) {
12499 	xmlSchemaConstructionCtxtFree(ctxt->constructor);
12500 	ctxt->constructor = NULL;
12501 	ctxt->ownsConstructor = 0;
12502     }
12503     if (ctxt->attrProhibs != NULL)
12504 	xmlSchemaItemListFree(ctxt->attrProhibs);
12505     xmlDictFree(ctxt->dict);
12506     xmlFree(ctxt);
12507 }
12508 
12509 /************************************************************************
12510  *									*
12511  *			Building the content models			*
12512  *									*
12513  ************************************************************************/
12514 
12515 static void
xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,xmlSchemaParticlePtr particle,int counter,xmlAutomataStatePtr end)12516 xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
12517 	xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end)
12518 {
12519     xmlAutomataStatePtr start, tmp;
12520     xmlSchemaElementPtr elemDecl, member;
12521     xmlSchemaSubstGroupPtr substGroup;
12522     int i;
12523 
12524     elemDecl = (xmlSchemaElementPtr) particle->children;
12525     /*
12526     * Wrap the substitution group with a CHOICE.
12527     */
12528     start = pctxt->state;
12529     if (end == NULL)
12530 	end = xmlAutomataNewState(pctxt->am);
12531     substGroup = xmlSchemaSubstGroupGet(pctxt, elemDecl);
12532     if (substGroup == NULL) {
12533 	xmlSchemaPErr(pctxt, WXS_ITEM_NODE(particle),
12534 	    XML_SCHEMAP_INTERNAL,
12535 	    "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
12536 	    "declaration is marked having a subst. group but none "
12537 	    "available.\n", elemDecl->name, NULL);
12538 	return;
12539     }
12540     if (counter >= 0) {
12541 	/*
12542 	* NOTE that we put the declaration in, even if it's abstract.
12543 	* However, an error will be raised during *validation* if an element
12544 	* information item shall be validated against an abstract element
12545 	* declaration.
12546 	*/
12547 	tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter);
12548         xmlAutomataNewTransition2(pctxt->am, tmp, end,
12549 	            elemDecl->name, elemDecl->targetNamespace, elemDecl);
12550 	/*
12551 	* Add subst. group members.
12552 	*/
12553 	for (i = 0; i < substGroup->members->nbItems; i++) {
12554 	    member = (xmlSchemaElementPtr) substGroup->members->items[i];
12555             xmlAutomataNewTransition2(pctxt->am, tmp, end,
12556 		               member->name, member->targetNamespace, member);
12557 	}
12558     } else if (particle->maxOccurs == 1) {
12559 	/*
12560 	* NOTE that we put the declaration in, even if it's abstract,
12561 	*/
12562 	xmlAutomataNewEpsilon(pctxt->am,
12563 	    xmlAutomataNewTransition2(pctxt->am,
12564 	    start, NULL,
12565 	    elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
12566 	/*
12567 	* Add subst. group members.
12568 	*/
12569 	for (i = 0; i < substGroup->members->nbItems; i++) {
12570 	    member = (xmlSchemaElementPtr) substGroup->members->items[i];
12571 	    /*
12572 	    * NOTE: This fixes bug #341150. xmlAutomataNewOnceTrans2()
12573 	    *  was incorrectly used instead of xmlAutomataNewTransition2()
12574 	    *  (seems like a copy&paste bug from the XML_SCHEMA_TYPE_ALL
12575 	    *  section in xmlSchemaBuildAContentModel() ).
12576 	    * TODO: Check if xmlAutomataNewOnceTrans2() was instead
12577 	    *  intended for the above "counter" section originally. I.e.,
12578 	    *  check xs:all with subst-groups.
12579 	    *
12580 	    * tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL,
12581 	    *	               member->name, member->targetNamespace,
12582 	    *		       1, 1, member);
12583 	    */
12584 	    tmp = xmlAutomataNewTransition2(pctxt->am, start, NULL,
12585 		member->name, member->targetNamespace, member);
12586 	    xmlAutomataNewEpsilon(pctxt->am, tmp, end);
12587 	}
12588     } else {
12589 	xmlAutomataStatePtr hop;
12590 	int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12591 	    UNBOUNDED : particle->maxOccurs - 1;
12592 	int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12593 
12594 	counter =
12595 	    xmlAutomataNewCounter(pctxt->am, minOccurs,
12596 	    maxOccurs);
12597 	hop = xmlAutomataNewState(pctxt->am);
12598 
12599 	xmlAutomataNewEpsilon(pctxt->am,
12600 	    xmlAutomataNewTransition2(pctxt->am,
12601 	    start, NULL,
12602 	    elemDecl->name, elemDecl->targetNamespace, elemDecl),
12603 	    hop);
12604 	/*
12605 	 * Add subst. group members.
12606 	 */
12607 	for (i = 0; i < substGroup->members->nbItems; i++) {
12608 	    member = (xmlSchemaElementPtr) substGroup->members->items[i];
12609 	    xmlAutomataNewEpsilon(pctxt->am,
12610 		xmlAutomataNewTransition2(pctxt->am,
12611 		start, NULL,
12612 		member->name, member->targetNamespace, member),
12613 		hop);
12614 	}
12615 	xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12616 	xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12617     }
12618     if (particle->minOccurs == 0)
12619 	xmlAutomataNewEpsilon(pctxt->am, start, end);
12620     pctxt->state = end;
12621 }
12622 
12623 static void
xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr particle)12624 xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
12625 				     xmlSchemaParticlePtr particle)
12626 {
12627     if (((xmlSchemaElementPtr) particle->children)->flags &
12628 	XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
12629 	/*
12630 	* Substitution groups.
12631 	*/
12632 	xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
12633     } else {
12634 	xmlSchemaElementPtr elemDecl;
12635 	xmlAutomataStatePtr start;
12636 
12637 	elemDecl = (xmlSchemaElementPtr) particle->children;
12638 
12639 	if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
12640 	    return;
12641 	if (particle->maxOccurs == 1) {
12642 	    start = ctxt->state;
12643 	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12644 		    elemDecl->name, elemDecl->targetNamespace, elemDecl);
12645 	} else if ((particle->maxOccurs >= UNBOUNDED) &&
12646 	           (particle->minOccurs < 2)) {
12647 	    /* Special case. */
12648 	    start = ctxt->state;
12649 	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12650 		elemDecl->name, elemDecl->targetNamespace, elemDecl);
12651 	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, ctxt->state, ctxt->state,
12652 		elemDecl->name, elemDecl->targetNamespace, elemDecl);
12653 	} else {
12654 	    int counter;
12655 	    int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12656 			    UNBOUNDED : particle->maxOccurs - 1;
12657 	    int minOccurs = particle->minOccurs < 1 ?
12658 			    0 : particle->minOccurs - 1;
12659 
12660 	    start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
12661 	    counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
12662 	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12663 		elemDecl->name, elemDecl->targetNamespace, elemDecl);
12664 	    xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
12665 	    ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
12666 		NULL, counter);
12667 	}
12668 	if (particle->minOccurs == 0)
12669 	    xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
12670     }
12671 }
12672 
12673 /**
12674  * xmlSchemaBuildAContentModel:
12675  * @ctxt:  the schema parser context
12676  * @particle:  the particle component
12677  * @name:  the complex type's name whose content is being built
12678  *
12679  * Create the automaton for the {content type} of a complex type.
12680  *
12681  */
12682 static void
xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,xmlSchemaParticlePtr particle)12683 xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
12684 			    xmlSchemaParticlePtr particle)
12685 {
12686     if (particle == NULL) {
12687 	PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL");
12688 	return;
12689     }
12690     if (particle->children == NULL) {
12691 	/*
12692 	* Just return in this case. A missing "term" of the particle
12693 	* might arise due to an invalid "term" component.
12694 	*/
12695 	return;
12696     }
12697 
12698     switch (particle->children->type) {
12699 	case XML_SCHEMA_TYPE_ANY: {
12700 	    xmlAutomataStatePtr start, end;
12701 	    xmlSchemaWildcardPtr wild;
12702 	    xmlSchemaWildcardNsPtr ns;
12703 
12704 	    wild = (xmlSchemaWildcardPtr) particle->children;
12705 
12706 	    start = pctxt->state;
12707 	    end = xmlAutomataNewState(pctxt->am);
12708 
12709 	    if (particle->maxOccurs == 1) {
12710 		if (wild->any == 1) {
12711 		    /*
12712 		    * We need to add both transitions:
12713 		    *
12714 		    * 1. the {"*", "*"} for elements in a namespace.
12715 		    */
12716 		    pctxt->state =
12717 			xmlAutomataNewTransition2(pctxt->am,
12718 			start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12719 		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12720 		    /*
12721 		    * 2. the {"*"} for elements in no namespace.
12722 		    */
12723 		    pctxt->state =
12724 			xmlAutomataNewTransition2(pctxt->am,
12725 			start, NULL, BAD_CAST "*", NULL, wild);
12726 		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12727 
12728 		} else if (wild->nsSet != NULL) {
12729 		    ns = wild->nsSet;
12730 		    do {
12731 			pctxt->state = start;
12732 			pctxt->state = xmlAutomataNewTransition2(pctxt->am,
12733 			    pctxt->state, NULL, BAD_CAST "*", ns->value, wild);
12734 			xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12735 			ns = ns->next;
12736 		    } while (ns != NULL);
12737 
12738 		} else if (wild->negNsSet != NULL) {
12739 		    pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12740 			start, end, BAD_CAST "*", wild->negNsSet->value,
12741 			wild);
12742 		}
12743 	    } else {
12744 		int counter;
12745 		xmlAutomataStatePtr hop;
12746 		int maxOccurs =
12747 		    particle->maxOccurs == UNBOUNDED ? UNBOUNDED : particle->maxOccurs - 1;
12748 		int minOccurs =
12749 		    particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12750 
12751 		counter = xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12752 		hop = xmlAutomataNewState(pctxt->am);
12753 		if (wild->any == 1) {
12754 		    pctxt->state =
12755 			xmlAutomataNewTransition2(pctxt->am,
12756 			start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12757 		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12758 		    pctxt->state =
12759 			xmlAutomataNewTransition2(pctxt->am,
12760 			start, NULL, BAD_CAST "*", NULL, wild);
12761 		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12762 		} else if (wild->nsSet != NULL) {
12763 		    ns = wild->nsSet;
12764 		    do {
12765 			pctxt->state =
12766 			    xmlAutomataNewTransition2(pctxt->am,
12767 				start, NULL, BAD_CAST "*", ns->value, wild);
12768 			xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12769 			ns = ns->next;
12770 		    } while (ns != NULL);
12771 
12772 		} else if (wild->negNsSet != NULL) {
12773 		    pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12774 			start, hop, BAD_CAST "*", wild->negNsSet->value,
12775 			wild);
12776 		}
12777 		xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12778 		xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12779 	    }
12780 	    if (particle->minOccurs == 0) {
12781 		xmlAutomataNewEpsilon(pctxt->am, start, end);
12782 	    }
12783 	    pctxt->state = end;
12784             break;
12785 	}
12786         case XML_SCHEMA_TYPE_ELEMENT:
12787 	    xmlSchemaBuildContentModelForElement(pctxt, particle);
12788 	    break;
12789         case XML_SCHEMA_TYPE_SEQUENCE:{
12790                 xmlSchemaTreeItemPtr sub;
12791 
12792                 /*
12793                  * If max and min occurances are default (1) then
12794                  * simply iterate over the particles of the <sequence>.
12795                  */
12796                 if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
12797                     sub = particle->children->children;
12798                     while (sub != NULL) {
12799                         xmlSchemaBuildAContentModel(pctxt,
12800 			    (xmlSchemaParticlePtr) sub);
12801                         sub = sub->next;
12802                     }
12803                 } else {
12804                     xmlAutomataStatePtr oldstate = pctxt->state;
12805 
12806                     if (particle->maxOccurs >= UNBOUNDED) {
12807                         if (particle->minOccurs > 1) {
12808                             xmlAutomataStatePtr tmp;
12809                             int counter;
12810 
12811                             pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12812 				oldstate, NULL);
12813                             oldstate = pctxt->state;
12814 
12815                             counter = xmlAutomataNewCounter(pctxt->am,
12816 				particle->minOccurs - 1, UNBOUNDED);
12817 
12818                             sub = particle->children->children;
12819                             while (sub != NULL) {
12820                                 xmlSchemaBuildAContentModel(pctxt,
12821 				    (xmlSchemaParticlePtr) sub);
12822                                 sub = sub->next;
12823                             }
12824                             tmp = pctxt->state;
12825                             xmlAutomataNewCountedTrans(pctxt->am, tmp,
12826                                                        oldstate, counter);
12827                             pctxt->state =
12828                                 xmlAutomataNewCounterTrans(pctxt->am, tmp,
12829                                                            NULL, counter);
12830 
12831                         } else {
12832                             pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12833 				oldstate, NULL);
12834                             oldstate = pctxt->state;
12835 
12836 			    sub = particle->children->children;
12837                             while (sub != NULL) {
12838                                 xmlSchemaBuildAContentModel(pctxt,
12839 				    (xmlSchemaParticlePtr) sub);
12840                                 sub = sub->next;
12841                             }
12842                             xmlAutomataNewEpsilon(pctxt->am, pctxt->state,
12843                                                   oldstate);
12844 			    /*
12845 			     * epsilon needed to block previous trans from
12846 			     * being allowed to enter back from another
12847 			     * construct
12848 			     */
12849 			    pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12850 						pctxt->state, NULL);
12851                             if (particle->minOccurs == 0) {
12852                                 xmlAutomataNewEpsilon(pctxt->am,
12853 				    oldstate, pctxt->state);
12854                             }
12855                         }
12856                     } else if ((particle->maxOccurs > 1)
12857                                || (particle->minOccurs > 1)) {
12858                         xmlAutomataStatePtr tmp;
12859                         int counter;
12860 
12861                         pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12862 			    oldstate, NULL);
12863                         oldstate = pctxt->state;
12864 
12865                         counter = xmlAutomataNewCounter(pctxt->am,
12866 			    particle->minOccurs - 1,
12867 			    particle->maxOccurs - 1);
12868 
12869                         sub = particle->children->children;
12870                         while (sub != NULL) {
12871                             xmlSchemaBuildAContentModel(pctxt,
12872 				(xmlSchemaParticlePtr) sub);
12873                             sub = sub->next;
12874                         }
12875                         tmp = pctxt->state;
12876                         xmlAutomataNewCountedTrans(pctxt->am,
12877 			    tmp, oldstate, counter);
12878                         pctxt->state =
12879                             xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL,
12880                                                        counter);
12881                         if (particle->minOccurs == 0) {
12882                             xmlAutomataNewEpsilon(pctxt->am,
12883 				oldstate, pctxt->state);
12884                         }
12885                     } else {
12886                         sub = particle->children->children;
12887                         while (sub != NULL) {
12888                             xmlSchemaBuildAContentModel(pctxt,
12889 				(xmlSchemaParticlePtr) sub);
12890                             sub = sub->next;
12891                         }
12892                         if (particle->minOccurs == 0) {
12893                             xmlAutomataNewEpsilon(pctxt->am, oldstate,
12894                                                   pctxt->state);
12895                         }
12896                     }
12897                 }
12898                 break;
12899             }
12900         case XML_SCHEMA_TYPE_CHOICE:{
12901                 xmlSchemaTreeItemPtr sub;
12902                 xmlAutomataStatePtr start, end;
12903 
12904                 start = pctxt->state;
12905                 end = xmlAutomataNewState(pctxt->am);
12906 
12907                 /*
12908                  * iterate over the subtypes and remerge the end with an
12909                  * epsilon transition
12910                  */
12911                 if (particle->maxOccurs == 1) {
12912 		    sub = particle->children->children;
12913                     while (sub != NULL) {
12914                         pctxt->state = start;
12915                         xmlSchemaBuildAContentModel(pctxt,
12916 			    (xmlSchemaParticlePtr) sub);
12917                         xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12918                         sub = sub->next;
12919                     }
12920                 } else {
12921                     int counter;
12922                     xmlAutomataStatePtr hop, base;
12923                     int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12924                         UNBOUNDED : particle->maxOccurs - 1;
12925                     int minOccurs =
12926                         particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12927 
12928                     /*
12929                      * use a counter to keep track of the number of transtions
12930                      * which went through the choice.
12931                      */
12932                     counter =
12933                         xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12934                     hop = xmlAutomataNewState(pctxt->am);
12935                     base = xmlAutomataNewState(pctxt->am);
12936 
12937 		    sub = particle->children->children;
12938                     while (sub != NULL) {
12939                         pctxt->state = base;
12940                         xmlSchemaBuildAContentModel(pctxt,
12941 			    (xmlSchemaParticlePtr) sub);
12942                         xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12943                         sub = sub->next;
12944                     }
12945                     xmlAutomataNewEpsilon(pctxt->am, start, base);
12946 		    xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter);
12947                     xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12948                 }
12949                 if (particle->minOccurs == 0) {
12950                     xmlAutomataNewEpsilon(pctxt->am, start, end);
12951                 }
12952                 pctxt->state = end;
12953                 break;
12954             }
12955         case XML_SCHEMA_TYPE_ALL:{
12956                 xmlAutomataStatePtr start;
12957 		xmlSchemaParticlePtr sub;
12958 		xmlSchemaElementPtr elemDecl;
12959                 int lax;
12960 
12961 		sub = (xmlSchemaParticlePtr) particle->children->children;
12962                 if (sub == NULL)
12963                     break;
12964                 start = pctxt->state;
12965                 while (sub != NULL) {
12966                     pctxt->state = start;
12967 
12968 		    elemDecl = (xmlSchemaElementPtr) sub->children;
12969 		    if (elemDecl == NULL) {
12970 			PERROR_INT("xmlSchemaBuildAContentModel",
12971 			    "<element> particle has no term");
12972 			return;
12973 		    };
12974 		    /*
12975 		    * NOTE: The {max occurs} of all the particles in the
12976 		    * {particles} of the group must be 0 or 1; this is
12977 		    * already ensured during the parse of the content of
12978 		    * <all>.
12979 		    */
12980 		    if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
12981 			int counter;
12982 
12983 		        /*
12984 			 * This is an abstract group, we need to share
12985 			 * the same counter for all the element transitions
12986 			 * derived from the group
12987 			 */
12988 			counter = xmlAutomataNewCounter(pctxt->am,
12989 			                   sub->minOccurs, sub->maxOccurs);
12990 			xmlSchemaBuildContentModelForSubstGroup(pctxt,
12991 					   sub, counter, pctxt->state);
12992 		    } else {
12993 			if ((sub->minOccurs == 1) &&
12994 			    (sub->maxOccurs == 1)) {
12995 			    xmlAutomataNewOnceTrans2(pctxt->am, pctxt->state,
12996 						    pctxt->state,
12997 						    elemDecl->name,
12998 						    elemDecl->targetNamespace,
12999 						    1, 1, elemDecl);
13000 			} else if ((sub->minOccurs == 0) &&
13001 			    (sub->maxOccurs == 1)) {
13002 
13003 			    xmlAutomataNewCountTrans2(pctxt->am, pctxt->state,
13004 						     pctxt->state,
13005 						     elemDecl->name,
13006 						     elemDecl->targetNamespace,
13007 						     0,
13008 						     1,
13009 						     elemDecl);
13010 			}
13011 		    }
13012                     sub = (xmlSchemaParticlePtr) sub->next;
13013                 }
13014                 lax = particle->minOccurs == 0;
13015                 pctxt->state =
13016                     xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, lax);
13017                 break;
13018             }
13019 	case XML_SCHEMA_TYPE_GROUP:
13020 	    /*
13021 	    * If we hit a model group definition, then this means that
13022 	    * it was empty, thus was not substituted for the containing
13023 	    * model group. Just do nothing in this case.
13024 	    * TODO: But the group should be substituted and not occur at
13025 	    * all in the content model at this point. Fix this.
13026 	    */
13027 	    break;
13028         default:
13029 	    xmlSchemaInternalErr2(ACTXT_CAST pctxt,
13030 		"xmlSchemaBuildAContentModel",
13031 		"found unexpected term of type '%s' in content model",
13032 		WXS_ITEM_TYPE_NAME(particle->children), NULL);
13033             return;
13034     }
13035 }
13036 
13037 /**
13038  * xmlSchemaBuildContentModel:
13039  * @ctxt:  the schema parser context
13040  * @type:  the complex type definition
13041  * @name:  the element name
13042  *
13043  * Builds the content model of the complex type.
13044  */
13045 static void
xmlSchemaBuildContentModel(xmlSchemaTypePtr type,xmlSchemaParserCtxtPtr ctxt)13046 xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
13047 			   xmlSchemaParserCtxtPtr ctxt)
13048 {
13049     if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
13050 	(type->contModel != NULL) ||
13051 	((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
13052 	(type->contentType != XML_SCHEMA_CONTENT_MIXED)))
13053 	return;
13054 
13055 #ifdef DEBUG_CONTENT
13056     xmlGenericError(xmlGenericErrorContext,
13057                     "Building content model for %s\n", name);
13058 #endif
13059     ctxt->am = NULL;
13060     ctxt->am = xmlNewAutomata();
13061     if (ctxt->am == NULL) {
13062         xmlGenericError(xmlGenericErrorContext,
13063 	    "Cannot create automata for complex type %s\n", type->name);
13064         return;
13065     }
13066     ctxt->state = xmlAutomataGetInitState(ctxt->am);
13067     /*
13068     * Build the automaton.
13069     */
13070     xmlSchemaBuildAContentModel(ctxt, WXS_TYPE_PARTICLE(type));
13071     xmlAutomataSetFinalState(ctxt->am, ctxt->state);
13072     type->contModel = xmlAutomataCompile(ctxt->am);
13073     if (type->contModel == NULL) {
13074         xmlSchemaPCustomErr(ctxt,
13075 	    XML_SCHEMAP_INTERNAL,
13076 	    WXS_BASIC_CAST type, type->node,
13077 	    "Failed to compile the content model", NULL);
13078     } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
13079         xmlSchemaPCustomErr(ctxt,
13080 	    XML_SCHEMAP_NOT_DETERMINISTIC,
13081 	    /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
13082 	    WXS_BASIC_CAST type, type->node,
13083 	    "The content model is not determinist", NULL);
13084     } else {
13085 #ifdef DEBUG_CONTENT_REGEXP
13086         xmlGenericError(xmlGenericErrorContext,
13087                         "Content model of %s:\n", type->name);
13088         xmlRegexpPrint(stderr, type->contModel);
13089 #endif
13090     }
13091     ctxt->state = NULL;
13092     xmlFreeAutomata(ctxt->am);
13093     ctxt->am = NULL;
13094 }
13095 
13096 /**
13097  * xmlSchemaResolveElementReferences:
13098  * @elem:  the schema element context
13099  * @ctxt:  the schema parser context
13100  *
13101  * Resolves the references of an element declaration
13102  * or particle, which has an element declaration as it's
13103  * term.
13104  */
13105 static void
xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,xmlSchemaParserCtxtPtr ctxt)13106 xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,
13107 				  xmlSchemaParserCtxtPtr ctxt)
13108 {
13109     if ((ctxt == NULL) || (elemDecl == NULL) ||
13110 	((elemDecl != NULL) &&
13111 	(elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
13112         return;
13113     elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
13114 
13115     if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
13116 	xmlSchemaTypePtr type;
13117 
13118 	/* (type definition) ... otherwise the type definition �resolved�
13119 	* to by the �actual value� of the type [attribute] ...
13120 	*/
13121 	type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
13122 	    elemDecl->namedTypeNs);
13123 	if (type == NULL) {
13124 	    xmlSchemaPResCompAttrErr(ctxt,
13125 		XML_SCHEMAP_SRC_RESOLVE,
13126 		WXS_BASIC_CAST elemDecl, elemDecl->node,
13127 		"type", elemDecl->namedType, elemDecl->namedTypeNs,
13128 		XML_SCHEMA_TYPE_BASIC, "type definition");
13129 	} else
13130 	    elemDecl->subtypes = type;
13131     }
13132     if (elemDecl->substGroup != NULL) {
13133 	xmlSchemaElementPtr substHead;
13134 
13135 	/*
13136 	* FIXME TODO: Do we need a new field in _xmlSchemaElement for
13137 	* substitutionGroup?
13138 	*/
13139 	substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
13140 	    elemDecl->substGroupNs);
13141 	if (substHead == NULL) {
13142 	    xmlSchemaPResCompAttrErr(ctxt,
13143 		XML_SCHEMAP_SRC_RESOLVE,
13144 		WXS_BASIC_CAST elemDecl, NULL,
13145 		"substitutionGroup", elemDecl->substGroup,
13146 		elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
13147 	} else {
13148 	    xmlSchemaResolveElementReferences(substHead, ctxt);
13149 	    /*
13150 	    * Set the "substitution group affiliation".
13151 	    * NOTE that now we use the "refDecl" field for this.
13152 	    */
13153 	    WXS_SUBST_HEAD(elemDecl) = substHead;
13154 	    /*
13155 	    * The type definitions is set to:
13156 	    * SPEC "...the {type definition} of the element
13157 	    * declaration �resolved� to by the �actual value�
13158 	    * of the substitutionGroup [attribute], if present"
13159 	    */
13160 	    if (elemDecl->subtypes == NULL)
13161 		elemDecl->subtypes = substHead->subtypes;
13162 	}
13163     }
13164     /*
13165     * SPEC "The definition of anyType serves as the default type definition
13166     * for element declarations whose XML representation does not specify one."
13167     */
13168     if ((elemDecl->subtypes == NULL) &&
13169 	(elemDecl->namedType == NULL) &&
13170 	(elemDecl->substGroup == NULL))
13171 	elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
13172 }
13173 
13174 /**
13175  * xmlSchemaResolveUnionMemberTypes:
13176  * @ctxt:  the schema parser context
13177  * @type:  the schema simple type definition
13178  *
13179  * Checks and builds the "member type definitions" property of the union
13180  * simple type. This handles part (1), part (2) is done in
13181  * xmlSchemaFinishMemberTypeDefinitionsProperty()
13182  *
13183  * Returns -1 in case of an internal error, 0 otherwise.
13184  */
13185 static int
xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)13186 xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
13187 				 xmlSchemaTypePtr type)
13188 {
13189 
13190     xmlSchemaTypeLinkPtr link, lastLink, newLink;
13191     xmlSchemaTypePtr memberType;
13192 
13193     /*
13194     * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
13195     * define the explicit members as the type definitions �resolved�
13196     * to by the items in the �actual value� of the memberTypes [attribute],
13197     * if any, followed by the type definitions corresponding to the
13198     * <simpleType>s among the [children] of <union>, if any."
13199     */
13200     /*
13201     * Resolve references.
13202     */
13203     link = type->memberTypes;
13204     lastLink = NULL;
13205     while (link != NULL) {
13206 	const xmlChar *name, *nsName;
13207 
13208 	name = ((xmlSchemaQNameRefPtr) link->type)->name;
13209 	nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
13210 
13211 	memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
13212 	if ((memberType == NULL) || (! WXS_IS_SIMPLE(memberType))) {
13213 	    xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
13214 		WXS_BASIC_CAST type, type->node, "memberTypes",
13215 		name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
13216 	    /*
13217 	    * Remove the member type link.
13218 	    */
13219 	    if (lastLink == NULL)
13220 		type->memberTypes = link->next;
13221 	    else
13222 		lastLink->next = link->next;
13223 	    newLink = link;
13224 	    link = link->next;
13225 	    xmlFree(newLink);
13226 	} else {
13227 	    link->type = memberType;
13228 	    lastLink = link;
13229 	    link = link->next;
13230 	}
13231     }
13232     /*
13233     * Add local simple types,
13234     */
13235     memberType = type->subtypes;
13236     while (memberType != NULL) {
13237 	link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
13238 	if (link == NULL) {
13239 	    xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
13240 	    return (-1);
13241 	}
13242 	link->type = memberType;
13243 	link->next = NULL;
13244 	if (lastLink == NULL)
13245 	    type->memberTypes = link;
13246 	else
13247 	    lastLink->next = link;
13248 	lastLink = link;
13249 	memberType = memberType->next;
13250     }
13251     return (0);
13252 }
13253 
13254 /**
13255  * xmlSchemaIsDerivedFromBuiltInType:
13256  * @ctxt:  the schema parser context
13257  * @type:  the type definition
13258  * @valType: the value type
13259  *
13260  *
13261  * Returns 1 if the type has the given value type, or
13262  * is derived from such a type.
13263  */
13264 static int
xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type,int valType)13265 xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13266 {
13267     if (type == NULL)
13268 	return (0);
13269     if (WXS_IS_COMPLEX(type))
13270 	return (0);
13271     if (type->type == XML_SCHEMA_TYPE_BASIC) {
13272 	if (type->builtInType == valType)
13273 	    return(1);
13274 	if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13275 	    (type->builtInType == XML_SCHEMAS_ANYTYPE))
13276 	    return (0);
13277 	return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13278     }
13279     return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13280 }
13281 
13282 #if 0
13283 /**
13284  * xmlSchemaIsDerivedFromBuiltInType:
13285  * @ctxt:  the schema parser context
13286  * @type:  the type definition
13287  * @valType: the value type
13288  *
13289  *
13290  * Returns 1 if the type has the given value type, or
13291  * is derived from such a type.
13292  */
13293 static int
13294 xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13295 {
13296     if (type == NULL)
13297 	return (0);
13298     if (WXS_IS_COMPLEX(type))
13299 	return (0);
13300     if (type->type == XML_SCHEMA_TYPE_BASIC) {
13301 	if (type->builtInType == valType)
13302 	    return(1);
13303 	return (0);
13304     } else
13305 	return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13306 
13307     return (0);
13308 }
13309 #endif
13310 
13311 static xmlSchemaTypePtr
xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)13312 xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
13313 {
13314     if (type == NULL)
13315 	return (NULL);
13316     if (WXS_IS_COMPLEX(type))
13317 	return (NULL);
13318     if (type->type == XML_SCHEMA_TYPE_BASIC)
13319 	return(type);
13320     return(xmlSchemaQueryBuiltInType(type->subtypes));
13321 }
13322 
13323 /**
13324  * xmlSchemaGetPrimitiveType:
13325  * @type:  the simpleType definition
13326  *
13327  * Returns the primitive type of the given type or
13328  * NULL in case of error.
13329  */
13330 static xmlSchemaTypePtr
xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)13331 xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
13332 {
13333 
13334     while (type != NULL) {
13335 	/*
13336 	* Note that anySimpleType is actually not a primitive type
13337 	* but we need that here.
13338 	*/
13339 	if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13340 	   (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
13341 	    return (type);
13342 	type = type->baseType;
13343     }
13344 
13345     return (NULL);
13346 }
13347 
13348 #if 0
13349 /**
13350  * xmlSchemaGetBuiltInTypeAncestor:
13351  * @type:  the simpleType definition
13352  *
13353  * Returns the primitive type of the given type or
13354  * NULL in case of error.
13355  */
13356 static xmlSchemaTypePtr
13357 xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
13358 {
13359     if (WXS_IS_LIST(type) || WXS_IS_UNION(type))
13360 	return (0);
13361     while (type != NULL) {
13362 	if (type->type == XML_SCHEMA_TYPE_BASIC)
13363 	    return (type);
13364 	type = type->baseType;
13365     }
13366 
13367     return (NULL);
13368 }
13369 #endif
13370 
13371 /**
13372  * xmlSchemaCloneWildcardNsConstraints:
13373  * @ctxt:  the schema parser context
13374  * @dest:  the destination wildcard
13375  * @source: the source wildcard
13376  *
13377  * Clones the namespace constraints of source
13378  * and assignes them to dest.
13379  * Returns -1 on internal error, 0 otherwise.
13380  */
13381 static int
xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,xmlSchemaWildcardPtr dest,xmlSchemaWildcardPtr source)13382 xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
13383 				    xmlSchemaWildcardPtr dest,
13384 				    xmlSchemaWildcardPtr source)
13385 {
13386     xmlSchemaWildcardNsPtr cur, tmp, last;
13387 
13388     if ((source == NULL) || (dest == NULL))
13389 	return(-1);
13390     dest->any = source->any;
13391     cur = source->nsSet;
13392     last = NULL;
13393     while (cur != NULL) {
13394 	tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13395 	if (tmp == NULL)
13396 	    return(-1);
13397 	tmp->value = cur->value;
13398 	if (last == NULL)
13399 	    dest->nsSet = tmp;
13400 	else
13401 	    last->next = tmp;
13402 	last = tmp;
13403 	cur = cur->next;
13404     }
13405     if (dest->negNsSet != NULL)
13406 	xmlSchemaFreeWildcardNsSet(dest->negNsSet);
13407     if (source->negNsSet != NULL) {
13408 	dest->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13409 	if (dest->negNsSet == NULL)
13410 	    return(-1);
13411 	dest->negNsSet->value = source->negNsSet->value;
13412     } else
13413 	dest->negNsSet = NULL;
13414     return(0);
13415 }
13416 
13417 /**
13418  * xmlSchemaUnionWildcards:
13419  * @ctxt:  the schema parser context
13420  * @completeWild:  the first wildcard
13421  * @curWild: the second wildcard
13422  *
13423  * Unions the namespace constraints of the given wildcards.
13424  * @completeWild will hold the resulting union.
13425  * Returns a positive error code on failure, -1 in case of an
13426  * internal error, 0 otherwise.
13427  */
13428 static int
xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,xmlSchemaWildcardPtr completeWild,xmlSchemaWildcardPtr curWild)13429 xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
13430 			    xmlSchemaWildcardPtr completeWild,
13431 			    xmlSchemaWildcardPtr curWild)
13432 {
13433     xmlSchemaWildcardNsPtr cur, curB, tmp;
13434 
13435     /*
13436     * 1 If O1 and O2 are the same value, then that value must be the
13437     * value.
13438     */
13439     if ((completeWild->any == curWild->any) &&
13440 	((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13441 	((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13442 
13443 	if ((completeWild->negNsSet == NULL) ||
13444 	    (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13445 
13446 	    if (completeWild->nsSet != NULL) {
13447 		int found = 0;
13448 
13449 		/*
13450 		* Check equality of sets.
13451 		*/
13452 		cur = completeWild->nsSet;
13453 		while (cur != NULL) {
13454 		    found = 0;
13455 		    curB = curWild->nsSet;
13456 		    while (curB != NULL) {
13457 			if (cur->value == curB->value) {
13458 			    found = 1;
13459 			    break;
13460 			}
13461 			curB = curB->next;
13462 		    }
13463 		    if (!found)
13464 			break;
13465 		    cur = cur->next;
13466 		}
13467 		if (found)
13468 		    return(0);
13469 	    } else
13470 		return(0);
13471 	}
13472     }
13473     /*
13474     * 2 If either O1 or O2 is any, then any must be the value
13475     */
13476     if (completeWild->any != curWild->any) {
13477 	if (completeWild->any == 0) {
13478 	    completeWild->any = 1;
13479 	    if (completeWild->nsSet != NULL) {
13480 		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13481 		completeWild->nsSet = NULL;
13482 	    }
13483 	    if (completeWild->negNsSet != NULL) {
13484 		xmlFree(completeWild->negNsSet);
13485 		completeWild->negNsSet = NULL;
13486 	    }
13487 	}
13488 	return (0);
13489     }
13490     /*
13491     * 3 If both O1 and O2 are sets of (namespace names or �absent�),
13492     * then the union of those sets must be the value.
13493     */
13494     if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13495 	int found;
13496 	xmlSchemaWildcardNsPtr start;
13497 
13498 	cur = curWild->nsSet;
13499 	start = completeWild->nsSet;
13500 	while (cur != NULL) {
13501 	    found = 0;
13502 	    curB = start;
13503 	    while (curB != NULL) {
13504 		if (cur->value == curB->value) {
13505 		    found = 1;
13506 		    break;
13507 		}
13508 		curB = curB->next;
13509 	    }
13510 	    if (!found) {
13511 		tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13512 		if (tmp == NULL)
13513 		    return (-1);
13514 		tmp->value = cur->value;
13515 		tmp->next = completeWild->nsSet;
13516 		completeWild->nsSet = tmp;
13517 	    }
13518 	    cur = cur->next;
13519 	}
13520 
13521 	return(0);
13522     }
13523     /*
13524     * 4 If the two are negations of different values (namespace names
13525     * or �absent�), then a pair of not and �absent� must be the value.
13526     */
13527     if ((completeWild->negNsSet != NULL) &&
13528 	(curWild->negNsSet != NULL) &&
13529 	(completeWild->negNsSet->value != curWild->negNsSet->value)) {
13530 	completeWild->negNsSet->value = NULL;
13531 
13532 	return(0);
13533     }
13534     /*
13535      * 5.
13536      */
13537     if (((completeWild->negNsSet != NULL) &&
13538 	(completeWild->negNsSet->value != NULL) &&
13539 	(curWild->nsSet != NULL)) ||
13540 	((curWild->negNsSet != NULL) &&
13541 	(curWild->negNsSet->value != NULL) &&
13542 	(completeWild->nsSet != NULL))) {
13543 
13544 	int nsFound, absentFound = 0;
13545 
13546 	if (completeWild->nsSet != NULL) {
13547 	    cur = completeWild->nsSet;
13548 	    curB = curWild->negNsSet;
13549 	} else {
13550 	    cur = curWild->nsSet;
13551 	    curB = completeWild->negNsSet;
13552 	}
13553 	nsFound = 0;
13554 	while (cur != NULL) {
13555 	    if (cur->value == NULL)
13556 		absentFound = 1;
13557 	    else if (cur->value == curB->value)
13558 		nsFound = 1;
13559 	    if (nsFound && absentFound)
13560 		break;
13561 	    cur = cur->next;
13562 	}
13563 
13564 	if (nsFound && absentFound) {
13565 	    /*
13566 	    * 5.1 If the set S includes both the negated namespace
13567 	    * name and �absent�, then any must be the value.
13568 	    */
13569 	    completeWild->any = 1;
13570 	    if (completeWild->nsSet != NULL) {
13571 		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13572 		completeWild->nsSet = NULL;
13573 	    }
13574 	    if (completeWild->negNsSet != NULL) {
13575 		xmlFree(completeWild->negNsSet);
13576 		completeWild->negNsSet = NULL;
13577 	    }
13578 	} else if (nsFound && (!absentFound)) {
13579 	    /*
13580 	    * 5.2 If the set S includes the negated namespace name
13581 	    * but not �absent�, then a pair of not and �absent� must
13582 	    * be the value.
13583 	    */
13584 	    if (completeWild->nsSet != NULL) {
13585 		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13586 		completeWild->nsSet = NULL;
13587 	    }
13588 	    if (completeWild->negNsSet == NULL) {
13589 		completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13590 		if (completeWild->negNsSet == NULL)
13591 		    return (-1);
13592 	    }
13593 	    completeWild->negNsSet->value = NULL;
13594 	} else if ((!nsFound) && absentFound) {
13595 	    /*
13596 	    * 5.3 If the set S includes �absent� but not the negated
13597 	    * namespace name, then the union is not expressible.
13598 	    */
13599 	    xmlSchemaPErr(ctxt, completeWild->node,
13600 		XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
13601 		"The union of the wilcard is not expressible.\n",
13602 		NULL, NULL);
13603 	    return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
13604 	} else if ((!nsFound) && (!absentFound)) {
13605 	    /*
13606 	    * 5.4 If the set S does not include either the negated namespace
13607 	    * name or �absent�, then whichever of O1 or O2 is a pair of not
13608 	    * and a namespace name must be the value.
13609 	    */
13610 	    if (completeWild->negNsSet == NULL) {
13611 		if (completeWild->nsSet != NULL) {
13612 		    xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13613 		    completeWild->nsSet = NULL;
13614 		}
13615 		completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13616 		if (completeWild->negNsSet == NULL)
13617 		    return (-1);
13618 		completeWild->negNsSet->value = curWild->negNsSet->value;
13619 	    }
13620 	}
13621 	return (0);
13622     }
13623     /*
13624      * 6.
13625      */
13626     if (((completeWild->negNsSet != NULL) &&
13627 	(completeWild->negNsSet->value == NULL) &&
13628 	(curWild->nsSet != NULL)) ||
13629 	((curWild->negNsSet != NULL) &&
13630 	(curWild->negNsSet->value == NULL) &&
13631 	(completeWild->nsSet != NULL))) {
13632 
13633 	if (completeWild->nsSet != NULL) {
13634 	    cur = completeWild->nsSet;
13635 	} else {
13636 	    cur = curWild->nsSet;
13637 	}
13638 	while (cur != NULL) {
13639 	    if (cur->value == NULL) {
13640 		/*
13641 		* 6.1 If the set S includes �absent�, then any must be the
13642 		* value.
13643 		*/
13644 		completeWild->any = 1;
13645 		if (completeWild->nsSet != NULL) {
13646 		    xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13647 		    completeWild->nsSet = NULL;
13648 		}
13649 		if (completeWild->negNsSet != NULL) {
13650 		    xmlFree(completeWild->negNsSet);
13651 		    completeWild->negNsSet = NULL;
13652 		}
13653 		return (0);
13654 	    }
13655 	    cur = cur->next;
13656 	}
13657 	if (completeWild->negNsSet == NULL) {
13658 	    /*
13659 	    * 6.2 If the set S does not include �absent�, then a pair of not
13660 	    * and �absent� must be the value.
13661 	    */
13662 	    if (completeWild->nsSet != NULL) {
13663 		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13664 		completeWild->nsSet = NULL;
13665 	    }
13666 	    completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13667 	    if (completeWild->negNsSet == NULL)
13668 		return (-1);
13669 	    completeWild->negNsSet->value = NULL;
13670 	}
13671 	return (0);
13672     }
13673     return (0);
13674 
13675 }
13676 
13677 /**
13678  * xmlSchemaIntersectWildcards:
13679  * @ctxt:  the schema parser context
13680  * @completeWild:  the first wildcard
13681  * @curWild: the second wildcard
13682  *
13683  * Intersects the namespace constraints of the given wildcards.
13684  * @completeWild will hold the resulting intersection.
13685  * Returns a positive error code on failure, -1 in case of an
13686  * internal error, 0 otherwise.
13687  */
13688 static int
xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,xmlSchemaWildcardPtr completeWild,xmlSchemaWildcardPtr curWild)13689 xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
13690 			    xmlSchemaWildcardPtr completeWild,
13691 			    xmlSchemaWildcardPtr curWild)
13692 {
13693     xmlSchemaWildcardNsPtr cur, curB, prev,  tmp;
13694 
13695     /*
13696     * 1 If O1 and O2 are the same value, then that value must be the
13697     * value.
13698     */
13699     if ((completeWild->any == curWild->any) &&
13700 	((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13701 	((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13702 
13703 	if ((completeWild->negNsSet == NULL) ||
13704 	    (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13705 
13706 	    if (completeWild->nsSet != NULL) {
13707 		int found = 0;
13708 
13709 		/*
13710 		* Check equality of sets.
13711 		*/
13712 		cur = completeWild->nsSet;
13713 		while (cur != NULL) {
13714 		    found = 0;
13715 		    curB = curWild->nsSet;
13716 		    while (curB != NULL) {
13717 			if (cur->value == curB->value) {
13718 			    found = 1;
13719 			    break;
13720 			}
13721 			curB = curB->next;
13722 		    }
13723 		    if (!found)
13724 			break;
13725 		    cur = cur->next;
13726 		}
13727 		if (found)
13728 		    return(0);
13729 	    } else
13730 		return(0);
13731 	}
13732     }
13733     /*
13734     * 2 If either O1 or O2 is any, then the other must be the value.
13735     */
13736     if ((completeWild->any != curWild->any) && (completeWild->any)) {
13737 	if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13738 	    return(-1);
13739 	return(0);
13740     }
13741     /*
13742     * 3 If either O1 or O2 is a pair of not and a value (a namespace
13743     * name or �absent�) and the other is a set of (namespace names or
13744     * �absent�), then that set, minus the negated value if it was in
13745     * the set, minus �absent� if it was in the set, must be the value.
13746     */
13747     if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
13748 	((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
13749 	const xmlChar *neg;
13750 
13751 	if (completeWild->nsSet == NULL) {
13752 	    neg = completeWild->negNsSet->value;
13753 	    if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13754 		return(-1);
13755 	} else
13756 	    neg = curWild->negNsSet->value;
13757 	/*
13758 	* Remove absent and negated.
13759 	*/
13760 	prev = NULL;
13761 	cur = completeWild->nsSet;
13762 	while (cur != NULL) {
13763 	    if (cur->value == NULL) {
13764 		if (prev == NULL)
13765 		    completeWild->nsSet = cur->next;
13766 		else
13767 		    prev->next = cur->next;
13768 		xmlFree(cur);
13769 		break;
13770 	    }
13771 	    prev = cur;
13772 	    cur = cur->next;
13773 	}
13774 	if (neg != NULL) {
13775 	    prev = NULL;
13776 	    cur = completeWild->nsSet;
13777 	    while (cur != NULL) {
13778 		if (cur->value == neg) {
13779 		    if (prev == NULL)
13780 			completeWild->nsSet = cur->next;
13781 		    else
13782 			prev->next = cur->next;
13783 		    xmlFree(cur);
13784 		    break;
13785 		}
13786 		prev = cur;
13787 		cur = cur->next;
13788 	    }
13789 	}
13790 
13791 	return(0);
13792     }
13793     /*
13794     * 4 If both O1 and O2 are sets of (namespace names or �absent�),
13795     * then the intersection of those sets must be the value.
13796     */
13797     if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13798 	int found;
13799 
13800 	cur = completeWild->nsSet;
13801 	prev = NULL;
13802 	while (cur != NULL) {
13803 	    found = 0;
13804 	    curB = curWild->nsSet;
13805 	    while (curB != NULL) {
13806 		if (cur->value == curB->value) {
13807 		    found = 1;
13808 		    break;
13809 		}
13810 		curB = curB->next;
13811 	    }
13812 	    if (!found) {
13813 		if (prev == NULL)
13814 		    completeWild->nsSet = cur->next;
13815 		else
13816 		    prev->next = cur->next;
13817 		tmp = cur->next;
13818 		xmlFree(cur);
13819 		cur = tmp;
13820 		continue;
13821 	    }
13822 	    prev = cur;
13823 	    cur = cur->next;
13824 	}
13825 
13826 	return(0);
13827     }
13828     /* 5 If the two are negations of different namespace names,
13829     * then the intersection is not expressible
13830     */
13831     if ((completeWild->negNsSet != NULL) &&
13832 	(curWild->negNsSet != NULL) &&
13833 	(completeWild->negNsSet->value != curWild->negNsSet->value) &&
13834 	(completeWild->negNsSet->value != NULL) &&
13835 	(curWild->negNsSet->value != NULL)) {
13836 
13837 	xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
13838 	    "The intersection of the wilcard is not expressible.\n",
13839 	    NULL, NULL);
13840 	return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
13841     }
13842     /*
13843     * 6 If the one is a negation of a namespace name and the other
13844     * is a negation of �absent�, then the one which is the negation
13845     * of a namespace name must be the value.
13846     */
13847     if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
13848 	(completeWild->negNsSet->value != curWild->negNsSet->value) &&
13849 	(completeWild->negNsSet->value == NULL)) {
13850 	completeWild->negNsSet->value =  curWild->negNsSet->value;
13851     }
13852     return(0);
13853 }
13854 
13855 /**
13856  * xmlSchemaIsWildcardNsConstraintSubset:
13857  * @ctxt:  the schema parser context
13858  * @sub:  the first wildcard
13859  * @super: the second wildcard
13860  *
13861  * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
13862  *
13863  * Returns 0 if the namespace constraint of @sub is an intensional
13864  * subset of @super, 1 otherwise.
13865  */
13866 static int
xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,xmlSchemaWildcardPtr super)13867 xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
13868 			  xmlSchemaWildcardPtr super)
13869 {
13870     /*
13871     * 1 super must be any.
13872     */
13873     if (super->any)
13874 	return (0);
13875     /*
13876     * 2.1 sub must be a pair of not and a namespace name or �absent�.
13877     * 2.2 super must be a pair of not and the same value.
13878     */
13879     if ((sub->negNsSet != NULL) &&
13880 	(super->negNsSet != NULL) &&
13881 	(sub->negNsSet->value == sub->negNsSet->value))
13882 	return (0);
13883     /*
13884     * 3.1 sub must be a set whose members are either namespace names or �absent�.
13885     */
13886     if (sub->nsSet != NULL) {
13887 	/*
13888 	* 3.2.1 super must be the same set or a superset thereof.
13889 	*/
13890 	if (super->nsSet != NULL) {
13891 	    xmlSchemaWildcardNsPtr cur, curB;
13892 	    int found = 0;
13893 
13894 	    cur = sub->nsSet;
13895 	    while (cur != NULL) {
13896 		found = 0;
13897 		curB = super->nsSet;
13898 		while (curB != NULL) {
13899 		    if (cur->value == curB->value) {
13900 			found = 1;
13901 			break;
13902 		    }
13903 		    curB = curB->next;
13904 		}
13905 		if (!found)
13906 		    return (1);
13907 		cur = cur->next;
13908 	    }
13909 	    if (found)
13910 		return (0);
13911 	} else if (super->negNsSet != NULL) {
13912 	    xmlSchemaWildcardNsPtr cur;
13913 	    /*
13914 	    * 3.2.2 super must be a pair of not and a namespace name or
13915 	    * �absent� and that value must not be in sub's set.
13916 	    */
13917 	    cur = sub->nsSet;
13918 	    while (cur != NULL) {
13919 		if (cur->value == super->negNsSet->value)
13920 		    return (1);
13921 		cur = cur->next;
13922 	    }
13923 	    return (0);
13924 	}
13925     }
13926     return (1);
13927 }
13928 
13929 static int
xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse,int * fixed,const xmlChar ** value,xmlSchemaValPtr * val)13930 xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse,
13931 				     int *fixed,
13932 				     const xmlChar **value,
13933 				     xmlSchemaValPtr *val)
13934 {
13935     *fixed = 0;
13936     *value = NULL;
13937     if (val != 0)
13938 	*val = NULL;
13939 
13940     if (attruse->defValue != NULL) {
13941 	*value = attruse->defValue;
13942 	if (val != NULL)
13943 	    *val = attruse->defVal;
13944 	if (attruse->flags & XML_SCHEMA_ATTR_USE_FIXED)
13945 	    *fixed = 1;
13946 	return(1);
13947     } else if ((attruse->attrDecl != NULL) &&
13948 	(attruse->attrDecl->defValue != NULL)) {
13949 	*value = attruse->attrDecl->defValue;
13950 	if (val != NULL)
13951 	    *val = attruse->attrDecl->defVal;
13952 	if (attruse->attrDecl->flags & XML_SCHEMAS_ATTR_FIXED)
13953 	    *fixed = 1;
13954 	return(1);
13955     }
13956     return(0);
13957 }
13958 /**
13959  * xmlSchemaCheckCVCWildcardNamespace:
13960  * @wild:  the wildcard
13961  * @ns:  the namespace
13962  *
13963  * Validation Rule: Wildcard allows Namespace Name
13964  * (cvc-wildcard-namespace)
13965  *
13966  * Returns 0 if the given namespace matches the wildcard,
13967  * 1 otherwise and -1 on API errors.
13968  */
13969 static int
xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,const xmlChar * ns)13970 xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
13971 				   const xmlChar* ns)
13972 {
13973     if (wild == NULL)
13974 	return(-1);
13975 
13976     if (wild->any)
13977 	return(0);
13978     else if (wild->nsSet != NULL) {
13979 	xmlSchemaWildcardNsPtr cur;
13980 
13981 	cur = wild->nsSet;
13982 	while (cur != NULL) {
13983 	    if (xmlStrEqual(cur->value, ns))
13984 		return(0);
13985 	    cur = cur->next;
13986 	}
13987     } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
13988 	(!xmlStrEqual(wild->negNsSet->value, ns)))
13989 	return(0);
13990 
13991     return(1);
13992 }
13993 
13994 #define XML_SCHEMA_ACTION_DERIVE 0
13995 #define XML_SCHEMA_ACTION_REDEFINE 1
13996 
13997 #define WXS_ACTION_STR(a) \
13998 ((a) == XML_SCHEMA_ACTION_DERIVE) ? (const xmlChar *) "base" : (const xmlChar *) "redefined"
13999 
14000 /*
14001 * Schema Component Constraint:
14002 *   Derivation Valid (Restriction, Complex)
14003 *   derivation-ok-restriction (2) - (4)
14004 *
14005 * ATTENTION:
14006 * In XML Schema 1.1 this will be:
14007 * Validation Rule:
14008 *     Checking complex type subsumption (practicalSubsumption) (1, 2 and 3)
14009 *
14010 */
14011 static int
xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt,int action,xmlSchemaBasicItemPtr item,xmlSchemaBasicItemPtr baseItem,xmlSchemaItemListPtr uses,xmlSchemaItemListPtr baseUses,xmlSchemaWildcardPtr wild,xmlSchemaWildcardPtr baseWild)14012 xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt,
14013 				       int action,
14014 				       xmlSchemaBasicItemPtr item,
14015 				       xmlSchemaBasicItemPtr baseItem,
14016 				       xmlSchemaItemListPtr uses,
14017 				       xmlSchemaItemListPtr baseUses,
14018 				       xmlSchemaWildcardPtr wild,
14019 				       xmlSchemaWildcardPtr baseWild)
14020 {
14021     xmlSchemaAttributeUsePtr cur = NULL, bcur;
14022     int i, j, found; /* err = 0; */
14023     const xmlChar *bEffValue;
14024     int effFixed;
14025 
14026     if (uses != NULL) {
14027 	for (i = 0; i < uses->nbItems; i++) {
14028 	    cur = uses->items[i];
14029 	    found = 0;
14030 	    if (baseUses == NULL)
14031 		goto not_found;
14032 	    for (j = 0; j < baseUses->nbItems; j++) {
14033 		bcur = baseUses->items[j];
14034 		if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14035 			WXS_ATTRUSE_DECL_NAME(bcur)) &&
14036 		    (WXS_ATTRUSE_DECL_TNS(cur) ==
14037 			WXS_ATTRUSE_DECL_TNS(bcur)))
14038 		{
14039 		    /*
14040 		    * (2.1) "If there is an attribute use in the {attribute
14041 		    * uses} of the {base type definition} (call this B) whose
14042 		    * {attribute declaration} has the same {name} and {target
14043 		    * namespace}, then  all of the following must be true:"
14044 		    */
14045 		    found = 1;
14046 
14047 		    if ((cur->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
14048 			(bcur->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED))
14049 		    {
14050 			xmlChar *str = NULL;
14051 			/*
14052 			* (2.1.1) "one of the following must be true:"
14053 			* (2.1.1.1) "B's {required} is false."
14054 			* (2.1.1.2) "R's {required} is true."
14055 			*/
14056 			xmlSchemaPAttrUseErr4(pctxt,
14057 			    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
14058 			    WXS_ITEM_NODE(item), item, cur,
14059 			    "The 'optional' attribute use is inconsistent "
14060 			    "with the corresponding 'required' attribute use of "
14061 			    "the %s %s",
14062 			    WXS_ACTION_STR(action),
14063 			    xmlSchemaGetComponentDesignation(&str, baseItem),
14064 			    NULL, NULL);
14065 			FREE_AND_NULL(str);
14066 			/* err = pctxt->err; */
14067 		    } else if (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
14068 			WXS_ATTRUSE_TYPEDEF(cur),
14069 			WXS_ATTRUSE_TYPEDEF(bcur), 0) != 0)
14070 		    {
14071 			xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
14072 
14073 			/*
14074 			* SPEC (2.1.2) "R's {attribute declaration}'s
14075 			* {type definition} must be validly derived from
14076 			* B's {type definition} given the empty set as
14077 			* defined in Type Derivation OK (Simple) (�3.14.6)."
14078 			*/
14079 			xmlSchemaPAttrUseErr4(pctxt,
14080 			    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
14081 			    WXS_ITEM_NODE(item), item, cur,
14082 			    "The attribute declaration's %s "
14083 			    "is not validly derived from "
14084 			    "the corresponding %s of the "
14085 			    "attribute declaration in the %s %s",
14086 			    xmlSchemaGetComponentDesignation(&strA,
14087 				WXS_ATTRUSE_TYPEDEF(cur)),
14088 			    xmlSchemaGetComponentDesignation(&strB,
14089 				WXS_ATTRUSE_TYPEDEF(bcur)),
14090 			    WXS_ACTION_STR(action),
14091 			    xmlSchemaGetComponentDesignation(&strC, baseItem));
14092 			    /* xmlSchemaGetComponentDesignation(&str, baseItem), */
14093 			FREE_AND_NULL(strA);
14094 			FREE_AND_NULL(strB);
14095 			FREE_AND_NULL(strC);
14096 			/* err = pctxt->err; */
14097 		    } else {
14098 			/*
14099 			* 2.1.3 [Definition:]  Let the effective value
14100 			* constraint of an attribute use be its {value
14101 			* constraint}, if present, otherwise its {attribute
14102 			* declaration}'s {value constraint} .
14103 			*/
14104 			xmlSchemaGetEffectiveValueConstraint(bcur,
14105 			    &effFixed, &bEffValue, NULL);
14106 			/*
14107 			* 2.1.3 ... one of the following must be true
14108 			*
14109 			* 2.1.3.1 B's �effective value constraint� is
14110 			* �absent� or default.
14111 			*/
14112 			if ((bEffValue != NULL) &&
14113 			    (effFixed == 1)) {
14114 			    const xmlChar *rEffValue = NULL;
14115 
14116 			    xmlSchemaGetEffectiveValueConstraint(bcur,
14117 				&effFixed, &rEffValue, NULL);
14118 			    /*
14119 			    * 2.1.3.2 R's �effective value constraint� is
14120 			    * fixed with the same string as B's.
14121 			    * MAYBE TODO: Compare the computed values.
14122 			    *       Hmm, it says "same string" so
14123 			    *       string-equality might really be sufficient.
14124 			    */
14125 			    if ((effFixed == 0) ||
14126 				(! WXS_ARE_DEFAULT_STR_EQUAL(rEffValue, bEffValue)))
14127 			    {
14128 				xmlChar *str = NULL;
14129 
14130 				xmlSchemaPAttrUseErr4(pctxt,
14131 				    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
14132 				    WXS_ITEM_NODE(item), item, cur,
14133 				    "The effective value constraint of the "
14134 				    "attribute use is inconsistent with "
14135 				    "its correspondent in the %s %s",
14136 				    WXS_ACTION_STR(action),
14137 				    xmlSchemaGetComponentDesignation(&str,
14138 					baseItem),
14139 				    NULL, NULL);
14140 				FREE_AND_NULL(str);
14141 				/* err = pctxt->err; */
14142 			    }
14143 			}
14144 		    }
14145 		    break;
14146 		}
14147 	    }
14148 not_found:
14149 	    if (!found) {
14150 		/*
14151 		* (2.2) "otherwise the {base type definition} must have an
14152 		* {attribute wildcard} and the {target namespace} of the
14153 		* R's {attribute declaration} must be �valid� with respect
14154 		* to that wildcard, as defined in Wildcard allows Namespace
14155 		* Name (�3.10.4)."
14156 		*/
14157 		if ((baseWild == NULL) ||
14158 		    (xmlSchemaCheckCVCWildcardNamespace(baseWild,
14159 		    (WXS_ATTRUSE_DECL(cur))->targetNamespace) != 0))
14160 		{
14161 		    xmlChar *str = NULL;
14162 
14163 		    xmlSchemaPAttrUseErr4(pctxt,
14164 			XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
14165 			WXS_ITEM_NODE(item), item, cur,
14166 			"Neither a matching attribute use, "
14167 			"nor a matching wildcard exists in the %s %s",
14168 			WXS_ACTION_STR(action),
14169 			xmlSchemaGetComponentDesignation(&str, baseItem),
14170 			NULL, NULL);
14171 		    FREE_AND_NULL(str);
14172 		    /* err = pctxt->err; */
14173 		}
14174 	    }
14175 	}
14176     }
14177     /*
14178     * SPEC derivation-ok-restriction (3):
14179     * (3) "For each attribute use in the {attribute uses} of the {base type
14180     * definition} whose {required} is true, there must be an attribute
14181     * use with an {attribute declaration} with the same {name} and
14182     * {target namespace} as its {attribute declaration} in the {attribute
14183     * uses} of the complex type definition itself whose {required} is true.
14184     */
14185     if (baseUses != NULL) {
14186 	for (j = 0; j < baseUses->nbItems; j++) {
14187 	    bcur = baseUses->items[j];
14188 	    if (bcur->occurs != XML_SCHEMAS_ATTR_USE_REQUIRED)
14189 		continue;
14190 	    found = 0;
14191 	    if (uses != NULL) {
14192 		for (i = 0; i < uses->nbItems; i++) {
14193 		    cur = uses->items[i];
14194 		    if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14195 			WXS_ATTRUSE_DECL_NAME(bcur)) &&
14196 			(WXS_ATTRUSE_DECL_TNS(cur) ==
14197 			WXS_ATTRUSE_DECL_TNS(bcur))) {
14198 			found = 1;
14199 			break;
14200 		    }
14201 		}
14202 	    }
14203 	    if (!found) {
14204 		xmlChar *strA = NULL, *strB = NULL;
14205 
14206 		xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14207 		    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
14208 		    NULL, item,
14209 		    "A matching attribute use for the "
14210 		    "'required' %s of the %s %s is missing",
14211 		    xmlSchemaGetComponentDesignation(&strA, bcur),
14212 		    WXS_ACTION_STR(action),
14213 		    xmlSchemaGetComponentDesignation(&strB, baseItem),
14214 		    NULL);
14215 		FREE_AND_NULL(strA);
14216 		FREE_AND_NULL(strB);
14217 	    }
14218 	}
14219     }
14220     /*
14221     * derivation-ok-restriction (4)
14222     */
14223     if (wild != NULL) {
14224 	/*
14225 	* (4) "If there is an {attribute wildcard}, all of the
14226 	* following must be true:"
14227 	*/
14228 	if (baseWild == NULL) {
14229 	    xmlChar *str = NULL;
14230 
14231 	    /*
14232 	    * (4.1) "The {base type definition} must also have one."
14233 	    */
14234 	    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14235 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
14236 		NULL, item,
14237 		"The %s has an attribute wildcard, "
14238 		"but the %s %s '%s' does not have one",
14239 		WXS_ITEM_TYPE_NAME(item),
14240 		WXS_ACTION_STR(action),
14241 		WXS_ITEM_TYPE_NAME(baseItem),
14242 		xmlSchemaGetComponentQName(&str, baseItem));
14243 	    FREE_AND_NULL(str);
14244 	    return(pctxt->err);
14245 	} else if ((baseWild->any == 0) &&
14246 		xmlSchemaCheckCOSNSSubset(wild, baseWild))
14247 	{
14248 	    xmlChar *str = NULL;
14249 	    /*
14250 	    * (4.2) "The complex type definition's {attribute wildcard}'s
14251 	    * {namespace constraint} must be a subset of the {base type
14252 	    * definition}'s {attribute wildcard}'s {namespace constraint},
14253 	    * as defined by Wildcard Subset (�3.10.6)."
14254 	    */
14255 	    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14256 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
14257 		NULL, item,
14258 		"The attribute wildcard is not a valid "
14259 		"subset of the wildcard in the %s %s '%s'",
14260 		WXS_ACTION_STR(action),
14261 		WXS_ITEM_TYPE_NAME(baseItem),
14262 		xmlSchemaGetComponentQName(&str, baseItem),
14263 		NULL);
14264 	    FREE_AND_NULL(str);
14265 	    return(pctxt->err);
14266 	}
14267 	/* 4.3 Unless the {base type definition} is the �ur-type
14268 	* definition�, the complex type definition's {attribute
14269 	* wildcard}'s {process contents} must be identical to or
14270 	* stronger than the {base type definition}'s {attribute
14271 	* wildcard}'s {process contents}, where strict is stronger
14272 	* than lax is stronger than skip.
14273 	*/
14274 	if ((! WXS_IS_ANYTYPE(baseItem)) &&
14275 	    (wild->processContents < baseWild->processContents)) {
14276 	    xmlChar *str = NULL;
14277 	    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14278 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
14279 		NULL, baseItem,
14280 		"The {process contents} of the attribute wildcard is "
14281 		"weaker than the one in the %s %s '%s'",
14282 		WXS_ACTION_STR(action),
14283 		WXS_ITEM_TYPE_NAME(baseItem),
14284 		xmlSchemaGetComponentQName(&str, baseItem),
14285 		NULL);
14286 	    FREE_AND_NULL(str)
14287 		return(pctxt->err);
14288 	}
14289     }
14290     return(0);
14291 }
14292 
14293 
14294 static int
14295 xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
14296 				  xmlSchemaBasicItemPtr item,
14297 				  xmlSchemaWildcardPtr *completeWild,
14298 				  xmlSchemaItemListPtr list,
14299 				  xmlSchemaItemListPtr prohibs);
14300 /**
14301  * xmlSchemaFixupTypeAttributeUses:
14302  * @ctxt:  the schema parser context
14303  * @type:  the complex type definition
14304  *
14305  *
14306  * Builds the wildcard and the attribute uses on the given complex type.
14307  * Returns -1 if an internal error occurs, 0 otherwise.
14308  *
14309  * ATTENTION TODO: Experimantally this uses pointer comparisons for
14310  * strings, so recheck this if we start to hardcode some schemata, since
14311  * they might not be in the same dict.
14312  * NOTE: It is allowed to "extend" the xs:anyType type.
14313  */
14314 static int
xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)14315 xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt,
14316 				  xmlSchemaTypePtr type)
14317 {
14318     xmlSchemaTypePtr baseType = NULL;
14319     xmlSchemaAttributeUsePtr use;
14320     xmlSchemaItemListPtr uses, baseUses, prohibs = NULL;
14321 
14322     if (type->baseType == NULL) {
14323 	PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14324 	    "no base type");
14325         return (-1);
14326     }
14327     baseType = type->baseType;
14328     if (WXS_IS_TYPE_NOT_FIXED(baseType))
14329 	if (xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt) == -1)
14330 	    return(-1);
14331 
14332     uses = type->attrUses;
14333     baseUses = baseType->attrUses;
14334     /*
14335     * Expand attribute group references. And build the 'complete'
14336     * wildcard, i.e. intersect multiple wildcards.
14337     * Move attribute prohibitions into a separate list.
14338     */
14339     if (uses != NULL) {
14340 	if (WXS_IS_RESTRICTION(type)) {
14341 	    /*
14342 	    * This one will transfer all attr. prohibitions
14343 	    * into pctxt->attrProhibs.
14344 	    */
14345 	    if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14346 		WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14347 		pctxt->attrProhibs) == -1)
14348 	    {
14349 		PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14350 		"failed to expand attributes");
14351 	    }
14352 	    if (pctxt->attrProhibs->nbItems != 0)
14353 		prohibs = pctxt->attrProhibs;
14354 	} else {
14355 	    if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14356 		WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14357 		NULL) == -1)
14358 	    {
14359 		PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14360 		"failed to expand attributes");
14361 	    }
14362 	}
14363     }
14364     /*
14365     * Inherit the attribute uses of the base type.
14366     */
14367     if (baseUses != NULL) {
14368 	int i, j;
14369 	xmlSchemaAttributeUseProhibPtr pro;
14370 
14371 	if (WXS_IS_RESTRICTION(type)) {
14372 	    int usesCount;
14373 	    xmlSchemaAttributeUsePtr tmp;
14374 
14375 	    if (uses != NULL)
14376 		usesCount = uses->nbItems;
14377 	    else
14378 		usesCount = 0;
14379 
14380 	    /* Restriction. */
14381 	    for (i = 0; i < baseUses->nbItems; i++) {
14382 		use = baseUses->items[i];
14383 		if (prohibs) {
14384 		    /*
14385 		    * Filter out prohibited uses.
14386 		    */
14387 		    for (j = 0; j < prohibs->nbItems; j++) {
14388 			pro = prohibs->items[j];
14389 			if ((WXS_ATTRUSE_DECL_NAME(use) == pro->name) &&
14390 			    (WXS_ATTRUSE_DECL_TNS(use) ==
14391 				pro->targetNamespace))
14392 			{
14393 			    goto inherit_next;
14394 			}
14395 		    }
14396 		}
14397 		if (usesCount) {
14398 		    /*
14399 		    * Filter out existing uses.
14400 		    */
14401 		    for (j = 0; j < usesCount; j++) {
14402 			tmp = uses->items[j];
14403 			if ((WXS_ATTRUSE_DECL_NAME(use) ==
14404 				WXS_ATTRUSE_DECL_NAME(tmp)) &&
14405 			    (WXS_ATTRUSE_DECL_TNS(use) ==
14406 				WXS_ATTRUSE_DECL_TNS(tmp)))
14407 			{
14408 			    goto inherit_next;
14409 			}
14410 		    }
14411 		}
14412 		if (uses == NULL) {
14413 		    type->attrUses = xmlSchemaItemListCreate();
14414 		    if (type->attrUses == NULL)
14415 			goto exit_failure;
14416 		    uses = type->attrUses;
14417 		}
14418 		xmlSchemaItemListAddSize(uses, 2, use);
14419 inherit_next: {}
14420 	    }
14421 	} else {
14422 	    /* Extension. */
14423 	    for (i = 0; i < baseUses->nbItems; i++) {
14424 		use = baseUses->items[i];
14425 		if (uses == NULL) {
14426 		    type->attrUses = xmlSchemaItemListCreate();
14427 		    if (type->attrUses == NULL)
14428 			goto exit_failure;
14429 		    uses = type->attrUses;
14430 		}
14431 		xmlSchemaItemListAddSize(uses, baseUses->nbItems, use);
14432 	    }
14433 	}
14434     }
14435     /*
14436     * Shrink attr. uses.
14437     */
14438     if (uses) {
14439 	if (uses->nbItems == 0) {
14440 	    xmlSchemaItemListFree(uses);
14441 	    type->attrUses = NULL;
14442 	}
14443 	/*
14444 	* TODO: We could shrink the size of the array
14445 	* to fit the actual number of items.
14446 	*/
14447     }
14448     /*
14449     * Compute the complete wildcard.
14450     */
14451     if (WXS_IS_EXTENSION(type)) {
14452 	if (baseType->attributeWildcard != NULL) {
14453 	    /*
14454 	    * (3.2.2.1) "If the �base wildcard� is non-�absent�, then
14455 	    * the appropriate case among the following:"
14456 	    */
14457 	    if (type->attributeWildcard != NULL) {
14458 		/*
14459 		* Union the complete wildcard with the base wildcard.
14460 		* SPEC {attribute wildcard}
14461 		* (3.2.2.1.2) "otherwise a wildcard whose {process contents}
14462 		* and {annotation} are those of the �complete wildcard�,
14463 		* and whose {namespace constraint} is the intensional union
14464 		* of the {namespace constraint} of the �complete wildcard�
14465 		* and of the �base wildcard�, as defined in Attribute
14466 		* Wildcard Union (�3.10.6)."
14467 		*/
14468 		if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
14469 		    baseType->attributeWildcard) == -1)
14470 		    goto exit_failure;
14471 	    } else {
14472 		/*
14473 		* (3.2.2.1.1) "If the �complete wildcard� is �absent�,
14474 		* then the �base wildcard�."
14475 		*/
14476 		type->attributeWildcard = baseType->attributeWildcard;
14477 	    }
14478 	} else {
14479 	    /*
14480 	    * (3.2.2.2) "otherwise (the �base wildcard� is �absent�) the
14481 	    * �complete wildcard"
14482 	    * NOOP
14483 	    */
14484 	}
14485     } else {
14486 	/*
14487 	* SPEC {attribute wildcard}
14488 	* (3.1) "If the <restriction> alternative is chosen, then the
14489 	* �complete wildcard�;"
14490 	* NOOP
14491 	*/
14492     }
14493 
14494     return (0);
14495 
14496 exit_failure:
14497     return(-1);
14498 }
14499 
14500 /**
14501  * xmlSchemaTypeFinalContains:
14502  * @schema:  the schema
14503  * @type:  the type definition
14504  * @final: the final
14505  *
14506  * Evaluates if a type definition contains the given "final".
14507  * This does take "finalDefault" into account as well.
14508  *
14509  * Returns 1 if the type does containt the given "final",
14510  * 0 otherwise.
14511  */
14512 static int
xmlSchemaTypeFinalContains(xmlSchemaTypePtr type,int final)14513 xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
14514 {
14515     if (type == NULL)
14516 	return (0);
14517     if (type->flags & final)
14518 	return (1);
14519     else
14520 	return (0);
14521 }
14522 
14523 /**
14524  * xmlSchemaGetUnionSimpleTypeMemberTypes:
14525  * @type:  the Union Simple Type
14526  *
14527  * Returns a list of member types of @type if existing,
14528  * returns NULL otherwise.
14529  */
14530 static xmlSchemaTypeLinkPtr
xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)14531 xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
14532 {
14533     while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
14534 	if (type->memberTypes != NULL)
14535 	    return (type->memberTypes);
14536 	else
14537 	    type = type->baseType;
14538     }
14539     return (NULL);
14540 }
14541 
14542 /**
14543  * xmlSchemaGetParticleTotalRangeMin:
14544  * @particle: the particle
14545  *
14546  * Schema Component Constraint: Effective Total Range
14547  * (all and sequence) + (choice)
14548  *
14549  * Returns the minimun Effective Total Range.
14550  */
14551 static int
xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)14552 xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
14553 {
14554     if ((particle->children == NULL) ||
14555 	(particle->minOccurs == 0))
14556 	return (0);
14557     if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14558 	int min = -1, cur;
14559 	xmlSchemaParticlePtr part =
14560 	    (xmlSchemaParticlePtr) particle->children->children;
14561 
14562 	if (part == NULL)
14563 	    return (0);
14564 	while (part != NULL) {
14565 	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14566 		(part->children->type == XML_SCHEMA_TYPE_ANY))
14567 		cur = part->minOccurs;
14568 	    else
14569 		cur = xmlSchemaGetParticleTotalRangeMin(part);
14570 	    if (cur == 0)
14571 		return (0);
14572 	    if ((min > cur) || (min == -1))
14573 		min = cur;
14574 	    part = (xmlSchemaParticlePtr) part->next;
14575 	}
14576 	return (particle->minOccurs * min);
14577     } else {
14578 	/* <all> and <sequence> */
14579 	int sum = 0;
14580 	xmlSchemaParticlePtr part =
14581 	    (xmlSchemaParticlePtr) particle->children->children;
14582 
14583 	if (part == NULL)
14584 	    return (0);
14585 	do {
14586 	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14587 		(part->children->type == XML_SCHEMA_TYPE_ANY))
14588 		sum += part->minOccurs;
14589 	    else
14590 		sum += xmlSchemaGetParticleTotalRangeMin(part);
14591 	    part = (xmlSchemaParticlePtr) part->next;
14592 	} while (part != NULL);
14593 	return (particle->minOccurs * sum);
14594     }
14595 }
14596 
14597 /**
14598  * xmlSchemaGetParticleTotalRangeMax:
14599  * @particle: the particle
14600  *
14601  * Schema Component Constraint: Effective Total Range
14602  * (all and sequence) + (choice)
14603  *
14604  * Returns the maximum Effective Total Range.
14605  */
14606 static int
xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)14607 xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
14608 {
14609     if ((particle->children == NULL) ||
14610 	(particle->children->children == NULL))
14611 	return (0);
14612     if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14613 	int max = -1, cur;
14614 	xmlSchemaParticlePtr part =
14615 	    (xmlSchemaParticlePtr) particle->children->children;
14616 
14617 	for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14618 	    if (part->children == NULL)
14619 		continue;
14620 	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14621 		(part->children->type == XML_SCHEMA_TYPE_ANY))
14622 		cur = part->maxOccurs;
14623 	    else
14624 		cur = xmlSchemaGetParticleTotalRangeMax(part);
14625 	    if (cur == UNBOUNDED)
14626 		return (UNBOUNDED);
14627 	    if ((max < cur) || (max == -1))
14628 		max = cur;
14629 	}
14630 	/* TODO: Handle overflows? */
14631 	return (particle->maxOccurs * max);
14632     } else {
14633 	/* <all> and <sequence> */
14634 	int sum = 0, cur;
14635 	xmlSchemaParticlePtr part =
14636 	    (xmlSchemaParticlePtr) particle->children->children;
14637 
14638 	for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14639 	    if (part->children == NULL)
14640 		continue;
14641 	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14642 		(part->children->type == XML_SCHEMA_TYPE_ANY))
14643 		cur = part->maxOccurs;
14644 	    else
14645 		cur = xmlSchemaGetParticleTotalRangeMax(part);
14646 	    if (cur == UNBOUNDED)
14647 		return (UNBOUNDED);
14648 	    if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
14649 		return (UNBOUNDED);
14650 	    sum += cur;
14651 	}
14652 	/* TODO: Handle overflows? */
14653 	return (particle->maxOccurs * sum);
14654     }
14655 }
14656 
14657 /**
14658  * xmlSchemaIsParticleEmptiable:
14659  * @particle: the particle
14660  *
14661  * Schema Component Constraint: Particle Emptiable
14662  * Checks whether the given particle is emptiable.
14663  *
14664  * Returns 1 if emptiable, 0 otherwise.
14665  */
14666 static int
xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)14667 xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
14668 {
14669     /*
14670     * SPEC (1) "Its {min occurs} is 0."
14671     */
14672     if ((particle == NULL) || (particle->minOccurs == 0) ||
14673 	(particle->children == NULL))
14674 	return (1);
14675     /*
14676     * SPEC (2) "Its {term} is a group and the minimum part of the
14677     * effective total range of that group, [...] is 0."
14678     */
14679     if (WXS_IS_MODEL_GROUP(particle->children)) {
14680 	if (xmlSchemaGetParticleTotalRangeMin(particle) == 0)
14681 	    return (1);
14682     }
14683     return (0);
14684 }
14685 
14686 /**
14687  * xmlSchemaCheckCOSSTDerivedOK:
14688  * @actxt: a context
14689  * @type:  the derived simple type definition
14690  * @baseType:  the base type definition
14691  * @subset: the subset of ('restriction', ect.)
14692  *
14693  * Schema Component Constraint:
14694  * Type Derivation OK (Simple) (cos-st-derived-OK)
14695  *
14696  * Checks wheter @type can be validly
14697  * derived from @baseType.
14698  *
14699  * Returns 0 on success, an positive error code otherwise.
14700  */
14701 static int
xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,xmlSchemaTypePtr type,xmlSchemaTypePtr baseType,int subset)14702 xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
14703 			     xmlSchemaTypePtr type,
14704 			     xmlSchemaTypePtr baseType,
14705 			     int subset)
14706 {
14707     /*
14708     * 1 They are the same type definition.
14709     * TODO: The identy check might have to be more complex than this.
14710     */
14711     if (type == baseType)
14712 	return (0);
14713     /*
14714     * 2.1 restriction is not in the subset, or in the {final}
14715     * of its own {base type definition};
14716     *
14717     * NOTE that this will be used also via "xsi:type".
14718     *
14719     * TODO: Revise this, it looks strange. How can the "type"
14720     * not be fixed or *in* fixing?
14721     */
14722     if (WXS_IS_TYPE_NOT_FIXED(type))
14723 	if (xmlSchemaTypeFixup(type, actxt) == -1)
14724 	    return(-1);
14725     if (WXS_IS_TYPE_NOT_FIXED(baseType))
14726 	if (xmlSchemaTypeFixup(baseType, actxt) == -1)
14727 	    return(-1);
14728     if ((subset & SUBSET_RESTRICTION) ||
14729 	(xmlSchemaTypeFinalContains(type->baseType,
14730 	    XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
14731 	return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
14732     }
14733     /* 2.2 */
14734     if (type->baseType == baseType) {
14735 	/*
14736 	* 2.2.1 D's �base type definition� is B.
14737 	*/
14738 	return (0);
14739     }
14740     /*
14741     * 2.2.2 D's �base type definition� is not the �ur-type definition�
14742     * and is validly derived from B given the subset, as defined by this
14743     * constraint.
14744     */
14745     if ((! WXS_IS_ANYTYPE(type->baseType)) &&
14746 	(xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
14747 	    baseType, subset) == 0)) {
14748 	return (0);
14749     }
14750     /*
14751     * 2.2.3 D's {variety} is list or union and B is the �simple ur-type
14752     * definition�.
14753     */
14754     if (WXS_IS_ANY_SIMPLE_TYPE(baseType) &&
14755 	(WXS_IS_LIST(type) || WXS_IS_UNION(type))) {
14756 	return (0);
14757     }
14758     /*
14759     * 2.2.4 B's {variety} is union and D is validly derived from a type
14760     * definition in B's {member type definitions} given the subset, as
14761     * defined by this constraint.
14762     *
14763     * NOTE: This seems not to involve built-in types, since there is no
14764     * built-in Union Simple Type.
14765     */
14766     if (WXS_IS_UNION(baseType)) {
14767 	xmlSchemaTypeLinkPtr cur;
14768 
14769 	cur = baseType->memberTypes;
14770 	while (cur != NULL) {
14771 	    if (WXS_IS_TYPE_NOT_FIXED(cur->type))
14772 		if (xmlSchemaTypeFixup(cur->type, actxt) == -1)
14773 		    return(-1);
14774 	    if (xmlSchemaCheckCOSSTDerivedOK(actxt,
14775 		    type, cur->type, subset) == 0)
14776 	    {
14777 		/*
14778 		* It just has to be validly derived from at least one
14779 		* member-type.
14780 		*/
14781 		return (0);
14782 	    }
14783 	    cur = cur->next;
14784 	}
14785     }
14786     return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
14787 }
14788 
14789 /**
14790  * xmlSchemaCheckTypeDefCircularInternal:
14791  * @pctxt:  the schema parser context
14792  * @ctxtType:  the type definition
14793  * @ancestor: an ancestor of @ctxtType
14794  *
14795  * Checks st-props-correct (2) + ct-props-correct (3).
14796  * Circular type definitions are not allowed.
14797  *
14798  * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
14799  * circular, 0 otherwise.
14800  */
14801 static int
xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr ctxtType,xmlSchemaTypePtr ancestor)14802 xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
14803 			   xmlSchemaTypePtr ctxtType,
14804 			   xmlSchemaTypePtr ancestor)
14805 {
14806     int ret;
14807 
14808     if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
14809 	return (0);
14810 
14811     if (ctxtType == ancestor) {
14812 	xmlSchemaPCustomErr(pctxt,
14813 	    XML_SCHEMAP_ST_PROPS_CORRECT_2,
14814 	    WXS_BASIC_CAST ctxtType, WXS_ITEM_NODE(ctxtType),
14815 	    "The definition is circular", NULL);
14816 	return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
14817     }
14818     if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
14819 	/*
14820 	* Avoid inifinite recursion on circular types not yet checked.
14821 	*/
14822 	return (0);
14823     }
14824     ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
14825     ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
14826 	ancestor->baseType);
14827     ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
14828     return (ret);
14829 }
14830 
14831 /**
14832  * xmlSchemaCheckTypeDefCircular:
14833  * @item:  the complex/simple type definition
14834  * @ctxt:  the parser context
14835  * @name:  the name
14836  *
14837  * Checks for circular type definitions.
14838  */
14839 static void
xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,xmlSchemaParserCtxtPtr ctxt)14840 xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
14841 			      xmlSchemaParserCtxtPtr ctxt)
14842 {
14843     if ((item == NULL) ||
14844 	(item->type == XML_SCHEMA_TYPE_BASIC) ||
14845 	(item->baseType == NULL))
14846 	return;
14847     xmlSchemaCheckTypeDefCircularInternal(ctxt, item,
14848 	item->baseType);
14849 }
14850 
14851 /*
14852 * Simple Type Definition Representation OK (src-simple-type) 4
14853 *
14854 * "4 Circular union type definition is disallowed. That is, if the
14855 * <union> alternative is chosen, there must not be any entries in the
14856 * memberTypes [attribute] at any depth which resolve to the component
14857 * corresponding to the <simpleType>."
14858 *
14859 * Note that this should work on the *representation* of a component,
14860 * thus assumes any union types in the member types not being yet
14861 * substituted. At this stage we need the variety of the types
14862 * to be already computed.
14863 */
14864 static int
xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr ctxType,xmlSchemaTypeLinkPtr members)14865 xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,
14866 					xmlSchemaTypePtr ctxType,
14867 					xmlSchemaTypeLinkPtr members)
14868 {
14869     xmlSchemaTypeLinkPtr member;
14870     xmlSchemaTypePtr memberType;
14871 
14872     member = members;
14873     while (member != NULL) {
14874 	memberType = member->type;
14875 	while ((memberType != NULL) &&
14876 	    (memberType->type != XML_SCHEMA_TYPE_BASIC)) {
14877 	    if (memberType == ctxType) {
14878 		xmlSchemaPCustomErr(pctxt,
14879 		    XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
14880 		    WXS_BASIC_CAST ctxType, NULL,
14881 		    "The union type definition is circular", NULL);
14882 		return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
14883 	    }
14884 	    if ((WXS_IS_UNION(memberType)) &&
14885 		((memberType->flags & XML_SCHEMAS_TYPE_MARKED) == 0))
14886 	    {
14887 		int res;
14888 		memberType->flags |= XML_SCHEMAS_TYPE_MARKED;
14889 		res = xmlSchemaCheckUnionTypeDefCircularRecur(pctxt,
14890 		    ctxType,
14891 		    xmlSchemaGetUnionSimpleTypeMemberTypes(memberType));
14892 		memberType->flags ^= XML_SCHEMAS_TYPE_MARKED;
14893 		if (res != 0)
14894 		    return(res);
14895 	    }
14896 	    memberType = memberType->baseType;
14897 	}
14898 	member = member->next;
14899     }
14900     return(0);
14901 }
14902 
14903 static int
xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)14904 xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,
14905 				   xmlSchemaTypePtr type)
14906 {
14907     if (! WXS_IS_UNION(type))
14908 	return(0);
14909     return(xmlSchemaCheckUnionTypeDefCircularRecur(pctxt, type,
14910 	type->memberTypes));
14911 }
14912 
14913 /**
14914  * xmlSchemaResolveTypeReferences:
14915  * @item:  the complex/simple type definition
14916  * @ctxt:  the parser context
14917  * @name:  the name
14918  *
14919  * Resolvese type definition references
14920  */
14921 static void
xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,xmlSchemaParserCtxtPtr ctxt)14922 xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,
14923 			 xmlSchemaParserCtxtPtr ctxt)
14924 {
14925     if (typeDef == NULL)
14926 	return;
14927 
14928     /*
14929     * Resolve the base type.
14930     */
14931     if (typeDef->baseType == NULL) {
14932 	typeDef->baseType = xmlSchemaGetType(ctxt->schema,
14933 	    typeDef->base, typeDef->baseNs);
14934 	if (typeDef->baseType == NULL) {
14935 	    xmlSchemaPResCompAttrErr(ctxt,
14936 		XML_SCHEMAP_SRC_RESOLVE,
14937 		WXS_BASIC_CAST typeDef, typeDef->node,
14938 		"base", typeDef->base, typeDef->baseNs,
14939 		XML_SCHEMA_TYPE_SIMPLE, NULL);
14940 	    return;
14941 	}
14942     }
14943     if (WXS_IS_SIMPLE(typeDef)) {
14944 	if (WXS_IS_UNION(typeDef)) {
14945 	    /*
14946 	    * Resolve the memberTypes.
14947 	    */
14948 	    xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
14949 	    return;
14950 	} else if (WXS_IS_LIST(typeDef)) {
14951 	    /*
14952 	    * Resolve the itemType.
14953 	    */
14954 	    if ((typeDef->subtypes == NULL) && (typeDef->base != NULL)) {
14955 
14956 		typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
14957 		    typeDef->base, typeDef->baseNs);
14958 
14959 		if ((typeDef->subtypes == NULL) ||
14960 		    (! WXS_IS_SIMPLE(typeDef->subtypes)))
14961 		{
14962 		    typeDef->subtypes = NULL;
14963 		    xmlSchemaPResCompAttrErr(ctxt,
14964 			XML_SCHEMAP_SRC_RESOLVE,
14965 			WXS_BASIC_CAST typeDef, typeDef->node,
14966 			"itemType", typeDef->base, typeDef->baseNs,
14967 			XML_SCHEMA_TYPE_SIMPLE, NULL);
14968 		}
14969 	    }
14970 	    return;
14971 	}
14972     }
14973     /*
14974     * The ball of letters below means, that if we have a particle
14975     * which has a QName-helper component as its {term}, we want
14976     * to resolve it...
14977     */
14978     else if ((WXS_TYPE_CONTENTTYPE(typeDef) != NULL) &&
14979 	((WXS_TYPE_CONTENTTYPE(typeDef))->type ==
14980 	    XML_SCHEMA_TYPE_PARTICLE) &&
14981 	(WXS_TYPE_PARTICLE_TERM(typeDef) != NULL) &&
14982 	((WXS_TYPE_PARTICLE_TERM(typeDef))->type ==
14983 	    XML_SCHEMA_EXTRA_QNAMEREF))
14984     {
14985 	xmlSchemaQNameRefPtr ref =
14986 	    WXS_QNAME_CAST WXS_TYPE_PARTICLE_TERM(typeDef);
14987 	xmlSchemaModelGroupDefPtr groupDef;
14988 
14989 	/*
14990 	* URGENT TODO: Test this.
14991 	*/
14992 	WXS_TYPE_PARTICLE_TERM(typeDef) = NULL;
14993 	/*
14994 	* Resolve the MG definition reference.
14995 	*/
14996 	groupDef =
14997 	    WXS_MODEL_GROUPDEF_CAST xmlSchemaGetNamedComponent(ctxt->schema,
14998 		ref->itemType, ref->name, ref->targetNamespace);
14999 	if (groupDef == NULL) {
15000 	    xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
15001 		NULL, WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)),
15002 		"ref", ref->name, ref->targetNamespace, ref->itemType,
15003 		NULL);
15004 	    /* Remove the particle. */
15005 	    WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15006 	} else if (WXS_MODELGROUPDEF_MODEL(groupDef) == NULL)
15007 	    /* Remove the particle. */
15008 	    WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15009 	else {
15010 	    /*
15011 	    * Assign the MG definition's {model group} to the
15012 	    * particle's {term}.
15013 	    */
15014 	    WXS_TYPE_PARTICLE_TERM(typeDef) = WXS_MODELGROUPDEF_MODEL(groupDef);
15015 
15016 	    if (WXS_MODELGROUPDEF_MODEL(groupDef)->type == XML_SCHEMA_TYPE_ALL) {
15017 		/*
15018 		* SPEC cos-all-limited (1.2)
15019 		* "1.2 the {term} property of a particle with
15020 		* {max occurs}=1 which is part of a pair which constitutes
15021 		* the {content type} of a complex type definition."
15022 		*/
15023 		if ((WXS_TYPE_PARTICLE(typeDef))->maxOccurs != 1) {
15024 		    xmlSchemaCustomErr(ACTXT_CAST ctxt,
15025 			/* TODO: error code */
15026 			XML_SCHEMAP_COS_ALL_LIMITED,
15027 			WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)), NULL,
15028 			"The particle's {max occurs} must be 1, since the "
15029 			"reference resolves to an 'all' model group",
15030 			NULL, NULL);
15031 		}
15032 	    }
15033 	}
15034     }
15035 }
15036 
15037 
15038 
15039 /**
15040  * xmlSchemaCheckSTPropsCorrect:
15041  * @ctxt:  the schema parser context
15042  * @type:  the simple type definition
15043  *
15044  * Checks st-props-correct.
15045  *
15046  * Returns 0 if the properties are correct,
15047  * if not, a positive error code and -1 on internal
15048  * errors.
15049  */
15050 static int
xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)15051 xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
15052 			     xmlSchemaTypePtr type)
15053 {
15054     xmlSchemaTypePtr baseType = type->baseType;
15055     xmlChar *str = NULL;
15056 
15057     /* STATE: error funcs converted. */
15058     /*
15059     * Schema Component Constraint: Simple Type Definition Properties Correct
15060     *
15061     * NOTE: This is somehow redundant, since we actually built a simple type
15062     * to have all the needed information; this acts as an self test.
15063     */
15064     /* Base type: If the datatype has been �derived� by �restriction�
15065     * then the Simple Type Definition component from which it is �derived�,
15066     * otherwise the Simple Type Definition for anySimpleType (�4.1.6).
15067     */
15068     if (baseType == NULL) {
15069 	/*
15070 	* TODO: Think about: "modulo the impact of Missing
15071 	* Sub-components (�5.3)."
15072 	*/
15073 	xmlSchemaPCustomErr(ctxt,
15074 	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15075 	    WXS_BASIC_CAST type, NULL,
15076 	    "No base type existent", NULL);
15077 	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15078 
15079     }
15080     if (! WXS_IS_SIMPLE(baseType)) {
15081 	xmlSchemaPCustomErr(ctxt,
15082 	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15083 	    WXS_BASIC_CAST type, NULL,
15084 	    "The base type '%s' is not a simple type",
15085 	    xmlSchemaGetComponentQName(&str, baseType));
15086 	FREE_AND_NULL(str)
15087 	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15088     }
15089     if ( (WXS_IS_LIST(type) || WXS_IS_UNION(type)) &&
15090 	 (WXS_IS_RESTRICTION(type) == 0) &&
15091 	 (! WXS_IS_ANY_SIMPLE_TYPE(baseType))) {
15092 	xmlSchemaPCustomErr(ctxt,
15093 	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15094 	    WXS_BASIC_CAST type, NULL,
15095 	    "A type, derived by list or union, must have"
15096 	    "the simple ur-type definition as base type, not '%s'",
15097 	    xmlSchemaGetComponentQName(&str, baseType));
15098 	FREE_AND_NULL(str)
15099 	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15100     }
15101     /*
15102     * Variety: One of {atomic, list, union}.
15103     */
15104     if ((! WXS_IS_ATOMIC(type)) && (! WXS_IS_UNION(type)) &&
15105 	(! WXS_IS_LIST(type))) {
15106 	xmlSchemaPCustomErr(ctxt,
15107 	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15108 	    WXS_BASIC_CAST type, NULL,
15109 	    "The variety is absent", NULL);
15110 	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15111     }
15112     /* TODO: Finish this. Hmm, is this finished? */
15113 
15114     /*
15115     * 3 The {final} of the {base type definition} must not contain restriction.
15116     */
15117     if (xmlSchemaTypeFinalContains(baseType,
15118 	XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15119 	xmlSchemaPCustomErr(ctxt,
15120 	    XML_SCHEMAP_ST_PROPS_CORRECT_3,
15121 	    WXS_BASIC_CAST type, NULL,
15122 	    "The 'final' of its base type '%s' must not contain "
15123 	    "'restriction'",
15124 	    xmlSchemaGetComponentQName(&str, baseType));
15125 	FREE_AND_NULL(str)
15126 	return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
15127     }
15128 
15129     /*
15130     * 2 All simple type definitions must be derived ultimately from the �simple
15131     * ur-type definition (so� circular definitions are disallowed). That is, it
15132     * must be possible to reach a built-in primitive datatype or the �simple
15133     * ur-type definition� by repeatedly following the {base type definition}.
15134     *
15135     * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
15136     */
15137     return (0);
15138 }
15139 
15140 /**
15141  * xmlSchemaCheckCOSSTRestricts:
15142  * @ctxt:  the schema parser context
15143  * @type:  the simple type definition
15144  *
15145  * Schema Component Constraint:
15146  * Derivation Valid (Restriction, Simple) (cos-st-restricts)
15147 
15148  * Checks if the given @type (simpleType) is derived validly by restriction.
15149  * STATUS:
15150  *
15151  * Returns -1 on internal errors, 0 if the type is validly derived,
15152  * a positive error code otherwise.
15153  */
15154 static int
xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)15155 xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
15156 			     xmlSchemaTypePtr type)
15157 {
15158     xmlChar *str = NULL;
15159 
15160     if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
15161 	PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15162 	    "given type is not a user-derived simpleType");
15163 	return (-1);
15164     }
15165 
15166     if (WXS_IS_ATOMIC(type)) {
15167 	xmlSchemaTypePtr primitive;
15168 	/*
15169 	* 1.1 The {base type definition} must be an atomic simple
15170 	* type definition or a built-in primitive datatype.
15171 	*/
15172 	if (! WXS_IS_ATOMIC(type->baseType)) {
15173 	    xmlSchemaPCustomErr(pctxt,
15174 		XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
15175 		WXS_BASIC_CAST type, NULL,
15176 		"The base type '%s' is not an atomic simple type",
15177 		xmlSchemaGetComponentQName(&str, type->baseType));
15178 	    FREE_AND_NULL(str)
15179 	    return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
15180 	}
15181 	/* 1.2 The {final} of the {base type definition} must not contain
15182 	* restriction.
15183 	*/
15184 	/* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
15185 	if (xmlSchemaTypeFinalContains(type->baseType,
15186 	    XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15187 	    xmlSchemaPCustomErr(pctxt,
15188 		XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
15189 		WXS_BASIC_CAST type, NULL,
15190 		"The final of its base type '%s' must not contain 'restriction'",
15191 		xmlSchemaGetComponentQName(&str, type->baseType));
15192 	    FREE_AND_NULL(str)
15193 	    return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
15194 	}
15195 
15196 	/*
15197 	* 1.3.1 DF must be an allowed constraining facet for the {primitive
15198 	* type definition}, as specified in the appropriate subsection of 3.2
15199 	* Primitive datatypes.
15200 	*/
15201 	if (type->facets != NULL) {
15202 	    xmlSchemaFacetPtr facet;
15203 	    int ok = 1;
15204 
15205 	    primitive = xmlSchemaGetPrimitiveType(type);
15206 	    if (primitive == NULL) {
15207 		PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15208 		    "failed to get primitive type");
15209 		return (-1);
15210 	    }
15211 	    facet = type->facets;
15212 	    do {
15213 		if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
15214 		    ok = 0;
15215 		    xmlSchemaPIllegalFacetAtomicErr(pctxt,
15216 			XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
15217 			type, primitive, facet);
15218 		}
15219 		facet = facet->next;
15220 	    } while (facet != NULL);
15221 	    if (ok == 0)
15222 		return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
15223 	}
15224 	/*
15225 	* SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
15226 	* of the {base type definition} (call this BF),then the DF's {value}
15227 	* must be a valid restriction of BF's {value} as defined in
15228 	* [XML Schemas: Datatypes]."
15229 	*
15230 	* NOTE (1.3.2) Facet derivation constraints are currently handled in
15231 	* xmlSchemaDeriveAndValidateFacets()
15232 	*/
15233     } else if (WXS_IS_LIST(type)) {
15234 	xmlSchemaTypePtr itemType = NULL;
15235 
15236 	itemType = type->subtypes;
15237 	if ((itemType == NULL) || (! WXS_IS_SIMPLE(itemType))) {
15238 	    PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15239 		"failed to evaluate the item type");
15240 	    return (-1);
15241 	}
15242 	if (WXS_IS_TYPE_NOT_FIXED(itemType))
15243 	    xmlSchemaTypeFixup(itemType, ACTXT_CAST pctxt);
15244 	/*
15245 	* 2.1 The {item type definition} must have a {variety} of atomic or
15246 	* union (in which case all the {member type definitions}
15247 	* must be atomic).
15248 	*/
15249 	if ((! WXS_IS_ATOMIC(itemType)) &&
15250 	    (! WXS_IS_UNION(itemType))) {
15251 	    xmlSchemaPCustomErr(pctxt,
15252 		XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15253 		WXS_BASIC_CAST type, NULL,
15254 		"The item type '%s' does not have a variety of atomic or union",
15255 		xmlSchemaGetComponentQName(&str, itemType));
15256 	    FREE_AND_NULL(str)
15257 	    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15258 	} else if (WXS_IS_UNION(itemType)) {
15259 	    xmlSchemaTypeLinkPtr member;
15260 
15261 	    member = itemType->memberTypes;
15262 	    while (member != NULL) {
15263 		if (! WXS_IS_ATOMIC(member->type)) {
15264 		    xmlSchemaPCustomErr(pctxt,
15265 			XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15266 			WXS_BASIC_CAST type, NULL,
15267 			"The item type is a union type, but the "
15268 			"member type '%s' of this item type is not atomic",
15269 			xmlSchemaGetComponentQName(&str, member->type));
15270 		    FREE_AND_NULL(str)
15271 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15272 		}
15273 		member = member->next;
15274 	    }
15275 	}
15276 
15277 	if (WXS_IS_ANY_SIMPLE_TYPE(type->baseType)) {
15278 	    xmlSchemaFacetPtr facet;
15279 	    /*
15280 	    * This is the case if we have: <simpleType><list ..
15281 	    */
15282 	    /*
15283 	    * 2.3.1
15284 	    * 2.3.1.1 The {final} of the {item type definition} must not
15285 	    * contain list.
15286 	    */
15287 	    if (xmlSchemaTypeFinalContains(itemType,
15288 		XML_SCHEMAS_TYPE_FINAL_LIST)) {
15289 		xmlSchemaPCustomErr(pctxt,
15290 		    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
15291 		    WXS_BASIC_CAST type, NULL,
15292 		    "The final of its item type '%s' must not contain 'list'",
15293 		    xmlSchemaGetComponentQName(&str, itemType));
15294 		FREE_AND_NULL(str)
15295 		return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
15296 	    }
15297 	    /*
15298 	    * 2.3.1.2 The {facets} must only contain the whiteSpace
15299 	    * facet component.
15300 	    * OPTIMIZE TODO: the S4S already disallows any facet
15301 	    * to be specified.
15302 	    */
15303 	    if (type->facets != NULL) {
15304 		facet = type->facets;
15305 		do {
15306 		    if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
15307 			xmlSchemaPIllegalFacetListUnionErr(pctxt,
15308 			    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
15309 			    type, facet);
15310 			return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
15311 		    }
15312 		    facet = facet->next;
15313 		} while (facet != NULL);
15314 	    }
15315 	    /*
15316 	    * MAYBE TODO: (Hmm, not really) Datatypes states:
15317 	    * A �list� datatype can be �derived� from an �atomic� datatype
15318 	    * whose �lexical space� allows space (such as string or anyURI)or
15319 	    * a �union� datatype any of whose {member type definitions}'s
15320 	    * �lexical space� allows space.
15321 	    */
15322 	} else {
15323 	    /*
15324 	    * This is the case if we have: <simpleType><restriction ...
15325 	    * I.e. the variety of "list" is inherited.
15326 	    */
15327 	    /*
15328 	    * 2.3.2
15329 	    * 2.3.2.1 The {base type definition} must have a {variety} of list.
15330 	    */
15331 	    if (! WXS_IS_LIST(type->baseType)) {
15332 		xmlSchemaPCustomErr(pctxt,
15333 		    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
15334 		    WXS_BASIC_CAST type, NULL,
15335 		    "The base type '%s' must be a list type",
15336 		    xmlSchemaGetComponentQName(&str, type->baseType));
15337 		FREE_AND_NULL(str)
15338 		return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
15339 	    }
15340 	    /*
15341 	    * 2.3.2.2 The {final} of the {base type definition} must not
15342 	    * contain restriction.
15343 	    */
15344 	    if (xmlSchemaTypeFinalContains(type->baseType,
15345 		XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15346 		xmlSchemaPCustomErr(pctxt,
15347 		    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
15348 		    WXS_BASIC_CAST type, NULL,
15349 		    "The 'final' of the base type '%s' must not contain 'restriction'",
15350 		    xmlSchemaGetComponentQName(&str, type->baseType));
15351 		FREE_AND_NULL(str)
15352 		return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
15353 	    }
15354 	    /*
15355 	    * 2.3.2.3 The {item type definition} must be validly derived
15356 	    * from the {base type definition}'s {item type definition} given
15357 	    * the empty set, as defined in Type Derivation OK (Simple) (�3.14.6).
15358 	    */
15359 	    {
15360 		xmlSchemaTypePtr baseItemType;
15361 
15362 		baseItemType = type->baseType->subtypes;
15363 		if ((baseItemType == NULL) || (! WXS_IS_SIMPLE(baseItemType))) {
15364 		    PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15365 			"failed to eval the item type of a base type");
15366 		    return (-1);
15367 		}
15368 		if ((itemType != baseItemType) &&
15369 		    (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt, itemType,
15370 			baseItemType, 0) != 0)) {
15371 		    xmlChar *strBIT = NULL, *strBT = NULL;
15372 		    xmlSchemaPCustomErrExt(pctxt,
15373 			XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
15374 			WXS_BASIC_CAST type, NULL,
15375 			"The item type '%s' is not validly derived from "
15376 			"the item type '%s' of the base type '%s'",
15377 			xmlSchemaGetComponentQName(&str, itemType),
15378 			xmlSchemaGetComponentQName(&strBIT, baseItemType),
15379 			xmlSchemaGetComponentQName(&strBT, type->baseType));
15380 
15381 		    FREE_AND_NULL(str)
15382 		    FREE_AND_NULL(strBIT)
15383 		    FREE_AND_NULL(strBT)
15384 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
15385 		}
15386 	    }
15387 
15388 	    if (type->facets != NULL) {
15389 		xmlSchemaFacetPtr facet;
15390 		int ok = 1;
15391 		/*
15392 		* 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
15393 		* and enumeration facet components are allowed among the {facets}.
15394 		*/
15395 		facet = type->facets;
15396 		do {
15397 		    switch (facet->type) {
15398 			case XML_SCHEMA_FACET_LENGTH:
15399 			case XML_SCHEMA_FACET_MINLENGTH:
15400 			case XML_SCHEMA_FACET_MAXLENGTH:
15401 			case XML_SCHEMA_FACET_WHITESPACE:
15402 			    /*
15403 			    * TODO: 2.5.1.2 List datatypes
15404 			    * The value of �whiteSpace� is fixed to the value collapse.
15405 			    */
15406 			case XML_SCHEMA_FACET_PATTERN:
15407 			case XML_SCHEMA_FACET_ENUMERATION:
15408 			    break;
15409 			default: {
15410 			    xmlSchemaPIllegalFacetListUnionErr(pctxt,
15411 				XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
15412 				type, facet);
15413 			    /*
15414 			    * We could return, but it's nicer to report all
15415 			    * invalid facets.
15416 			    */
15417 			    ok = 0;
15418 			}
15419 		    }
15420 		    facet = facet->next;
15421 		} while (facet != NULL);
15422 		if (ok == 0)
15423 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
15424 		/*
15425 		* SPEC (2.3.2.5) (same as 1.3.2)
15426 		*
15427 		* NOTE (2.3.2.5) This is currently done in
15428 		* xmlSchemaDeriveAndValidateFacets()
15429 		*/
15430 	    }
15431 	}
15432     } else if (WXS_IS_UNION(type)) {
15433 	/*
15434 	* 3.1 The {member type definitions} must all have {variety} of
15435 	* atomic or list.
15436 	*/
15437 	xmlSchemaTypeLinkPtr member;
15438 
15439 	member = type->memberTypes;
15440 	while (member != NULL) {
15441 	    if (WXS_IS_TYPE_NOT_FIXED(member->type))
15442 		xmlSchemaTypeFixup(member->type, ACTXT_CAST pctxt);
15443 
15444 	    if ((! WXS_IS_ATOMIC(member->type)) &&
15445 		(! WXS_IS_LIST(member->type))) {
15446 		xmlSchemaPCustomErr(pctxt,
15447 		    XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
15448 		    WXS_BASIC_CAST type, NULL,
15449 		    "The member type '%s' is neither an atomic, nor a list type",
15450 		    xmlSchemaGetComponentQName(&str, member->type));
15451 		FREE_AND_NULL(str)
15452 		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
15453 	    }
15454 	    member = member->next;
15455 	}
15456 	/*
15457 	* 3.3.1 If the {base type definition} is the �simple ur-type
15458 	* definition�
15459 	*/
15460 	if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
15461 	    /*
15462 	    * 3.3.1.1 All of the {member type definitions} must have a
15463 	    * {final} which does not contain union.
15464 	    */
15465 	    member = type->memberTypes;
15466 	    while (member != NULL) {
15467 		if (xmlSchemaTypeFinalContains(member->type,
15468 		    XML_SCHEMAS_TYPE_FINAL_UNION)) {
15469 		    xmlSchemaPCustomErr(pctxt,
15470 			XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
15471 			WXS_BASIC_CAST type, NULL,
15472 			"The 'final' of member type '%s' contains 'union'",
15473 			xmlSchemaGetComponentQName(&str, member->type));
15474 		    FREE_AND_NULL(str)
15475 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
15476 		}
15477 		member = member->next;
15478 	    }
15479 	    /*
15480 	    * 3.3.1.2 The {facets} must be empty.
15481 	    */
15482 	    if (type->facetSet != NULL) {
15483 		xmlSchemaPCustomErr(pctxt,
15484 		    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
15485 		    WXS_BASIC_CAST type, NULL,
15486 		    "No facets allowed", NULL);
15487 		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
15488 	    }
15489 	} else {
15490 	    /*
15491 	    * 3.3.2.1 The {base type definition} must have a {variety} of union.
15492 	    * I.e. the variety of "list" is inherited.
15493 	    */
15494 	    if (! WXS_IS_UNION(type->baseType)) {
15495 		xmlSchemaPCustomErr(pctxt,
15496 		    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
15497 		    WXS_BASIC_CAST type, NULL,
15498 		    "The base type '%s' is not a union type",
15499 		    xmlSchemaGetComponentQName(&str, type->baseType));
15500 		FREE_AND_NULL(str)
15501 		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
15502 	    }
15503 	    /*
15504 	    * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
15505 	    */
15506 	    if (xmlSchemaTypeFinalContains(type->baseType,
15507 		XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15508 		xmlSchemaPCustomErr(pctxt,
15509 		    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
15510 		    WXS_BASIC_CAST type, NULL,
15511 		    "The 'final' of its base type '%s' must not contain 'restriction'",
15512 		    xmlSchemaGetComponentQName(&str, type->baseType));
15513 		FREE_AND_NULL(str)
15514 		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
15515 	    }
15516 	    /*
15517 	    * 3.3.2.3 The {member type definitions}, in order, must be validly
15518 	    * derived from the corresponding type definitions in the {base
15519 	    * type definition}'s {member type definitions} given the empty set,
15520 	    * as defined in Type Derivation OK (Simple) (�3.14.6).
15521 	    */
15522 	    {
15523 		xmlSchemaTypeLinkPtr baseMember;
15524 
15525 		/*
15526 		* OPTIMIZE: if the type is restricting, it has no local defined
15527 		* member types and inherits the member types of the base type;
15528 		* thus a check for equality can be skipped.
15529 		*/
15530 		/*
15531 		* Even worse: I cannot see a scenario where a restricting
15532 		* union simple type can have other member types as the member
15533 		* types of it's base type. This check seems not necessary with
15534 		* respect to the derivation process in libxml2.
15535 		* But necessary if constructing types with an API.
15536 		*/
15537 		if (type->memberTypes != NULL) {
15538 		    member = type->memberTypes;
15539 		    baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
15540 		    if ((member == NULL) && (baseMember != NULL)) {
15541 			PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15542 			    "different number of member types in base");
15543 		    }
15544 		    while (member != NULL) {
15545 			if (baseMember == NULL) {
15546 			    PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15547 			    "different number of member types in base");
15548 			} else if ((member->type != baseMember->type) &&
15549 			    (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
15550 				member->type, baseMember->type, 0) != 0)) {
15551 			    xmlChar *strBMT = NULL, *strBT = NULL;
15552 
15553 			    xmlSchemaPCustomErrExt(pctxt,
15554 				XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
15555 				WXS_BASIC_CAST type, NULL,
15556 				"The member type %s is not validly "
15557 				"derived from its corresponding member "
15558 				"type %s of the base type %s",
15559 				xmlSchemaGetComponentQName(&str, member->type),
15560 				xmlSchemaGetComponentQName(&strBMT, baseMember->type),
15561 				xmlSchemaGetComponentQName(&strBT, type->baseType));
15562 			    FREE_AND_NULL(str)
15563 			    FREE_AND_NULL(strBMT)
15564 			    FREE_AND_NULL(strBT)
15565 			    return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
15566 			}
15567 			member = member->next;
15568 			baseMember = baseMember->next;
15569 		    }
15570 		}
15571 	    }
15572 	    /*
15573 	    * 3.3.2.4 Only pattern and enumeration facet components are
15574 	    * allowed among the {facets}.
15575 	    */
15576 	    if (type->facets != NULL) {
15577 		xmlSchemaFacetPtr facet;
15578 		int ok = 1;
15579 
15580 		facet = type->facets;
15581 		do {
15582 		    if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
15583 			(facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
15584 			xmlSchemaPIllegalFacetListUnionErr(pctxt,
15585 				XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
15586 				type, facet);
15587 			ok = 0;
15588 		    }
15589 		    facet = facet->next;
15590 		} while (facet != NULL);
15591 		if (ok == 0)
15592 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
15593 
15594 	    }
15595 	    /*
15596 	    * SPEC (3.3.2.5) (same as 1.3.2)
15597 	    *
15598 	    * NOTE (3.3.2.5) This is currently done in
15599 	    * xmlSchemaDeriveAndValidateFacets()
15600 	    */
15601 	}
15602     }
15603 
15604     return (0);
15605 }
15606 
15607 /**
15608  * xmlSchemaCheckSRCSimpleType:
15609  * @ctxt:  the schema parser context
15610  * @type:  the simple type definition
15611  *
15612  * Checks crc-simple-type constraints.
15613  *
15614  * Returns 0 if the constraints are satisfied,
15615  * if not a positive error code and -1 on internal
15616  * errors.
15617  */
15618 #if 0
15619 static int
15620 xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
15621 			    xmlSchemaTypePtr type)
15622 {
15623     /*
15624     * src-simple-type.1 The corresponding simple type definition, if any,
15625     * must satisfy the conditions set out in Constraints on Simple Type
15626     * Definition Schema Components (�3.14.6).
15627     */
15628     if (WXS_IS_RESTRICTION(type)) {
15629 	/*
15630 	* src-simple-type.2 "If the <restriction> alternative is chosen,
15631 	* either it must have a base [attribute] or a <simpleType> among its
15632 	* [children], but not both."
15633 	* NOTE: This is checked in the parse function of <restriction>.
15634 	*/
15635 	/*
15636 	*
15637 	*/
15638     } else if (WXS_IS_LIST(type)) {
15639 	/* src-simple-type.3 "If the <list> alternative is chosen, either it must have
15640 	* an itemType [attribute] or a <simpleType> among its [children],
15641 	* but not both."
15642 	*
15643 	* NOTE: This is checked in the parse function of <list>.
15644 	*/
15645     } else if (WXS_IS_UNION(type)) {
15646 	/*
15647 	* src-simple-type.4 is checked in xmlSchemaCheckUnionTypeDefCircular().
15648 	*/
15649     }
15650     return (0);
15651 }
15652 #endif
15653 
15654 static int
xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)15655 xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
15656 {
15657    if (ctxt->vctxt == NULL) {
15658 	ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
15659 	if (ctxt->vctxt == NULL) {
15660 	    xmlSchemaPErr(ctxt, NULL,
15661 		XML_SCHEMAP_INTERNAL,
15662 		"Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
15663 		"failed to create a temp. validation context.\n",
15664 		NULL, NULL);
15665 	    return (-1);
15666 	}
15667 	/* TODO: Pass user data. */
15668 	xmlSchemaSetValidErrors(ctxt->vctxt,
15669 	    ctxt->error, ctxt->warning, ctxt->errCtxt);
15670 	xmlSchemaSetValidStructuredErrors(ctxt->vctxt,
15671 	    ctxt->serror, ctxt->errCtxt);
15672     }
15673     return (0);
15674 }
15675 
15676 static int
15677 xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
15678 			     xmlNodePtr node,
15679 			     xmlSchemaTypePtr type,
15680 			     const xmlChar *value,
15681 			     xmlSchemaValPtr *retVal,
15682 			     int fireErrors,
15683 			     int normalize,
15684 			     int isNormalized);
15685 
15686 /**
15687  * xmlSchemaParseCheckCOSValidDefault:
15688  * @pctxt:  the schema parser context
15689  * @type:  the simple type definition
15690  * @value: the default value
15691  * @node: an optional node (the holder of the value)
15692  *
15693  * Schema Component Constraint: Element Default Valid (Immediate)
15694  * (cos-valid-default)
15695  * This will be used by the parser only. For the validator there's
15696  * an other version.
15697  *
15698  * Returns 0 if the constraints are satisfied,
15699  * if not, a positive error code and -1 on internal
15700  * errors.
15701  */
15702 static int
xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,xmlNodePtr node,xmlSchemaTypePtr type,const xmlChar * value,xmlSchemaValPtr * val)15703 xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
15704 				   xmlNodePtr node,
15705 				   xmlSchemaTypePtr type,
15706 				   const xmlChar *value,
15707 				   xmlSchemaValPtr *val)
15708 {
15709     int ret = 0;
15710 
15711     /*
15712     * cos-valid-default:
15713     * Schema Component Constraint: Element Default Valid (Immediate)
15714     * For a string to be a valid default with respect to a type
15715     * definition the appropriate case among the following must be true:
15716     */
15717     if WXS_IS_COMPLEX(type) {
15718 	/*
15719 	* Complex type.
15720 	*
15721 	* SPEC (2.1) "its {content type} must be a simple type definition
15722 	* or mixed."
15723 	* SPEC (2.2.2) "If the {content type} is mixed, then the {content
15724 	* type}'s particle must be �emptiable� as defined by
15725 	* Particle Emptiable (�3.9.6)."
15726 	*/
15727 	if ((! WXS_HAS_SIMPLE_CONTENT(type)) &&
15728 	    ((! WXS_HAS_MIXED_CONTENT(type)) || (! WXS_EMPTIABLE(type)))) {
15729 	    /* NOTE that this covers (2.2.2) as well. */
15730 	    xmlSchemaPCustomErr(pctxt,
15731 		XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
15732 		WXS_BASIC_CAST type, type->node,
15733 		"For a string to be a valid default, the type definition "
15734 		"must be a simple type or a complex type with mixed content "
15735 		"and a particle emptiable", NULL);
15736 	    return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
15737 	}
15738     }
15739     /*
15740     * 1 If the type definition is a simple type definition, then the string
15741     * must be �valid� with respect to that definition as defined by String
15742     * Valid (�3.14.4).
15743     *
15744     * AND
15745     *
15746     * 2.2.1 If the {content type} is a simple type definition, then the
15747     * string must be �valid� with respect to that simple type definition
15748     * as defined by String Valid (�3.14.4).
15749     */
15750     if (WXS_IS_SIMPLE(type))
15751 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15752 	    type, value, val, 1, 1, 0);
15753     else if (WXS_HAS_SIMPLE_CONTENT(type))
15754 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15755 	    type->contentTypeDef, value, val, 1, 1, 0);
15756     else
15757 	return (ret);
15758 
15759     if (ret < 0) {
15760 	PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
15761 	    "calling xmlSchemaVCheckCVCSimpleType()");
15762     }
15763 
15764     return (ret);
15765 }
15766 
15767 /**
15768  * xmlSchemaCheckCTPropsCorrect:
15769  * @ctxt:  the schema parser context
15770  * @type:  the complex type definition
15771  *
15772  *.(4.6) Constraints on Complex Type Definition Schema Components
15773  * Schema Component Constraint:
15774  * Complex Type Definition Properties Correct (ct-props-correct)
15775  * STATUS: (seems) complete
15776  *
15777  * Returns 0 if the constraints are satisfied, a positive
15778  * error code if not and -1 if an internal error occured.
15779  */
15780 static int
xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)15781 xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
15782 			     xmlSchemaTypePtr type)
15783 {
15784     /*
15785     * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
15786     *
15787     * SPEC (1) "The values of the properties of a complex type definition must
15788     * be as described in the property tableau in The Complex Type Definition
15789     * Schema Component (�3.4.1), modulo the impact of Missing
15790     * Sub-components (�5.3)."
15791     */
15792     if ((type->baseType != NULL) &&
15793 	(WXS_IS_SIMPLE(type->baseType)) &&
15794 	(WXS_IS_EXTENSION(type) == 0)) {
15795 	/*
15796 	* SPEC (2) "If the {base type definition} is a simple type definition,
15797 	* the {derivation method} must be extension."
15798 	*/
15799 	xmlSchemaCustomErr(ACTXT_CAST pctxt,
15800 	    XML_SCHEMAP_SRC_CT_1,
15801 	    NULL, WXS_BASIC_CAST type,
15802 	    "If the base type is a simple type, the derivation method must be "
15803 	    "'extension'", NULL, NULL);
15804 	return (XML_SCHEMAP_SRC_CT_1);
15805     }
15806     /*
15807     * SPEC (3) "Circular definitions are disallowed, except for the �ur-type
15808     * definition�. That is, it must be possible to reach the �ur-type
15809     * definition by repeatedly following the {base type definition}."
15810     *
15811     * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
15812     */
15813     /*
15814     * NOTE that (4) and (5) need the following:
15815     *   - attribute uses need to be already inherited (apply attr. prohibitions)
15816     *   - attribute group references need to be expanded already
15817     *   - simple types need to be typefixed already
15818     */
15819     if (type->attrUses &&
15820 	(((xmlSchemaItemListPtr) type->attrUses)->nbItems > 1))
15821     {
15822 	xmlSchemaItemListPtr uses = (xmlSchemaItemListPtr) type->attrUses;
15823 	xmlSchemaAttributeUsePtr use, tmp;
15824 	int i, j, hasId = 0;
15825 
15826 	for (i = uses->nbItems -1; i >= 0; i--) {
15827 	    use = uses->items[i];
15828 
15829 	    /*
15830 	    * SPEC ct-props-correct
15831 	    * (4) "Two distinct attribute declarations in the
15832 	    * {attribute uses} must not have identical {name}s and
15833 	    * {target namespace}s."
15834 	    */
15835 	    if (i > 0) {
15836 		for (j = i -1; j >= 0; j--) {
15837 		    tmp = uses->items[j];
15838 		    if ((WXS_ATTRUSE_DECL_NAME(use) ==
15839 			WXS_ATTRUSE_DECL_NAME(tmp)) &&
15840 			(WXS_ATTRUSE_DECL_TNS(use) ==
15841 			WXS_ATTRUSE_DECL_TNS(tmp)))
15842 		    {
15843 			xmlChar *str = NULL;
15844 
15845 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
15846 			    XML_SCHEMAP_AG_PROPS_CORRECT,
15847 			    NULL, WXS_BASIC_CAST type,
15848 			    "Duplicate %s",
15849 			    xmlSchemaGetComponentDesignation(&str, use),
15850 			    NULL);
15851 			FREE_AND_NULL(str);
15852 			/*
15853 			* Remove the duplicate.
15854 			*/
15855 			if (xmlSchemaItemListRemove(uses, i) == -1)
15856 			    goto exit_failure;
15857 			goto next_use;
15858 		    }
15859 		}
15860 	    }
15861 	    /*
15862 	    * SPEC ct-props-correct
15863 	    * (5) "Two distinct attribute declarations in the
15864 	    * {attribute uses} must not have {type definition}s which
15865 	    * are or are derived from ID."
15866 	    */
15867 	    if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
15868 		if (xmlSchemaIsDerivedFromBuiltInType(
15869 		    WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
15870 		{
15871 		    if (hasId) {
15872 			xmlChar *str = NULL;
15873 
15874 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
15875 			    XML_SCHEMAP_AG_PROPS_CORRECT,
15876 			    NULL, WXS_BASIC_CAST type,
15877 			    "There must not exist more than one attribute "
15878 			    "declaration of type 'xs:ID' "
15879 			    "(or derived from 'xs:ID'). The %s violates this "
15880 			    "constraint",
15881 			    xmlSchemaGetComponentDesignation(&str, use),
15882 			    NULL);
15883 			FREE_AND_NULL(str);
15884 			if (xmlSchemaItemListRemove(uses, i) == -1)
15885 			    goto exit_failure;
15886 		    }
15887 
15888 		    hasId = 1;
15889 		}
15890 	    }
15891 next_use: {}
15892 	}
15893     }
15894     return (0);
15895 exit_failure:
15896     return(-1);
15897 }
15898 
15899 static int
xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,xmlSchemaTypePtr typeB)15900 xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
15901 		       xmlSchemaTypePtr typeB)
15902 {
15903     /*
15904     * TODO: This should implement component-identity
15905     * in the future.
15906     */
15907     if ((typeA == NULL) || (typeB == NULL))
15908 	return (0);
15909     return (typeA == typeB);
15910 }
15911 
15912 /**
15913  * xmlSchemaCheckCOSCTDerivedOK:
15914  * @ctxt:  the schema parser context
15915  * @type:  the to-be derived complex type definition
15916  * @baseType:  the base complex type definition
15917  * @set: the given set
15918  *
15919  * Schema Component Constraint:
15920  * Type Derivation OK (Complex) (cos-ct-derived-ok)
15921  *
15922  * STATUS: completed
15923  *
15924  * Returns 0 if the constraints are satisfied, or 1
15925  * if not.
15926  */
15927 static int
xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,xmlSchemaTypePtr type,xmlSchemaTypePtr baseType,int set)15928 xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
15929 			     xmlSchemaTypePtr type,
15930 			     xmlSchemaTypePtr baseType,
15931 			     int set)
15932 {
15933     int equal = xmlSchemaAreEqualTypes(type, baseType);
15934     /* TODO: Error codes. */
15935     /*
15936     * SPEC "For a complex type definition (call it D, for derived)
15937     * to be validly derived from a type definition (call this
15938     * B, for base) given a subset of {extension, restriction}
15939     * all of the following must be true:"
15940     */
15941     if (! equal) {
15942 	/*
15943 	* SPEC (1) "If B and D are not the same type definition, then the
15944 	* {derivation method} of D must not be in the subset."
15945 	*/
15946 	if (((set & SUBSET_EXTENSION) && (WXS_IS_EXTENSION(type))) ||
15947 	    ((set & SUBSET_RESTRICTION) && (WXS_IS_RESTRICTION(type))))
15948 	    return (1);
15949     } else {
15950 	/*
15951 	* SPEC (2.1) "B and D must be the same type definition."
15952 	*/
15953 	return (0);
15954     }
15955     /*
15956     * SPEC (2.2) "B must be D's {base type definition}."
15957     */
15958     if (type->baseType == baseType)
15959 	return (0);
15960     /*
15961     * SPEC (2.3.1) "D's {base type definition} must not be the �ur-type
15962     * definition�."
15963     */
15964     if (WXS_IS_ANYTYPE(type->baseType))
15965 	return (1);
15966 
15967     if (WXS_IS_COMPLEX(type->baseType)) {
15968 	/*
15969 	* SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
15970 	* must be validly derived from B given the subset as defined by this
15971 	* constraint."
15972 	*/
15973 	return (xmlSchemaCheckCOSCTDerivedOK(actxt, type->baseType,
15974 	    baseType, set));
15975     } else {
15976 	/*
15977 	* SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
15978 	* must be validly derived from B given the subset as defined in Type
15979 	* Derivation OK (Simple) (�3.14.6).
15980 	*/
15981 	return (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
15982 	    baseType, set));
15983     }
15984 }
15985 
15986 /**
15987  * xmlSchemaCheckCOSDerivedOK:
15988  * @type:  the derived simple type definition
15989  * @baseType:  the base type definition
15990  *
15991  * Calls:
15992  * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
15993  *
15994  * Checks wheter @type can be validly derived from @baseType.
15995  *
15996  * Returns 0 on success, an positive error code otherwise.
15997  */
15998 static int
xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt,xmlSchemaTypePtr type,xmlSchemaTypePtr baseType,int set)15999 xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16000 			   xmlSchemaTypePtr type,
16001 			   xmlSchemaTypePtr baseType,
16002 			   int set)
16003 {
16004     if (WXS_IS_SIMPLE(type))
16005 	return (xmlSchemaCheckCOSSTDerivedOK(actxt, type, baseType, set));
16006     else
16007 	return (xmlSchemaCheckCOSCTDerivedOK(actxt, type, baseType, set));
16008 }
16009 
16010 /**
16011  * xmlSchemaCheckCOSCTExtends:
16012  * @ctxt:  the schema parser context
16013  * @type:  the complex type definition
16014  *
16015  * (3.4.6) Constraints on Complex Type Definition Schema Components
16016  * Schema Component Constraint:
16017  * Derivation Valid (Extension) (cos-ct-extends)
16018  *
16019  * STATUS:
16020  *   missing:
16021  *     (1.5)
16022  *     (1.4.3.2.2.2) "Particle Valid (Extension)"
16023  *
16024  * Returns 0 if the constraints are satisfied, a positive
16025  * error code if not and -1 if an internal error occured.
16026  */
16027 static int
xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)16028 xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
16029 			   xmlSchemaTypePtr type)
16030 {
16031     xmlSchemaTypePtr base = type->baseType;
16032     /*
16033     * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
16034     * temporarily only.
16035     */
16036     /*
16037     * SPEC (1) "If the {base type definition} is a complex type definition,
16038     * then all of the following must be true:"
16039     */
16040     if (WXS_IS_COMPLEX(base)) {
16041 	/*
16042 	* SPEC (1.1) "The {final} of the {base type definition} must not
16043 	* contain extension."
16044 	*/
16045 	if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16046 	    xmlSchemaPCustomErr(ctxt,
16047 		XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16048 		WXS_BASIC_CAST type, NULL,
16049 		"The 'final' of the base type definition "
16050 		"contains 'extension'", NULL);
16051 	    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16052 	}
16053 
16054 	/*
16055 	* ATTENTION: The constrains (1.2) and (1.3) are not applied,
16056 	* since they are automatically satisfied through the
16057 	* inheriting mechanism.
16058 	* Note that even if redefining components, the inheriting mechanism
16059 	* is used.
16060 	*/
16061 #if 0
16062 	/*
16063 	* SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
16064 	* uses}
16065 	* of the complex type definition itself, that is, for every attribute
16066 	* use in the {attribute uses} of the {base type definition}, there
16067 	* must be an attribute use in the {attribute uses} of the complex
16068 	* type definition itself whose {attribute declaration} has the same
16069 	* {name}, {target namespace} and {type definition} as its attribute
16070 	* declaration"
16071 	*/
16072 	if (base->attrUses != NULL) {
16073 	    int i, j, found;
16074 	    xmlSchemaAttributeUsePtr use, buse;
16075 
16076 	    for (i = 0; i < (WXS_LIST_CAST base->attrUses)->nbItems; i ++) {
16077 		buse = (WXS_LIST_CAST base->attrUses)->items[i];
16078 		found = 0;
16079 		if (type->attrUses != NULL) {
16080 		    use = (WXS_LIST_CAST type->attrUses)->items[j];
16081 		    for (j = 0; j < (WXS_LIST_CAST type->attrUses)->nbItems; j ++)
16082 		    {
16083 			if ((WXS_ATTRUSE_DECL_NAME(use) ==
16084 				WXS_ATTRUSE_DECL_NAME(buse)) &&
16085 			    (WXS_ATTRUSE_DECL_TNS(use) ==
16086 				WXS_ATTRUSE_DECL_TNS(buse)) &&
16087 			    (WXS_ATTRUSE_TYPEDEF(use) ==
16088 				WXS_ATTRUSE_TYPEDEF(buse))
16089 			{
16090 			    found = 1;
16091 			    break;
16092 			}
16093 		    }
16094 		}
16095 		if (! found) {
16096 		    xmlChar *str = NULL;
16097 
16098 		    xmlSchemaCustomErr(ACTXT_CAST ctxt,
16099 			XML_SCHEMAP_COS_CT_EXTENDS_1_2,
16100 			NULL, WXS_BASIC_CAST type,
16101 			/*
16102 			* TODO: The report does not indicate that also the
16103 			* type needs to be the same.
16104 			*/
16105 			"This type is missing a matching correspondent "
16106 			"for its {base type}'s %s in its {attribute uses}",
16107 			xmlSchemaGetComponentDesignation(&str,
16108 			    buse->children),
16109 			NULL);
16110 		    FREE_AND_NULL(str)
16111 		}
16112 	    }
16113 	}
16114 	/*
16115 	* SPEC (1.3) "If it has an {attribute wildcard}, the complex type
16116 	* definition must also have one, and the base type definition's
16117 	* {attribute  wildcard}'s {namespace constraint} must be a subset
16118 	* of the complex  type definition's {attribute wildcard}'s {namespace
16119 	* constraint}, as defined by Wildcard Subset (�3.10.6)."
16120 	*/
16121 
16122 	/*
16123 	* MAYBE TODO: Enable if ever needed. But this will be needed only
16124 	* if created the type via a schema construction API.
16125 	*/
16126 	if (base->attributeWildcard != NULL) {
16127 	    if (type->attributeWilcard == NULL) {
16128 		xmlChar *str = NULL;
16129 
16130 		xmlSchemaCustomErr(ACTXT_CAST pctxt,
16131 		    XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16132 		    NULL, type,
16133 		    "The base %s has an attribute wildcard, "
16134 		    "but this type is missing an attribute wildcard",
16135 		    xmlSchemaGetComponentDesignation(&str, base));
16136 		FREE_AND_NULL(str)
16137 
16138 	    } else if (xmlSchemaCheckCOSNSSubset(
16139 		base->attributeWildcard, type->attributeWildcard))
16140 	    {
16141 		xmlChar *str = NULL;
16142 
16143 		xmlSchemaCustomErr(ACTXT_CAST pctxt,
16144 		    XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16145 		    NULL, type,
16146 		    "The attribute wildcard is not a valid "
16147 		    "superset of the one in the base %s",
16148 		    xmlSchemaGetComponentDesignation(&str, base));
16149 		FREE_AND_NULL(str)
16150 	    }
16151 	}
16152 #endif
16153 	/*
16154 	* SPEC (1.4) "One of the following must be true:"
16155 	*/
16156 	if ((type->contentTypeDef != NULL) &&
16157 	    (type->contentTypeDef == base->contentTypeDef)) {
16158 	    /*
16159 	    * SPEC (1.4.1) "The {content type} of the {base type definition}
16160 	    * and the {content type} of the complex type definition itself
16161 	    * must be the same simple type definition"
16162 	    * PASS
16163 	    */
16164 	} else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
16165 	    (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
16166 	    /*
16167 	    * SPEC (1.4.2) "The {content type} of both the {base type
16168 	    * definition} and the complex type definition itself must
16169 	    * be empty."
16170 	    * PASS
16171 	    */
16172 	} else {
16173 	    /*
16174 	    * SPEC (1.4.3) "All of the following must be true:"
16175 	    */
16176 	    if (type->subtypes == NULL) {
16177 		/*
16178 		* SPEC 1.4.3.1 The {content type} of the complex type
16179 		* definition itself must specify a particle.
16180 		*/
16181 		xmlSchemaPCustomErr(ctxt,
16182 		    XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16183 		    WXS_BASIC_CAST type, NULL,
16184 		    "The content type must specify a particle", NULL);
16185 		return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16186 	    }
16187 	    /*
16188 	    * SPEC (1.4.3.2) "One of the following must be true:"
16189 	    */
16190 	    if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16191 		/*
16192 		* SPEC (1.4.3.2.1) "The {content type} of the {base type
16193 		* definition} must be empty.
16194 		* PASS
16195 		*/
16196 	    } else {
16197 		/*
16198 		* SPEC (1.4.3.2.2) "All of the following must be true:"
16199 		*/
16200 		if ((type->contentType != base->contentType) ||
16201 		    ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
16202 		    (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
16203 		    /*
16204 		    * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
16205 		    * or both must be element-only."
16206 		    */
16207 		    xmlSchemaPCustomErr(ctxt,
16208 			XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16209 			WXS_BASIC_CAST type, NULL,
16210 			"The content type of both, the type and its base "
16211 			"type, must either 'mixed' or 'element-only'", NULL);
16212 		    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16213 		}
16214 		/*
16215 		* URGENT TODO SPEC (1.4.3.2.2.2) "The particle of the
16216 		* complex type definition must be a �valid extension�
16217 		* of the {base type definition}'s particle, as defined
16218 		* in Particle Valid (Extension) (�3.9.6)."
16219 		*
16220 		* NOTE that we won't check "Particle Valid (Extension)",
16221 		* since it is ensured by the derivation process in
16222 		* xmlSchemaTypeFixup(). We need to implement this when heading
16223 		* for a construction API
16224 		* TODO: !! This is needed to be checked if redefining a type !!
16225 		*/
16226 	    }
16227 	    /*
16228 	    * URGENT TODO (1.5)
16229 	    */
16230 	}
16231     } else {
16232 	/*
16233 	* SPEC (2) "If the {base type definition} is a simple type definition,
16234 	* then all of the following must be true:"
16235 	*/
16236 	if (type->contentTypeDef != base) {
16237 	    /*
16238 	    * SPEC (2.1) "The {content type} must be the same simple type
16239 	    * definition."
16240 	    */
16241 	    xmlSchemaPCustomErr(ctxt,
16242 		XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16243 		WXS_BASIC_CAST type, NULL,
16244 		"The content type must be the simple base type", NULL);
16245 	    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16246 	}
16247 	if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16248 	    /*
16249 	    * SPEC (2.2) "The {final} of the {base type definition} must not
16250 	    * contain extension"
16251 	    * NOTE that this is the same as (1.1).
16252 	    */
16253 	    xmlSchemaPCustomErr(ctxt,
16254 		XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16255 		WXS_BASIC_CAST type, NULL,
16256 		"The 'final' of the base type definition "
16257 		"contains 'extension'", NULL);
16258 	    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16259 	}
16260     }
16261     return (0);
16262 }
16263 
16264 /**
16265  * xmlSchemaCheckDerivationOKRestriction:
16266  * @ctxt:  the schema parser context
16267  * @type:  the complex type definition
16268  *
16269  * (3.4.6) Constraints on Complex Type Definition Schema Components
16270  * Schema Component Constraint:
16271  * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
16272  *
16273  * STATUS:
16274  *   missing:
16275  *     (5.4.2) ???
16276  *
16277  * ATTENTION:
16278  * In XML Schema 1.1 this will be:
16279  * Validation Rule: Checking complex type subsumption
16280  *
16281  * Returns 0 if the constraints are satisfied, a positive
16282  * error code if not and -1 if an internal error occured.
16283  */
16284 static int
xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)16285 xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
16286 				      xmlSchemaTypePtr type)
16287 {
16288     xmlSchemaTypePtr base;
16289 
16290     /*
16291     * TODO: Correct the error code; XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1 is used
16292     * temporarily only.
16293     */
16294     base = type->baseType;
16295     if (! WXS_IS_COMPLEX(base)) {
16296 	xmlSchemaCustomErr(ACTXT_CAST ctxt,
16297 	    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16298 	    type->node, WXS_BASIC_CAST type,
16299 	    "The base type must be a complex type", NULL, NULL);
16300 	return(ctxt->err);
16301     }
16302     if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
16303 	/*
16304 	* SPEC (1) "The {base type definition} must be a complex type
16305 	* definition whose {final} does not contain restriction."
16306 	*/
16307 	xmlSchemaCustomErr(ACTXT_CAST ctxt,
16308 	    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16309 	    type->node, WXS_BASIC_CAST type,
16310 	    "The 'final' of the base type definition "
16311 	    "contains 'restriction'", NULL, NULL);
16312 	return (ctxt->err);
16313     }
16314     /*
16315     * SPEC (2), (3) and (4)
16316     * Those are handled in a separate function, since the
16317     * same constraints are needed for redefinition of
16318     * attribute groups as well.
16319     */
16320     if (xmlSchemaCheckDerivationOKRestriction2to4(ctxt,
16321 	XML_SCHEMA_ACTION_DERIVE,
16322 	WXS_BASIC_CAST type, WXS_BASIC_CAST base,
16323 	type->attrUses, base->attrUses,
16324 	type->attributeWildcard,
16325 	base->attributeWildcard) == -1)
16326     {
16327 	return(-1);
16328     }
16329     /*
16330     * SPEC (5) "One of the following must be true:"
16331     */
16332     if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
16333 	/*
16334 	* SPEC (5.1) "The {base type definition} must be the
16335 	* �ur-type definition�."
16336 	* PASS
16337 	*/
16338     } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16339 	    (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16340 	/*
16341 	* SPEC (5.2.1) "The {content type} of the complex type definition
16342 	* must be a simple type definition"
16343 	*
16344 	* SPEC (5.2.2) "One of the following must be true:"
16345 	*/
16346 	if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16347 	    (base->contentType == XML_SCHEMA_CONTENT_BASIC))
16348 	{
16349 	    int err;
16350 	    /*
16351 	    * SPEC (5.2.2.1) "The {content type} of the {base type
16352 	    * definition} must be a simple type definition from which
16353 	    * the {content type} is validly derived given the empty
16354 	    * set as defined in Type Derivation OK (Simple) (�3.14.6)."
16355 	    *
16356 	    * ATTENTION TODO: This seems not needed if the type implicitely
16357 	    * derived from the base type.
16358 	    *
16359 	    */
16360 	    err = xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST ctxt,
16361 		type->contentTypeDef, base->contentTypeDef, 0);
16362 	    if (err != 0) {
16363 		xmlChar *strA = NULL, *strB = NULL;
16364 
16365 		if (err == -1)
16366 		    return(-1);
16367 		xmlSchemaCustomErr(ACTXT_CAST ctxt,
16368 		    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16369 		    NULL, WXS_BASIC_CAST type,
16370 		    "The {content type} %s is not validly derived from the "
16371 		    "base type's {content type} %s",
16372 		    xmlSchemaGetComponentDesignation(&strA,
16373 			type->contentTypeDef),
16374 		    xmlSchemaGetComponentDesignation(&strB,
16375 			base->contentTypeDef));
16376 		FREE_AND_NULL(strA);
16377 		FREE_AND_NULL(strB);
16378 		return(ctxt->err);
16379 	    }
16380 	} else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16381 	    (xmlSchemaIsParticleEmptiable(
16382 		(xmlSchemaParticlePtr) base->subtypes))) {
16383 	    /*
16384 	    * SPEC (5.2.2.2) "The {base type definition} must be mixed
16385 	    * and have a particle which is �emptiable� as defined in
16386 	    * Particle Emptiable (�3.9.6)."
16387 	    * PASS
16388 	    */
16389 	} else {
16390 	    xmlSchemaPCustomErr(ctxt,
16391 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16392 		WXS_BASIC_CAST type, NULL,
16393 		"The content type of the base type must be either "
16394 		"a simple type or 'mixed' and an emptiable particle", NULL);
16395 	    return (ctxt->err);
16396 	}
16397     } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16398 	/*
16399 	* SPEC (5.3.1) "The {content type} of the complex type itself must
16400 	* be empty"
16401 	*/
16402 	if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16403 	    /*
16404 	    * SPEC (5.3.2.1) "The {content type} of the {base type
16405 	    * definition} must also be empty."
16406 	    * PASS
16407 	    */
16408 	} else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16409 	    (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
16410 	    xmlSchemaIsParticleEmptiable(
16411 		(xmlSchemaParticlePtr) base->subtypes)) {
16412 	    /*
16413 	    * SPEC (5.3.2.2) "The {content type} of the {base type
16414 	    * definition} must be elementOnly or mixed and have a particle
16415 	    * which is �emptiable� as defined in Particle Emptiable (�3.9.6)."
16416 	    * PASS
16417 	    */
16418 	} else {
16419 	    xmlSchemaPCustomErr(ctxt,
16420 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16421 		WXS_BASIC_CAST type, NULL,
16422 		"The content type of the base type must be either "
16423 		"empty or 'mixed' (or 'elements-only') and an emptiable "
16424 		"particle", NULL);
16425 	    return (ctxt->err);
16426 	}
16427     } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16428 	WXS_HAS_MIXED_CONTENT(type)) {
16429 	/*
16430 	* SPEC (5.4.1.1) "The {content type} of the complex type definition
16431 	* itself must be element-only"
16432 	*/
16433 	if (WXS_HAS_MIXED_CONTENT(type) && (! WXS_HAS_MIXED_CONTENT(base))) {
16434 	    /*
16435 	    * SPEC (5.4.1.2) "The {content type} of the complex type
16436 	    * definition itself and of the {base type definition} must be
16437 	    * mixed"
16438 	    */
16439 	    xmlSchemaPCustomErr(ctxt,
16440 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16441 		WXS_BASIC_CAST type, NULL,
16442 		"If the content type is 'mixed', then the content type of the "
16443 		"base type must also be 'mixed'", NULL);
16444 	    return (ctxt->err);
16445 	}
16446 	/*
16447 	* SPEC (5.4.2) "The particle of the complex type definition itself
16448 	* must be a �valid restriction� of the particle of the {content
16449 	* type} of the {base type definition} as defined in Particle Valid
16450 	* (Restriction) (�3.9.6).
16451 	*
16452 	* URGENT TODO: (5.4.2)
16453 	*/
16454     } else {
16455 	xmlSchemaPCustomErr(ctxt,
16456 	    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16457 	    WXS_BASIC_CAST type, NULL,
16458 	    "The type is not a valid restriction of its base type", NULL);
16459 	return (ctxt->err);
16460     }
16461     return (0);
16462 }
16463 
16464 /**
16465  * xmlSchemaCheckCTComponent:
16466  * @ctxt:  the schema parser context
16467  * @type:  the complex type definition
16468  *
16469  * (3.4.6) Constraints on Complex Type Definition Schema Components
16470  *
16471  * Returns 0 if the constraints are satisfied, a positive
16472  * error code if not and -1 if an internal error occured.
16473  */
16474 static int
xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)16475 xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
16476 			  xmlSchemaTypePtr type)
16477 {
16478     int ret;
16479     /*
16480     * Complex Type Definition Properties Correct
16481     */
16482     ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
16483     if (ret != 0)
16484 	return (ret);
16485     if (WXS_IS_EXTENSION(type))
16486 	ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
16487     else
16488 	ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
16489     return (ret);
16490 }
16491 
16492 /**
16493  * xmlSchemaCheckSRCCT:
16494  * @ctxt:  the schema parser context
16495  * @type:  the complex type definition
16496  *
16497  * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
16498  * Schema Representation Constraint:
16499  * Complex Type Definition Representation OK (src-ct)
16500  *
16501  * Returns 0 if the constraints are satisfied, a positive
16502  * error code if not and -1 if an internal error occured.
16503  */
16504 static int
xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)16505 xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
16506 		    xmlSchemaTypePtr type)
16507 {
16508     xmlSchemaTypePtr base;
16509     int ret = 0;
16510 
16511     /*
16512     * TODO: Adjust the error codes here, as I used
16513     * XML_SCHEMAP_SRC_CT_1 only yet.
16514     */
16515     base = type->baseType;
16516     if (! WXS_HAS_SIMPLE_CONTENT(type)) {
16517 	/*
16518 	* 1 If the <complexContent> alternative is chosen, the type definition
16519 	* �resolved� to by the �actual value� of the base [attribute]
16520 	* must be a complex type definition;
16521 	*/
16522 	if (! WXS_IS_COMPLEX(base)) {
16523 	    xmlChar *str = NULL;
16524 	    xmlSchemaPCustomErr(ctxt,
16525 		XML_SCHEMAP_SRC_CT_1,
16526 		WXS_BASIC_CAST type, type->node,
16527 		"If using <complexContent>, the base type is expected to be "
16528 		"a complex type. The base type '%s' is a simple type",
16529 		xmlSchemaFormatQName(&str, base->targetNamespace,
16530 		base->name));
16531 	    FREE_AND_NULL(str)
16532 	    return (XML_SCHEMAP_SRC_CT_1);
16533 	}
16534     } else {
16535 	/*
16536 	* SPEC
16537 	* 2 If the <simpleContent> alternative is chosen, all of the
16538 	* following must be true:
16539 	* 2.1 The type definition �resolved� to by the �actual value� of the
16540 	* base [attribute] must be one of the following:
16541 	*/
16542 	if (WXS_IS_SIMPLE(base)) {
16543 	    if (WXS_IS_EXTENSION(type) == 0) {
16544 		xmlChar *str = NULL;
16545 		/*
16546 		* 2.1.3 only if the <extension> alternative is also
16547 		* chosen, a simple type definition.
16548 		*/
16549 		/* TODO: Change error code to ..._SRC_CT_2_1_3. */
16550 		xmlSchemaPCustomErr(ctxt,
16551 		    XML_SCHEMAP_SRC_CT_1,
16552 		    WXS_BASIC_CAST type, NULL,
16553 		    "If using <simpleContent> and <restriction>, the base "
16554 		    "type must be a complex type. The base type '%s' is "
16555 		    "a simple type",
16556 		    xmlSchemaFormatQName(&str, base->targetNamespace,
16557 			base->name));
16558 		FREE_AND_NULL(str)
16559 		return (XML_SCHEMAP_SRC_CT_1);
16560 	    }
16561 	} else {
16562 	    /* Base type is a complex type. */
16563 	    if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16564 		(base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16565 		/*
16566 		* 2.1.1 a complex type definition whose {content type} is a
16567 		* simple type definition;
16568 		* PASS
16569 		*/
16570 		if (base->contentTypeDef == NULL) {
16571 		    xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
16572 			WXS_BASIC_CAST type, NULL,
16573 			"Internal error: xmlSchemaCheckSRCCT, "
16574 			"'%s', base type has no content type",
16575 			type->name);
16576 		    return (-1);
16577 		}
16578 	    } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16579 		(WXS_IS_RESTRICTION(type))) {
16580 
16581 		/*
16582 		* 2.1.2 only if the <restriction> alternative is also
16583 		* chosen, a complex type definition whose {content type}
16584 		* is mixed and a particle emptiable.
16585 		*/
16586 		if (! xmlSchemaIsParticleEmptiable(
16587 		    (xmlSchemaParticlePtr) base->subtypes)) {
16588 		    ret = XML_SCHEMAP_SRC_CT_1;
16589 		} else
16590 		    /*
16591 		    * Attention: at this point the <simpleType> child is in
16592 		    * ->contentTypeDef (put there during parsing).
16593 		    */
16594 		    if (type->contentTypeDef == NULL) {
16595 		    xmlChar *str = NULL;
16596 		    /*
16597 		    * 2.2 If clause 2.1.2 above is satisfied, then there
16598 		    * must be a <simpleType> among the [children] of
16599 		    * <restriction>.
16600 		    */
16601 		    /* TODO: Change error code to ..._SRC_CT_2_2. */
16602 		    xmlSchemaPCustomErr(ctxt,
16603 			XML_SCHEMAP_SRC_CT_1,
16604 			WXS_BASIC_CAST type, NULL,
16605 			"A <simpleType> is expected among the children "
16606 			"of <restriction>, if <simpleContent> is used and "
16607 			"the base type '%s' is a complex type",
16608 			xmlSchemaFormatQName(&str, base->targetNamespace,
16609 			base->name));
16610 		    FREE_AND_NULL(str)
16611 		    return (XML_SCHEMAP_SRC_CT_1);
16612 		}
16613 	    } else {
16614 		ret = XML_SCHEMAP_SRC_CT_1;
16615 	    }
16616 	}
16617 	if (ret > 0) {
16618 	    xmlChar *str = NULL;
16619 	    if (WXS_IS_RESTRICTION(type)) {
16620 		xmlSchemaPCustomErr(ctxt,
16621 		    XML_SCHEMAP_SRC_CT_1,
16622 		    WXS_BASIC_CAST type, NULL,
16623 		    "If <simpleContent> and <restriction> is used, the "
16624 		    "base type must be a simple type or a complex type with "
16625 		    "mixed content and particle emptiable. The base type "
16626 		    "'%s' is none of those",
16627 		    xmlSchemaFormatQName(&str, base->targetNamespace,
16628 		    base->name));
16629 	    } else {
16630 		xmlSchemaPCustomErr(ctxt,
16631 		    XML_SCHEMAP_SRC_CT_1,
16632 		    WXS_BASIC_CAST type, NULL,
16633 		    "If <simpleContent> and <extension> is used, the "
16634 		    "base type must be a simple type. The base type '%s' "
16635 		    "is a complex type",
16636 		    xmlSchemaFormatQName(&str, base->targetNamespace,
16637 		    base->name));
16638 	    }
16639 	    FREE_AND_NULL(str)
16640 	}
16641     }
16642     /*
16643     * SPEC (3) "The corresponding complex type definition component must
16644     * satisfy the conditions set out in Constraints on Complex Type
16645     * Definition Schema Components (�3.4.6);"
16646     * NOTE (3) will be done in xmlSchemaTypeFixup().
16647     */
16648     /*
16649     * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
16650     * above for {attribute wildcard} is satisfied, the intensional
16651     * intersection must be expressible, as defined in Attribute Wildcard
16652     * Intersection (�3.10.6).
16653     * NOTE (4) is done in xmlSchemaFixupTypeAttributeUses().
16654     */
16655     return (ret);
16656 }
16657 
16658 #ifdef ENABLE_PARTICLE_RESTRICTION
16659 /**
16660  * xmlSchemaCheckParticleRangeOK:
16661  * @ctxt:  the schema parser context
16662  * @type:  the complex type definition
16663  *
16664  * (3.9.6) Constraints on Particle Schema Components
16665  * Schema Component Constraint:
16666  * Occurrence Range OK (range-ok)
16667  *
16668  * STATUS: complete
16669  *
16670  * Returns 0 if the constraints are satisfied, a positive
16671  * error code if not and -1 if an internal error occured.
16672  */
16673 static int
xmlSchemaCheckParticleRangeOK(int rmin,int rmax,int bmin,int bmax)16674 xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
16675 			      int bmin, int bmax)
16676 {
16677     if (rmin < bmin)
16678 	return (1);
16679     if ((bmax != UNBOUNDED) &&
16680 	(rmax > bmax))
16681 	return (1);
16682     return (0);
16683 }
16684 
16685 /**
16686  * xmlSchemaCheckRCaseNameAndTypeOK:
16687  * @ctxt:  the schema parser context
16688  * @r: the restricting element declaration particle
16689  * @b: the base element declaration particle
16690  *
16691  * (3.9.6) Constraints on Particle Schema Components
16692  * Schema Component Constraint:
16693  * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
16694  * (rcase-NameAndTypeOK)
16695  *
16696  * STATUS:
16697  *   MISSING (3.2.3)
16698  *   CLARIFY: (3.2.2)
16699  *
16700  * Returns 0 if the constraints are satisfied, a positive
16701  * error code if not and -1 if an internal error occured.
16702  */
16703 static int
xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)16704 xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
16705 				 xmlSchemaParticlePtr r,
16706 				 xmlSchemaParticlePtr b)
16707 {
16708     xmlSchemaElementPtr elemR, elemB;
16709 
16710     /* TODO: Error codes (rcase-NameAndTypeOK). */
16711     elemR = (xmlSchemaElementPtr) r->children;
16712     elemB = (xmlSchemaElementPtr) b->children;
16713     /*
16714     * SPEC (1) "The declarations' {name}s and {target namespace}s are
16715     * the same."
16716     */
16717     if ((elemR != elemB) &&
16718 	((! xmlStrEqual(elemR->name, elemB->name)) ||
16719 	(! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
16720 	return (1);
16721     /*
16722     * SPEC (2) "R's occurrence range is a valid restriction of B's
16723     * occurrence range as defined by Occurrence Range OK (�3.9.6)."
16724     */
16725     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16726 	    b->minOccurs, b->maxOccurs) != 0)
16727 	return (1);
16728     /*
16729     * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
16730     * {scope} are global."
16731     */
16732     if (elemR == elemB)
16733 	return (0);
16734     /*
16735     * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
16736     */
16737     if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
16738 	(elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
16739 	 return (1);
16740     /*
16741     * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
16742     * or is not fixed, or R's declaration's {value constraint} is fixed
16743     * with the same value."
16744     */
16745     if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
16746 	((elemR->value == NULL) ||
16747 	 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
16748 	 /* TODO: Equality of the initial value or normalized or canonical? */
16749 	 (! xmlStrEqual(elemR->value, elemB->value))))
16750 	 return (1);
16751     /*
16752     * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
16753     * definitions} is a subset of B's declaration's {identity-constraint
16754     * definitions}, if any."
16755     */
16756     if (elemB->idcs != NULL) {
16757 	/* TODO */
16758     }
16759     /*
16760     * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
16761     * superset of B's declaration's {disallowed substitutions}."
16762     */
16763     if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
16764 	 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
16765 	((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
16766 	 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
16767 	((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
16768 	 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
16769 	 return (1);
16770     /*
16771     * SPEC (3.2.5) "R's {type definition} is validly derived given
16772     * {extension, list, union} from B's {type definition}"
16773     *
16774     * BADSPEC TODO: What's the point of adding "list" and "union" to the
16775     * set, if the corresponding constraints handle "restriction" and
16776     * "extension" only?
16777     *
16778     */
16779     {
16780 	int set = 0;
16781 
16782 	set |= SUBSET_EXTENSION;
16783 	set |= SUBSET_LIST;
16784 	set |= SUBSET_UNION;
16785 	if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST ctxt, elemR->subtypes,
16786 	    elemB->subtypes, set) != 0)
16787 	    return (1);
16788     }
16789     return (0);
16790 }
16791 
16792 /**
16793  * xmlSchemaCheckRCaseNSCompat:
16794  * @ctxt:  the schema parser context
16795  * @r: the restricting element declaration particle
16796  * @b: the base wildcard particle
16797  *
16798  * (3.9.6) Constraints on Particle Schema Components
16799  * Schema Component Constraint:
16800  * Particle Derivation OK (Elt:Any -- NSCompat)
16801  * (rcase-NSCompat)
16802  *
16803  * STATUS: complete
16804  *
16805  * Returns 0 if the constraints are satisfied, a positive
16806  * error code if not and -1 if an internal error occured.
16807  */
16808 static int
xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)16809 xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
16810 			    xmlSchemaParticlePtr r,
16811 			    xmlSchemaParticlePtr b)
16812 {
16813     /* TODO:Error codes (rcase-NSCompat). */
16814     /*
16815     * SPEC "For an element declaration particle to be a �valid restriction�
16816     * of a wildcard particle all of the following must be true:"
16817     *
16818     * SPEC (1) "The element declaration's {target namespace} is �valid�
16819     * with respect to the wildcard's {namespace constraint} as defined by
16820     * Wildcard allows Namespace Name (�3.10.4)."
16821     */
16822     if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
16823 	((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
16824 	return (1);
16825     /*
16826     * SPEC (2) "R's occurrence range is a valid restriction of B's
16827     * occurrence range as defined by Occurrence Range OK (�3.9.6)."
16828     */
16829     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16830 	    b->minOccurs, b->maxOccurs) != 0)
16831 	return (1);
16832 
16833     return (0);
16834 }
16835 
16836 /**
16837  * xmlSchemaCheckRCaseRecurseAsIfGroup:
16838  * @ctxt:  the schema parser context
16839  * @r: the restricting element declaration particle
16840  * @b: the base model group particle
16841  *
16842  * (3.9.6) Constraints on Particle Schema Components
16843  * Schema Component Constraint:
16844  * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
16845  * (rcase-RecurseAsIfGroup)
16846  *
16847  * STATUS: TODO
16848  *
16849  * Returns 0 if the constraints are satisfied, a positive
16850  * error code if not and -1 if an internal error occured.
16851  */
16852 static int
xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)16853 xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
16854 				    xmlSchemaParticlePtr r,
16855 				    xmlSchemaParticlePtr b)
16856 {
16857     /* TODO: Error codes (rcase-RecurseAsIfGroup). */
16858     TODO
16859     return (0);
16860 }
16861 
16862 /**
16863  * xmlSchemaCheckRCaseNSSubset:
16864  * @ctxt:  the schema parser context
16865  * @r: the restricting wildcard particle
16866  * @b: the base wildcard particle
16867  *
16868  * (3.9.6) Constraints on Particle Schema Components
16869  * Schema Component Constraint:
16870  * Particle Derivation OK (Any:Any -- NSSubset)
16871  * (rcase-NSSubset)
16872  *
16873  * STATUS: complete
16874  *
16875  * Returns 0 if the constraints are satisfied, a positive
16876  * error code if not and -1 if an internal error occured.
16877  */
16878 static int
xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b,int isAnyTypeBase)16879 xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
16880 				    xmlSchemaParticlePtr r,
16881 				    xmlSchemaParticlePtr b,
16882 				    int isAnyTypeBase)
16883 {
16884     /* TODO: Error codes (rcase-NSSubset). */
16885     /*
16886     * SPEC (1) "R's occurrence range is a valid restriction of B's
16887     * occurrence range as defined by Occurrence Range OK (�3.9.6)."
16888     */
16889     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16890 	    b->minOccurs, b->maxOccurs))
16891 	return (1);
16892     /*
16893     * SPEC (2) "R's {namespace constraint} must be an intensional subset
16894     * of B's {namespace constraint} as defined by Wildcard Subset (�3.10.6)."
16895     */
16896     if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
16897 	(xmlSchemaWildcardPtr) b->children))
16898 	return (1);
16899     /*
16900     * SPEC (3) "Unless B is the content model wildcard of the �ur-type
16901     * definition�, R's {process contents} must be identical to or stronger
16902     * than B's {process contents}, where strict is stronger than lax is
16903     * stronger than skip."
16904     */
16905     if (! isAnyTypeBase) {
16906 	if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
16907 	    ((xmlSchemaWildcardPtr) b->children)->processContents)
16908 	    return (1);
16909     }
16910 
16911     return (0);
16912 }
16913 
16914 /**
16915  * xmlSchemaCheckCOSParticleRestrict:
16916  * @ctxt:  the schema parser context
16917  * @type:  the complex type definition
16918  *
16919  * (3.9.6) Constraints on Particle Schema Components
16920  * Schema Component Constraint:
16921  * Particle Valid (Restriction) (cos-particle-restrict)
16922  *
16923  * STATUS: TODO
16924  *
16925  * Returns 0 if the constraints are satisfied, a positive
16926  * error code if not and -1 if an internal error occured.
16927  */
16928 static int
xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)16929 xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
16930 				  xmlSchemaParticlePtr r,
16931 				  xmlSchemaParticlePtr b)
16932 {
16933     int ret = 0;
16934 
16935     /*part = WXS_TYPE_PARTICLE(type);
16936     basePart = WXS_TYPE_PARTICLE(base);
16937     */
16938 
16939     TODO
16940 
16941     /*
16942     * SPEC (1) "They are the same particle."
16943     */
16944     if (r == b)
16945 	return (0);
16946 
16947 
16948     return (0);
16949 }
16950 
16951 /**
16952  * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
16953  * @ctxt:  the schema parser context
16954  * @r: the model group particle
16955  * @b: the base wildcard particle
16956  *
16957  * (3.9.6) Constraints on Particle Schema Components
16958  * Schema Component Constraint:
16959  * Particle Derivation OK (All/Choice/Sequence:Any --
16960  *                         NSRecurseCheckCardinality)
16961  * (rcase-NSRecurseCheckCardinality)
16962  *
16963  * STATUS: TODO: subst-groups
16964  *
16965  * Returns 0 if the constraints are satisfied, a positive
16966  * error code if not and -1 if an internal error occured.
16967  */
16968 static int
xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)16969 xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
16970 					     xmlSchemaParticlePtr r,
16971 					     xmlSchemaParticlePtr b)
16972 {
16973     xmlSchemaParticlePtr part;
16974     /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
16975     if ((r->children == NULL) || (r->children->children == NULL))
16976 	return (-1);
16977     /*
16978     * SPEC "For a group particle to be a �valid restriction� of a
16979     * wildcard particle..."
16980     *
16981     * SPEC (1) "Every member of the {particles} of the group is a �valid
16982     * restriction� of the wildcard as defined by
16983     * Particle Valid (Restriction) (�3.9.6)."
16984     */
16985     part = (xmlSchemaParticlePtr) r->children->children;
16986     do {
16987 	if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
16988 	    return (1);
16989 	part = (xmlSchemaParticlePtr) part->next;
16990     } while (part != NULL);
16991     /*
16992     * SPEC (2) "The effective total range of the group [...] is a
16993     * valid restriction of B's occurrence range as defined by
16994     * Occurrence Range OK (�3.9.6)."
16995     */
16996     if (xmlSchemaCheckParticleRangeOK(
16997 	    xmlSchemaGetParticleTotalRangeMin(r),
16998 	    xmlSchemaGetParticleTotalRangeMax(r),
16999 	    b->minOccurs, b->maxOccurs) != 0)
17000 	return (1);
17001     return (0);
17002 }
17003 
17004 /**
17005  * xmlSchemaCheckRCaseRecurse:
17006  * @ctxt:  the schema parser context
17007  * @r: the <all> or <sequence> model group particle
17008  * @b: the base <all> or <sequence> model group particle
17009  *
17010  * (3.9.6) Constraints on Particle Schema Components
17011  * Schema Component Constraint:
17012  * Particle Derivation OK (All:All,Sequence:Sequence --
17013                            Recurse)
17014  * (rcase-Recurse)
17015  *
17016  * STATUS:  ?
17017  * TODO: subst-groups
17018  *
17019  * Returns 0 if the constraints are satisfied, a positive
17020  * error code if not and -1 if an internal error occured.
17021  */
17022 static int
xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)17023 xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
17024 			   xmlSchemaParticlePtr r,
17025 			   xmlSchemaParticlePtr b)
17026 {
17027     /* xmlSchemaParticlePtr part; */
17028     /* TODO: Error codes (rcase-Recurse). */
17029     if ((r->children == NULL) || (b->children == NULL) ||
17030 	(r->children->type != b->children->type))
17031 	return (-1);
17032     /*
17033     * SPEC "For an all or sequence group particle to be a �valid
17034     * restriction� of another group particle with the same {compositor}..."
17035     *
17036     * SPEC (1) "R's occurrence range is a valid restriction of B's
17037     * occurrence range as defined by Occurrence Range OK (�3.9.6)."
17038     */
17039     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17040 	    b->minOccurs, b->maxOccurs))
17041 	return (1);
17042 
17043 
17044     return (0);
17045 }
17046 
17047 #endif
17048 
17049 #define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
17050     xmlSchemaPCustomErrExt(pctxt,      \
17051 	XML_SCHEMAP_INVALID_FACET_VALUE, \
17052 	WXS_BASIC_CAST fac1, fac1->node, \
17053 	"It is an error for both '%s' and '%s' to be specified on the "\
17054 	"same type definition", \
17055 	BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
17056 	BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
17057 
17058 #define FACET_RESTR_ERR(fac1, msg) \
17059     xmlSchemaPCustomErr(pctxt,      \
17060 	XML_SCHEMAP_INVALID_FACET_VALUE, \
17061 	WXS_BASIC_CAST fac1, fac1->node, \
17062 	msg, NULL);
17063 
17064 #define FACET_RESTR_FIXED_ERR(fac) \
17065     xmlSchemaPCustomErr(pctxt, \
17066 	XML_SCHEMAP_INVALID_FACET_VALUE, \
17067 	WXS_BASIC_CAST fac, fac->node, \
17068 	"The base type's facet is 'fixed', thus the value must not " \
17069 	"differ", NULL);
17070 
17071 static void
xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,xmlSchemaFacetPtr facet1,xmlSchemaFacetPtr facet2,int lessGreater,int orEqual,int ofBase)17072 xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
17073 			xmlSchemaFacetPtr facet1,
17074 			xmlSchemaFacetPtr facet2,
17075 			int lessGreater,
17076 			int orEqual,
17077 			int ofBase)
17078 {
17079     xmlChar *msg = NULL;
17080 
17081     msg = xmlStrdup(BAD_CAST "'");
17082     msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
17083     msg = xmlStrcat(msg, BAD_CAST "' has to be");
17084     if (lessGreater == 0)
17085 	msg = xmlStrcat(msg, BAD_CAST " equal to");
17086     if (lessGreater == 1)
17087 	msg = xmlStrcat(msg, BAD_CAST " greater than");
17088     else
17089 	msg = xmlStrcat(msg, BAD_CAST " less than");
17090 
17091     if (orEqual)
17092 	msg = xmlStrcat(msg, BAD_CAST " or equal to");
17093     msg = xmlStrcat(msg, BAD_CAST " '");
17094     msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
17095     if (ofBase)
17096 	msg = xmlStrcat(msg, BAD_CAST "' of the base type");
17097     else
17098 	msg = xmlStrcat(msg, BAD_CAST "'");
17099 
17100     xmlSchemaPCustomErr(pctxt,
17101 	XML_SCHEMAP_INVALID_FACET_VALUE,
17102 	WXS_BASIC_CAST facet1, NULL,
17103 	(const char *) msg, NULL);
17104 
17105     if (msg != NULL)
17106 	xmlFree(msg);
17107 }
17108 
17109 /*
17110 * xmlSchemaDeriveAndValidateFacets:
17111 *
17112 * Schema Component Constraint: Simple Type Restriction (Facets)
17113 * (st-restrict-facets)
17114 */
17115 static int
xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)17116 xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
17117 				 xmlSchemaTypePtr type)
17118 {
17119     xmlSchemaTypePtr base = type->baseType;
17120     xmlSchemaFacetLinkPtr link, cur, last = NULL;
17121     xmlSchemaFacetPtr facet, bfacet,
17122 	flength = NULL, ftotdig = NULL, ffracdig = NULL,
17123 	fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
17124 	fmininc = NULL, fmaxinc = NULL,
17125 	fminexc = NULL, fmaxexc = NULL,
17126 	bflength = NULL, bftotdig = NULL, bffracdig = NULL,
17127 	bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
17128 	bfmininc = NULL, bfmaxinc = NULL,
17129 	bfminexc = NULL, bfmaxexc = NULL;
17130     int res; /* err = 0, fixedErr; */
17131 
17132     /*
17133     * SPEC st-restrict-facets 1:
17134     * "The {variety} of R is the same as that of B."
17135     */
17136     /*
17137     * SPEC st-restrict-facets 2:
17138     * "If {variety} is atomic, the {primitive type definition}
17139     * of R is the same as that of B."
17140     *
17141     * NOTE: we leave 1 & 2 out for now, since this will be
17142     * satisfied by the derivation process.
17143     * CONSTRUCTION TODO: Maybe needed if using a construction API.
17144     */
17145     /*
17146     * SPEC st-restrict-facets 3:
17147     * "The {facets} of R are the union of S and the {facets}
17148     * of B, eliminating duplicates. To eliminate duplicates,
17149     * when a facet of the same kind occurs in both S and the
17150     * {facets} of B, the one in the {facets} of B is not
17151     * included, with the exception of enumeration and pattern
17152     * facets, for which multiple occurrences with distinct values
17153     * are allowed."
17154     */
17155 
17156     if ((type->facetSet == NULL) && (base->facetSet == NULL))
17157 	return (0);
17158 
17159     last = type->facetSet;
17160     if (last != NULL)
17161 	while (last->next != NULL)
17162 	    last = last->next;
17163 
17164     for (cur = type->facetSet; cur != NULL; cur = cur->next) {
17165 	facet = cur->facet;
17166 	switch (facet->type) {
17167 	    case XML_SCHEMA_FACET_LENGTH:
17168 		flength = facet; break;
17169 	    case XML_SCHEMA_FACET_MINLENGTH:
17170 		fminlen = facet; break;
17171 	    case XML_SCHEMA_FACET_MININCLUSIVE:
17172 		fmininc = facet; break;
17173 	    case XML_SCHEMA_FACET_MINEXCLUSIVE:
17174 		fminexc = facet; break;
17175 	    case XML_SCHEMA_FACET_MAXLENGTH:
17176 		fmaxlen = facet; break;
17177 	    case XML_SCHEMA_FACET_MAXINCLUSIVE:
17178 		fmaxinc = facet; break;
17179 	    case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17180 		fmaxexc = facet; break;
17181 	    case XML_SCHEMA_FACET_TOTALDIGITS:
17182 		ftotdig = facet; break;
17183 	    case XML_SCHEMA_FACET_FRACTIONDIGITS:
17184 		ffracdig = facet; break;
17185 	    default:
17186 		break;
17187 	}
17188     }
17189     for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17190 	facet = cur->facet;
17191 	switch (facet->type) {
17192 	    case XML_SCHEMA_FACET_LENGTH:
17193 		bflength = facet; break;
17194 	    case XML_SCHEMA_FACET_MINLENGTH:
17195 		bfminlen = facet; break;
17196 	    case XML_SCHEMA_FACET_MININCLUSIVE:
17197 		bfmininc = facet; break;
17198 	    case XML_SCHEMA_FACET_MINEXCLUSIVE:
17199 		bfminexc = facet; break;
17200 	    case XML_SCHEMA_FACET_MAXLENGTH:
17201 		bfmaxlen = facet; break;
17202 	    case XML_SCHEMA_FACET_MAXINCLUSIVE:
17203 		bfmaxinc = facet; break;
17204 	    case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17205 		bfmaxexc = facet; break;
17206 	    case XML_SCHEMA_FACET_TOTALDIGITS:
17207 		bftotdig = facet; break;
17208 	    case XML_SCHEMA_FACET_FRACTIONDIGITS:
17209 		bffracdig = facet; break;
17210 	    default:
17211 		break;
17212 	}
17213     }
17214     /*
17215     * length and minLength or maxLength (2.2) + (3.2)
17216     */
17217     if (flength && (fminlen || fmaxlen)) {
17218 	FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
17219 	    "either of 'minLength' or 'maxLength' to be specified on "
17220 	    "the same type definition")
17221     }
17222     /*
17223     * Mutual exclusions in the same derivation step.
17224     */
17225     if ((fmaxinc) && (fmaxexc)) {
17226 	/*
17227 	* SCC "maxInclusive and maxExclusive"
17228 	*/
17229 	FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
17230     }
17231     if ((fmininc) && (fminexc)) {
17232 	/*
17233 	* SCC "minInclusive and minExclusive"
17234 	*/
17235 	FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
17236     }
17237 
17238     if (flength && bflength) {
17239 	/*
17240 	* SCC "length valid restriction"
17241 	* The values have to be equal.
17242 	*/
17243 	res = xmlSchemaCompareValues(flength->val, bflength->val);
17244 	if (res == -2)
17245 	    goto internal_error;
17246 	if (res != 0)
17247 	    xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
17248 	if ((res != 0) && (bflength->fixed)) {
17249 	    FACET_RESTR_FIXED_ERR(flength)
17250 	}
17251 
17252     }
17253     if (fminlen && bfminlen) {
17254 	/*
17255 	* SCC "minLength valid restriction"
17256 	* minLength >= BASE minLength
17257 	*/
17258 	res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
17259 	if (res == -2)
17260 	    goto internal_error;
17261 	if (res == -1)
17262 	    xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
17263 	if ((res != 0) && (bfminlen->fixed)) {
17264 	    FACET_RESTR_FIXED_ERR(fminlen)
17265 	}
17266     }
17267     if (fmaxlen && bfmaxlen) {
17268 	/*
17269 	* SCC "maxLength valid restriction"
17270 	* maxLength <= BASE minLength
17271 	*/
17272 	res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
17273 	if (res == -2)
17274 	    goto internal_error;
17275 	if (res == 1)
17276 	    xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
17277 	if ((res != 0) && (bfmaxlen->fixed)) {
17278 	    FACET_RESTR_FIXED_ERR(fmaxlen)
17279 	}
17280     }
17281     /*
17282     * SCC "length and minLength or maxLength"
17283     */
17284     if (! flength)
17285 	flength = bflength;
17286     if (flength) {
17287 	if (! fminlen)
17288 	    flength = bflength;
17289 	if (fminlen) {
17290 	    /* (1.1) length >= minLength */
17291 	    res = xmlSchemaCompareValues(flength->val, fminlen->val);
17292 	    if (res == -2)
17293 		goto internal_error;
17294 	    if (res == -1)
17295 		xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
17296 	}
17297 	if (! fmaxlen)
17298 	    fmaxlen = bfmaxlen;
17299 	if (fmaxlen) {
17300 	    /* (2.1) length <= maxLength */
17301 	    res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
17302 	    if (res == -2)
17303 		goto internal_error;
17304 	    if (res == 1)
17305 		xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
17306 	}
17307     }
17308     if (fmaxinc) {
17309 	/*
17310 	* "maxInclusive"
17311 	*/
17312 	if (fmininc) {
17313 	    /* SCC "maxInclusive >= minInclusive" */
17314 	    res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
17315 	    if (res == -2)
17316 		goto internal_error;
17317 	    if (res == -1) {
17318 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
17319 	    }
17320 	}
17321 	/*
17322 	* SCC "maxInclusive valid restriction"
17323 	*/
17324 	if (bfmaxinc) {
17325 	    /* maxInclusive <= BASE maxInclusive */
17326 	    res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
17327 	    if (res == -2)
17328 		goto internal_error;
17329 	    if (res == 1)
17330 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
17331 	    if ((res != 0) && (bfmaxinc->fixed)) {
17332 		FACET_RESTR_FIXED_ERR(fmaxinc)
17333 	    }
17334 	}
17335 	if (bfmaxexc) {
17336 	    /* maxInclusive < BASE maxExclusive */
17337 	    res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
17338 	    if (res == -2)
17339 		goto internal_error;
17340 	    if (res != -1) {
17341 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
17342 	    }
17343 	}
17344 	if (bfmininc) {
17345 	    /* maxInclusive >= BASE minInclusive */
17346 	    res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
17347 	    if (res == -2)
17348 		goto internal_error;
17349 	    if (res == -1) {
17350 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
17351 	    }
17352 	}
17353 	if (bfminexc) {
17354 	    /* maxInclusive > BASE minExclusive */
17355 	    res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
17356 	    if (res == -2)
17357 		goto internal_error;
17358 	    if (res != 1) {
17359 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
17360 	    }
17361 	}
17362     }
17363     if (fmaxexc) {
17364 	/*
17365 	* "maxExclusive >= minExclusive"
17366 	*/
17367 	if (fminexc) {
17368 	    res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
17369 	    if (res == -2)
17370 		goto internal_error;
17371 	    if (res == -1) {
17372 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
17373 	    }
17374 	}
17375 	/*
17376 	* "maxExclusive valid restriction"
17377 	*/
17378 	if (bfmaxexc) {
17379 	    /* maxExclusive <= BASE maxExclusive */
17380 	    res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
17381 	    if (res == -2)
17382 		goto internal_error;
17383 	    if (res == 1) {
17384 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
17385 	    }
17386 	    if ((res != 0) && (bfmaxexc->fixed)) {
17387 		FACET_RESTR_FIXED_ERR(fmaxexc)
17388 	    }
17389 	}
17390 	if (bfmaxinc) {
17391 	    /* maxExclusive <= BASE maxInclusive */
17392 	    res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
17393 	    if (res == -2)
17394 		goto internal_error;
17395 	    if (res == 1) {
17396 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
17397 	    }
17398 	}
17399 	if (bfmininc) {
17400 	    /* maxExclusive > BASE minInclusive */
17401 	    res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
17402 	    if (res == -2)
17403 		goto internal_error;
17404 	    if (res != 1) {
17405 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
17406 	    }
17407 	}
17408 	if (bfminexc) {
17409 	    /* maxExclusive > BASE minExclusive */
17410 	    res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
17411 	    if (res == -2)
17412 		goto internal_error;
17413 	    if (res != 1) {
17414 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
17415 	    }
17416 	}
17417     }
17418     if (fminexc) {
17419 	/*
17420 	* "minExclusive < maxInclusive"
17421 	*/
17422 	if (fmaxinc) {
17423 	    res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
17424 	    if (res == -2)
17425 		goto internal_error;
17426 	    if (res != -1) {
17427 		xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
17428 	    }
17429 	}
17430 	/*
17431 	* "minExclusive valid restriction"
17432 	*/
17433 	if (bfminexc) {
17434 	    /* minExclusive >= BASE minExclusive */
17435 	    res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
17436 	    if (res == -2)
17437 		goto internal_error;
17438 	    if (res == -1) {
17439 		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
17440 	    }
17441 	    if ((res != 0) && (bfminexc->fixed)) {
17442 		FACET_RESTR_FIXED_ERR(fminexc)
17443 	    }
17444 	}
17445 	if (bfmaxinc) {
17446 	    /* minExclusive <= BASE maxInclusive */
17447 	    res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
17448 	    if (res == -2)
17449 		goto internal_error;
17450 	    if (res == 1) {
17451 		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
17452 	    }
17453 	}
17454 	if (bfmininc) {
17455 	    /* minExclusive >= BASE minInclusive */
17456 	    res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
17457 	    if (res == -2)
17458 		goto internal_error;
17459 	    if (res == -1) {
17460 		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
17461 	    }
17462 	}
17463 	if (bfmaxexc) {
17464 	    /* minExclusive < BASE maxExclusive */
17465 	    res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
17466 	    if (res == -2)
17467 		goto internal_error;
17468 	    if (res != -1) {
17469 		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
17470 	    }
17471 	}
17472     }
17473     if (fmininc) {
17474 	/*
17475 	* "minInclusive < maxExclusive"
17476 	*/
17477 	if (fmaxexc) {
17478 	    res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
17479 	    if (res == -2)
17480 		goto internal_error;
17481 	    if (res != -1) {
17482 		xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
17483 	    }
17484 	}
17485 	/*
17486 	* "minExclusive valid restriction"
17487 	*/
17488 	if (bfmininc) {
17489 	    /* minInclusive >= BASE minInclusive */
17490 	    res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
17491 	    if (res == -2)
17492 		goto internal_error;
17493 	    if (res == -1) {
17494 		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
17495 	    }
17496 	    if ((res != 0) && (bfmininc->fixed)) {
17497 		FACET_RESTR_FIXED_ERR(fmininc)
17498 	    }
17499 	}
17500 	if (bfmaxinc) {
17501 	    /* minInclusive <= BASE maxInclusive */
17502 	    res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
17503 	    if (res == -2)
17504 		goto internal_error;
17505 	    if (res == 1) {
17506 		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
17507 	    }
17508 	}
17509 	if (bfminexc) {
17510 	    /* minInclusive > BASE minExclusive */
17511 	    res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
17512 	    if (res == -2)
17513 		goto internal_error;
17514 	    if (res != 1)
17515 		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
17516 	}
17517 	if (bfmaxexc) {
17518 	    /* minInclusive < BASE maxExclusive */
17519 	    res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
17520 	    if (res == -2)
17521 		goto internal_error;
17522 	    if (res != -1)
17523 		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
17524 	}
17525     }
17526     if (ftotdig && bftotdig) {
17527 	/*
17528 	* SCC " totalDigits valid restriction"
17529 	* totalDigits <= BASE totalDigits
17530 	*/
17531 	res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
17532 	if (res == -2)
17533 	    goto internal_error;
17534 	if (res == 1)
17535 	    xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
17536 	    -1, 1, 1);
17537 	if ((res != 0) && (bftotdig->fixed)) {
17538 	    FACET_RESTR_FIXED_ERR(ftotdig)
17539 	}
17540     }
17541     if (ffracdig && bffracdig) {
17542 	/*
17543 	* SCC  "fractionDigits valid restriction"
17544 	* fractionDigits <= BASE fractionDigits
17545 	*/
17546 	res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
17547 	if (res == -2)
17548 	    goto internal_error;
17549 	if (res == 1)
17550 	    xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
17551 	    -1, 1, 1);
17552 	if ((res != 0) && (bffracdig->fixed)) {
17553 	    FACET_RESTR_FIXED_ERR(ffracdig)
17554 	}
17555     }
17556     /*
17557     * SCC "fractionDigits less than or equal to totalDigits"
17558     */
17559     if (! ftotdig)
17560 	ftotdig = bftotdig;
17561     if (! ffracdig)
17562 	ffracdig = bffracdig;
17563     if (ftotdig && ffracdig) {
17564 	res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
17565 	if (res == -2)
17566 	    goto internal_error;
17567 	if (res == 1)
17568 	    xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
17569 		-1, 1, 0);
17570     }
17571     /*
17572     * *Enumerations* won' be added here, since only the first set
17573     * of enumerations in the ancestor-or-self axis is used
17574     * for validation, plus we need to use the base type of those
17575     * enumerations for whitespace.
17576     *
17577     * *Patterns*: won't be add here, since they are ORed at
17578     * type level and ANDed at ancestor level. This will
17579     * happed during validation by walking the base axis
17580     * of the type.
17581     */
17582     for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17583 	bfacet = cur->facet;
17584 	/*
17585 	* Special handling of enumerations and patterns.
17586 	* TODO: hmm, they should not appear in the set, so remove this.
17587 	*/
17588 	if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
17589 	    (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
17590 	    continue;
17591 	/*
17592 	* Search for a duplicate facet in the current type.
17593 	*/
17594 	link = type->facetSet;
17595 	/* err = 0; */
17596 	/* fixedErr = 0; */
17597 	while (link != NULL) {
17598 	    facet = link->facet;
17599 	    if (facet->type == bfacet->type) {
17600 		switch (facet->type) {
17601 		    case XML_SCHEMA_FACET_WHITESPACE:
17602 			/*
17603 			* The whitespace must be stronger.
17604 			*/
17605 			if (facet->whitespace < bfacet->whitespace) {
17606 			    FACET_RESTR_ERR(flength,
17607 				"The 'whitespace' value has to be equal to "
17608 				"or stronger than the 'whitespace' value of "
17609 				"the base type")
17610 			}
17611 			if ((bfacet->fixed) &&
17612 			    (facet->whitespace != bfacet->whitespace)) {
17613 			    FACET_RESTR_FIXED_ERR(facet)
17614 			}
17615 			break;
17616 		    default:
17617 			break;
17618 		}
17619 		/* Duplicate found. */
17620 		break;
17621 	    }
17622 	    link = link->next;
17623 	}
17624 	/*
17625 	* If no duplicate was found: add the base types's facet
17626 	* to the set.
17627 	*/
17628 	if (link == NULL) {
17629 	    link = (xmlSchemaFacetLinkPtr)
17630 		xmlMalloc(sizeof(xmlSchemaFacetLink));
17631 	    if (link == NULL) {
17632 		xmlSchemaPErrMemory(pctxt,
17633 		    "deriving facets, creating a facet link", NULL);
17634 		return (-1);
17635 	    }
17636 	    link->facet = cur->facet;
17637 	    link->next = NULL;
17638 	    if (last == NULL)
17639 		type->facetSet = link;
17640 	    else
17641 		last->next = link;
17642 	    last = link;
17643 	}
17644 
17645     }
17646 
17647     return (0);
17648 internal_error:
17649     PERROR_INT("xmlSchemaDeriveAndValidateFacets",
17650 	"an error occured");
17651     return (-1);
17652 }
17653 
17654 static int
xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)17655 xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
17656 					     xmlSchemaTypePtr type)
17657 {
17658     xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
17659     /*
17660     * The actual value is then formed by replacing any union type
17661     * definition in the �explicit members� with the members of their
17662     * {member type definitions}, in order.
17663     *
17664     * TODO: There's a bug entry at
17665     * "http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0287.html"
17666     * which indicates that we'll keep the union types the future.
17667     */
17668     link = type->memberTypes;
17669     while (link != NULL) {
17670 
17671 	if (WXS_IS_TYPE_NOT_FIXED(link->type))
17672 	    xmlSchemaTypeFixup(link->type, ACTXT_CAST pctxt);
17673 
17674 	if (WXS_IS_UNION(link->type)) {
17675 	    subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
17676 	    if (subLink != NULL) {
17677 		link->type = subLink->type;
17678 		if (subLink->next != NULL) {
17679 		    lastLink = link->next;
17680 		    subLink = subLink->next;
17681 		    prevLink = link;
17682 		    while (subLink != NULL) {
17683 			newLink = (xmlSchemaTypeLinkPtr)
17684 			    xmlMalloc(sizeof(xmlSchemaTypeLink));
17685 			if (newLink == NULL) {
17686 			    xmlSchemaPErrMemory(pctxt, "allocating a type link",
17687 				NULL);
17688 			    return (-1);
17689 			}
17690 			newLink->type = subLink->type;
17691 			prevLink->next = newLink;
17692 			prevLink = newLink;
17693 			newLink->next = lastLink;
17694 
17695 			subLink = subLink->next;
17696 		    }
17697 		}
17698 	    }
17699 	}
17700 	link = link->next;
17701     }
17702     return (0);
17703 }
17704 
17705 static void
xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)17706 xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
17707 {
17708     int has = 0, needVal = 0, normVal = 0;
17709 
17710     has	= (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
17711     if (has) {
17712 	needVal = (type->baseType->flags &
17713 	    XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
17714 	normVal = (type->baseType->flags &
17715 	    XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
17716     }
17717     if (type->facets != NULL) {
17718 	xmlSchemaFacetPtr fac;
17719 
17720 	for (fac = type->facets; fac != NULL; fac = fac->next) {
17721 	    switch (fac->type) {
17722 		case XML_SCHEMA_FACET_WHITESPACE:
17723 		    break;
17724 		case XML_SCHEMA_FACET_PATTERN:
17725 		    normVal = 1;
17726 		    has = 1;
17727 		    break;
17728 		case XML_SCHEMA_FACET_ENUMERATION:
17729 		    needVal = 1;
17730 		    normVal = 1;
17731 		    has = 1;
17732 		    break;
17733 		default:
17734 		    has = 1;
17735 		    break;
17736 	    }
17737 	}
17738     }
17739     if (normVal)
17740 	type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
17741     if (needVal)
17742 	type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17743     if (has)
17744 	type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
17745 
17746     if (has && (! needVal) && WXS_IS_ATOMIC(type)) {
17747 	xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
17748 	/*
17749 	* OPTIMIZE VAL TODO: Some facets need a computed value.
17750 	*/
17751 	if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
17752 	    (prim->builtInType != XML_SCHEMAS_STRING)) {
17753 	    type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17754 	}
17755     }
17756 }
17757 
17758 static int
xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)17759 xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
17760 {
17761 
17762 
17763     /*
17764     * Evaluate the whitespace-facet value.
17765     */
17766     if (WXS_IS_LIST(type)) {
17767 	type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17768 	return (0);
17769     } else if (WXS_IS_UNION(type))
17770 	return (0);
17771 
17772     if (type->facetSet != NULL) {
17773 	xmlSchemaFacetLinkPtr lin;
17774 
17775 	for (lin = type->facetSet; lin != NULL; lin = lin->next) {
17776 	    if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
17777 		switch (lin->facet->whitespace) {
17778 		case XML_SCHEMAS_FACET_PRESERVE:
17779 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17780 		    break;
17781 		case XML_SCHEMAS_FACET_REPLACE:
17782 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17783 		    break;
17784 		case XML_SCHEMAS_FACET_COLLAPSE:
17785 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17786 		    break;
17787 		default:
17788 		    return (-1);
17789 		}
17790 		return (0);
17791 	    }
17792 	}
17793     }
17794     /*
17795     * For all �atomic� datatypes other than string (and types �derived�
17796     * by �restriction� from it) the value of whiteSpace is fixed to
17797     * collapse
17798     */
17799     {
17800 	xmlSchemaTypePtr anc;
17801 
17802 	for (anc = type->baseType; anc != NULL &&
17803 		anc->builtInType != XML_SCHEMAS_ANYTYPE;
17804 		anc = anc->baseType) {
17805 
17806 	    if (anc->type == XML_SCHEMA_TYPE_BASIC) {
17807 		if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
17808 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17809 
17810 		} else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
17811 		    (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
17812 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17813 
17814 		} else
17815 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17816 		break;
17817 	    }
17818 	}
17819     }
17820     return (0);
17821 }
17822 
17823 static int
xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)17824 xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,
17825 			  xmlSchemaTypePtr type)
17826 {
17827     if (type->type != XML_SCHEMA_TYPE_SIMPLE)
17828 	return(0);
17829     if (! WXS_IS_TYPE_NOT_FIXED_1(type))
17830 	return(0);
17831     type->flags |= XML_SCHEMAS_TYPE_FIXUP_1;
17832 
17833     if (WXS_IS_LIST(type)) {
17834 	/*
17835 	* Corresponds to <simpleType><list>...
17836 	*/
17837 	if (type->subtypes == NULL) {
17838 	    /*
17839 	    * This one is really needed, so get out.
17840 	    */
17841 	    PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17842 		"list type has no item-type assigned");
17843 	    return(-1);
17844 	}
17845     } else if (WXS_IS_UNION(type)) {
17846 	/*
17847 	* Corresponds to <simpleType><union>...
17848 	*/
17849 	if (type->memberTypes == NULL) {
17850 	    /*
17851 	    * This one is really needed, so get out.
17852 	    */
17853 	    PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17854 		"union type has no member-types assigned");
17855 	    return(-1);
17856 	}
17857     } else {
17858 	/*
17859 	* Corresponds to <simpleType><restriction>...
17860 	*/
17861 	if (type->baseType == NULL) {
17862 	    PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17863 		"type has no base-type assigned");
17864 	    return(-1);
17865 	}
17866 	if (WXS_IS_TYPE_NOT_FIXED_1(type->baseType))
17867 	    if (xmlSchemaFixupSimpleTypeStageOne(pctxt, type->baseType) == -1)
17868 		return(-1);
17869 	/*
17870 	* Variety
17871 	* If the <restriction> alternative is chosen, then the
17872 	* {variety} of the {base type definition}.
17873 	*/
17874 	if (WXS_IS_ATOMIC(type->baseType))
17875 	    type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
17876 	else if (WXS_IS_LIST(type->baseType)) {
17877 	    type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
17878 	    /*
17879 	    * Inherit the itemType.
17880 	    */
17881 	    type->subtypes = type->baseType->subtypes;
17882 	} else if (WXS_IS_UNION(type->baseType)) {
17883 	    type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
17884 	    /*
17885 	    * NOTE that we won't assign the memberTypes of the base,
17886 	    * since this will make trouble when freeing them; we will
17887 	    * use a lookup function to access them instead.
17888 	    */
17889 	}
17890     }
17891     return(0);
17892 }
17893 
17894 #ifdef DEBUG_TYPE
17895 static void
xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)17896 xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt,
17897 		       xmlSchemaTypePtr type)
17898 {
17899     if (type->node != NULL) {
17900         xmlGenericError(xmlGenericErrorContext,
17901                         "Type of %s : %s:%d :", name,
17902                         type->node->doc->URL,
17903                         xmlGetLineNo(type->node));
17904     } else {
17905         xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
17906     }
17907     if ((WXS_IS_SIMPLE(type)) || (WXS_IS_COMPLEX(type))) {
17908 	switch (type->contentType) {
17909 	    case XML_SCHEMA_CONTENT_SIMPLE:
17910 		xmlGenericError(xmlGenericErrorContext, "simple\n");
17911 		break;
17912 	    case XML_SCHEMA_CONTENT_ELEMENTS:
17913 		xmlGenericError(xmlGenericErrorContext, "elements\n");
17914 		break;
17915 	    case XML_SCHEMA_CONTENT_UNKNOWN:
17916 		xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
17917 		break;
17918 	    case XML_SCHEMA_CONTENT_EMPTY:
17919 		xmlGenericError(xmlGenericErrorContext, "empty\n");
17920 		break;
17921 	    case XML_SCHEMA_CONTENT_MIXED:
17922 		if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
17923 		    type->subtypes))
17924 		    xmlGenericError(xmlGenericErrorContext,
17925 			"mixed as emptiable particle\n");
17926 		else
17927 		    xmlGenericError(xmlGenericErrorContext, "mixed\n");
17928 		break;
17929 		/* Removed, since not used. */
17930 		/*
17931 		case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
17932 		xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
17933 		break;
17934 		*/
17935 	    case XML_SCHEMA_CONTENT_BASIC:
17936 		xmlGenericError(xmlGenericErrorContext, "basic\n");
17937 		break;
17938 	    default:
17939 		xmlGenericError(xmlGenericErrorContext,
17940 		    "not registered !!!\n");
17941 		break;
17942 	}
17943     }
17944 }
17945 #endif
17946 
17947 /*
17948 * 3.14.6 Constraints on Simple Type Definition Schema Components
17949 */
17950 static int
xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)17951 xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,
17952 				 xmlSchemaTypePtr type)
17953 {
17954     int res, olderrs = pctxt->nberrors;
17955 
17956     if (type->type != XML_SCHEMA_TYPE_SIMPLE)
17957 	return(-1);
17958 
17959     if (! WXS_IS_TYPE_NOT_FIXED(type))
17960 	return(0);
17961 
17962     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
17963     type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
17964 
17965     if (type->baseType == NULL) {
17966 	PERROR_INT("xmlSchemaFixupSimpleTypeStageTwo",
17967 	    "missing baseType");
17968 	goto exit_failure;
17969     }
17970     if (WXS_IS_TYPE_NOT_FIXED(type->baseType))
17971 	xmlSchemaTypeFixup(type->baseType, ACTXT_CAST pctxt);
17972     /*
17973     * If a member type of a union is a union itself, we need to substitute
17974     * that member type for its member types.
17975     * NOTE that this might change in WXS 1.1; i.e. we will keep the union
17976     * types in WXS 1.1.
17977     */
17978     if ((type->memberTypes != NULL) &&
17979 	(xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1))
17980 	return(-1);
17981     /*
17982     * SPEC src-simple-type 1
17983     * "The corresponding simple type definition, if any, must satisfy
17984     * the conditions set out in Constraints on Simple Type Definition
17985     * Schema Components (�3.14.6)."
17986     */
17987     /*
17988     * Schema Component Constraint: Simple Type Definition Properties Correct
17989     * (st-props-correct)
17990     */
17991     res = xmlSchemaCheckSTPropsCorrect(pctxt, type);
17992     HFAILURE HERROR
17993     /*
17994     * Schema Component Constraint: Derivation Valid (Restriction, Simple)
17995     * (cos-st-restricts)
17996     */
17997     res = xmlSchemaCheckCOSSTRestricts(pctxt, type);
17998     HFAILURE HERROR
17999     /*
18000     * TODO: Removed the error report, since it got annoying to get an
18001     * extra error report, if anything failed until now.
18002     * Enable this if needed.
18003     *
18004     * xmlSchemaPErr(ctxt, type->node,
18005     *    XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
18006     *    "Simple type '%s' does not satisfy the constraints "
18007     *    "on simple type definitions.\n",
18008     *    type->name, NULL);
18009     */
18010     /*
18011     * Schema Component Constraint: Simple Type Restriction (Facets)
18012     * (st-restrict-facets)
18013     */
18014     res = xmlSchemaCheckFacetValues(type, pctxt);
18015     HFAILURE HERROR
18016     if ((type->facetSet != NULL) ||
18017 	(type->baseType->facetSet != NULL)) {
18018 	res = xmlSchemaDeriveAndValidateFacets(pctxt, type);
18019 	HFAILURE HERROR
18020     }
18021     /*
18022     * Whitespace value.
18023     */
18024     res = xmlSchemaTypeFixupWhitespace(type);
18025     HFAILURE HERROR
18026     xmlSchemaTypeFixupOptimFacets(type);
18027 
18028 exit_error:
18029 #ifdef DEBUG_TYPE
18030     xmlSchemaDebugFixedType(pctxt, type);
18031 #endif
18032     if (olderrs != pctxt->nberrors)
18033 	return(pctxt->err);
18034     return(0);
18035 
18036 exit_failure:
18037 #ifdef DEBUG_TYPE
18038     xmlSchemaDebugFixedType(pctxt, type);
18039 #endif
18040     return(-1);
18041 }
18042 
18043 static int
xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)18044 xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,
18045 			  xmlSchemaTypePtr type)
18046 {
18047     int res = 0, olderrs = pctxt->nberrors;
18048     xmlSchemaTypePtr baseType = type->baseType;
18049 
18050     if (! WXS_IS_TYPE_NOT_FIXED(type))
18051 	return(0);
18052     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18053     if (baseType == NULL) {
18054 	PERROR_INT("xmlSchemaFixupComplexType",
18055 	    "missing baseType");
18056 	goto exit_failure;
18057     }
18058     /*
18059     * Fixup the base type.
18060     */
18061     if (WXS_IS_TYPE_NOT_FIXED(baseType))
18062 	xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt);
18063     if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
18064 	/*
18065 	* Skip fixup if the base type is invalid.
18066 	* TODO: Generate a warning!
18067 	*/
18068 	return(0);
18069     }
18070     /*
18071     * This basically checks if the base type can be derived.
18072     */
18073     res = xmlSchemaCheckSRCCT(pctxt, type);
18074     HFAILURE HERROR
18075     /*
18076     * Fixup the content type.
18077     */
18078     if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
18079 	/*
18080 	* Corresponds to <complexType><simpleContent>...
18081 	*/
18082 	if ((WXS_IS_COMPLEX(baseType)) &&
18083 	    (baseType->contentTypeDef != NULL) &&
18084 	    (WXS_IS_RESTRICTION(type))) {
18085 	    xmlSchemaTypePtr contentBase, content;
18086 #ifdef ENABLE_NAMED_LOCALS
18087 	    char buf[30];
18088 	    const xmlChar *tmpname;
18089 #endif
18090 	    /*
18091 	    * SPEC (1) If <restriction> + base type is <complexType>,
18092 	    * "whose own {content type} is a simple type..."
18093 	    */
18094 	    if (type->contentTypeDef != NULL) {
18095 		/*
18096 		* SPEC (1.1) "the simple type definition corresponding to the
18097 		* <simpleType> among the [children] of <restriction> if there
18098 		* is one;"
18099 		* Note that this "<simpleType> among the [children]" was put
18100 		* into ->contentTypeDef during parsing.
18101 		*/
18102 		contentBase = type->contentTypeDef;
18103 		type->contentTypeDef = NULL;
18104 	    } else {
18105 		/*
18106 		* (1.2) "...otherwise (<restriction> has no <simpleType>
18107 		* among its [children]), the simple type definition which
18108 		* is the {content type} of the ... base type."
18109 		*/
18110 		contentBase = baseType->contentTypeDef;
18111 	    }
18112 	    /*
18113 	    * SPEC
18114 	    * "... a simple type definition which restricts the simple
18115 	    * type definition identified in clause 1.1 or clause 1.2
18116 	    * with a set of facet components"
18117 	    *
18118 	    * Create the anonymous simple type, which will be the content
18119 	    * type of the complex type.
18120 	    */
18121 #ifdef ENABLE_NAMED_LOCALS
18122 	    snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
18123 	    tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
18124 	    content = xmlSchemaAddType(pctxt, pctxt->schema,
18125 		XML_SCHEMA_TYPE_SIMPLE, tmpname, type->targetNamespace,
18126 		type->node, 0);
18127 #else
18128 	    content = xmlSchemaAddType(pctxt, pctxt->schema,
18129 		XML_SCHEMA_TYPE_SIMPLE, NULL, type->targetNamespace,
18130 		type->node, 0);
18131 #endif
18132 	    if (content == NULL)
18133 		goto exit_failure;
18134 	    /*
18135 	    * We will use the same node as for the <complexType>
18136 	    * to have it somehow anchored in the schema doc.
18137 	    */
18138 	    content->type = XML_SCHEMA_TYPE_SIMPLE;
18139 	    content->baseType = contentBase;
18140 	    /*
18141 	    * Move the facets, previously anchored on the
18142 	    * complexType during parsing.
18143 	    */
18144 	    content->facets = type->facets;
18145 	    type->facets = NULL;
18146 	    content->facetSet = type->facetSet;
18147 	    type->facetSet = NULL;
18148 
18149 	    type->contentTypeDef = content;
18150 	    if (WXS_IS_TYPE_NOT_FIXED(contentBase))
18151 		xmlSchemaTypeFixup(contentBase, ACTXT_CAST pctxt);
18152 	    /*
18153 	    * Fixup the newly created type. We don't need to check
18154 	    * for circularity here.
18155 	    */
18156 	    res = xmlSchemaFixupSimpleTypeStageOne(pctxt, content);
18157 	    HFAILURE HERROR
18158 	    res = xmlSchemaFixupSimpleTypeStageTwo(pctxt, content);
18159 	    HFAILURE HERROR
18160 
18161 	} else if ((WXS_IS_COMPLEX(baseType)) &&
18162 	    (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
18163 	    (WXS_IS_RESTRICTION(type))) {
18164 	    /*
18165 	    * SPEC (2) If <restriction> + base is a mixed <complexType> with
18166 	    * an emptiable particle, then a simple type definition which
18167 	    * restricts the <restriction>'s <simpleType> child.
18168 	    */
18169 	    if ((type->contentTypeDef == NULL) ||
18170 		(type->contentTypeDef->baseType == NULL)) {
18171 		/*
18172 		* TODO: Check if this ever happens.
18173 		*/
18174 		xmlSchemaPCustomErr(pctxt,
18175 		    XML_SCHEMAP_INTERNAL,
18176 		    WXS_BASIC_CAST type, NULL,
18177 		    "Internal error: xmlSchemaTypeFixup, "
18178 		    "complex type '%s': the <simpleContent><restriction> "
18179 		    "is missing a <simpleType> child, but was not catched "
18180 		    "by xmlSchemaCheckSRCCT()", type->name);
18181 		goto exit_failure;
18182 	    }
18183 	} else if ((WXS_IS_COMPLEX(baseType)) && WXS_IS_EXTENSION(type)) {
18184 	    /*
18185 	    * SPEC (3) If <extension> + base is <complexType> with
18186 	    * <simpleType> content, "...then the {content type} of that
18187 	    * complex type definition"
18188 	    */
18189 	    if (baseType->contentTypeDef == NULL) {
18190 		/*
18191 		* TODO: Check if this ever happens. xmlSchemaCheckSRCCT
18192 		* should have catched this already.
18193 		*/
18194 		xmlSchemaPCustomErr(pctxt,
18195 		    XML_SCHEMAP_INTERNAL,
18196 		    WXS_BASIC_CAST type, NULL,
18197 		    "Internal error: xmlSchemaTypeFixup, "
18198 		    "complex type '%s': the <extension>ed base type is "
18199 		    "a complex type with no simple content type",
18200 		    type->name);
18201 		goto exit_failure;
18202 	    }
18203 	    type->contentTypeDef = baseType->contentTypeDef;
18204 	} else if ((WXS_IS_SIMPLE(baseType)) && WXS_IS_EXTENSION(type)) {
18205 	    /*
18206 	    * SPEC (4) <extension> + base is <simpleType>
18207 	    * "... then that simple type definition"
18208 	    */
18209 	    type->contentTypeDef = baseType;
18210 	} else {
18211 	    /*
18212 	    * TODO: Check if this ever happens.
18213 	    */
18214 	    xmlSchemaPCustomErr(pctxt,
18215 		XML_SCHEMAP_INTERNAL,
18216 		WXS_BASIC_CAST type, NULL,
18217 		"Internal error: xmlSchemaTypeFixup, "
18218 		"complex type '%s' with <simpleContent>: unhandled "
18219 		"derivation case", type->name);
18220 	    goto exit_failure;
18221 	}
18222     } else {
18223 	int dummySequence = 0;
18224 	xmlSchemaParticlePtr particle =
18225 	    (xmlSchemaParticlePtr) type->subtypes;
18226 	/*
18227 	* Corresponds to <complexType><complexContent>...
18228 	*
18229 	* NOTE that the effective mixed was already set during parsing of
18230 	* <complexType> and <complexContent>; its flag value is
18231 	* XML_SCHEMAS_TYPE_MIXED.
18232 	*
18233 	* Compute the "effective content":
18234 	* (2.1.1) + (2.1.2) + (2.1.3)
18235 	*/
18236 	if ((particle == NULL) ||
18237 	    ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
18238 	    ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
18239 	    (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
18240 	    ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
18241 	    (particle->minOccurs == 0))) &&
18242 	    ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
18243 	    if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
18244 		/*
18245 		* SPEC (2.1.4) "If the �effective mixed� is true, then
18246 		* a particle whose properties are as follows:..."
18247 		*
18248 		* Empty sequence model group with
18249 		* minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
18250 		* NOTE that we sill assign it the <complexType> node to
18251 		* somehow anchor it in the doc.
18252 		*/
18253 		if ((particle == NULL) ||
18254 		    (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
18255 		    /*
18256 		    * Create the particle.
18257 		    */
18258 		    particle = xmlSchemaAddParticle(pctxt,
18259 			type->node, 1, 1);
18260 		    if (particle == NULL)
18261 			goto exit_failure;
18262 		    /*
18263 		    * Create the model group.
18264 		    */ /* URGENT TODO: avoid adding to pending items. */
18265 		    particle->children = (xmlSchemaTreeItemPtr)
18266 			xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18267 			XML_SCHEMA_TYPE_SEQUENCE, type->node);
18268 		    if (particle->children == NULL)
18269 			goto exit_failure;
18270 
18271 		    type->subtypes = (xmlSchemaTypePtr) particle;
18272 		}
18273 		dummySequence = 1;
18274 		type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18275 	    } else {
18276 		/*
18277 		* SPEC (2.1.5) "otherwise empty"
18278 		*/
18279 		type->contentType = XML_SCHEMA_CONTENT_EMPTY;
18280 	    }
18281 	} else {
18282 	    /*
18283 	    * SPEC (2.2) "otherwise the particle corresponding to the
18284 	    * <all>, <choice>, <group> or <sequence> among the
18285 	    * [children]."
18286 	    */
18287 	    type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18288 	}
18289 	/*
18290 	* Compute the "content type".
18291 	*/
18292 	if (WXS_IS_RESTRICTION(type)) {
18293 	    /*
18294 	    * SPEC (3.1) "If <restriction>..."
18295 	    * (3.1.1) + (3.1.2) */
18296 	    if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
18297 		if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18298 		    type->contentType = XML_SCHEMA_CONTENT_MIXED;
18299 	    }
18300 	} else {
18301 	    /*
18302 	    * SPEC (3.2) "If <extension>..."
18303 	    */
18304 	    if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18305 		/*
18306 		* SPEC (3.2.1)
18307 		* "If the �effective content� is empty, then the
18308 		*  {content type} of the [...] base ..."
18309 		*/
18310 		type->contentType = baseType->contentType;
18311 		type->subtypes = baseType->subtypes;
18312 		/*
18313 		* Fixes bug #347316:
18314 		* This is the case when the base type has a simple
18315 		* type definition as content.
18316 		*/
18317 		type->contentTypeDef = baseType->contentTypeDef;
18318 		/*
18319 		* NOTE that the effective mixed is ignored here.
18320 		*/
18321 	    } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18322 		/*
18323 		* SPEC (3.2.2)
18324 		*/
18325 		if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18326 		    type->contentType = XML_SCHEMA_CONTENT_MIXED;
18327 	    } else {
18328 		/*
18329 		* SPEC (3.2.3)
18330 		*/
18331 		if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18332 		    type->contentType = XML_SCHEMA_CONTENT_MIXED;
18333 		    /*
18334 		    * "A model group whose {compositor} is sequence and whose
18335 		    * {particles} are..."
18336 		    */
18337 		if ((WXS_TYPE_PARTICLE(type) != NULL) &&
18338 		    (WXS_TYPE_PARTICLE_TERM(type) != NULL) &&
18339 		    ((WXS_TYPE_PARTICLE_TERM(type))->type ==
18340 			XML_SCHEMA_TYPE_ALL))
18341 		{
18342 		    /*
18343 		    * SPEC cos-all-limited (1)
18344 		    */
18345 		    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18346 			/* TODO: error code */
18347 			XML_SCHEMAP_COS_ALL_LIMITED,
18348 			WXS_ITEM_NODE(type), NULL,
18349 			"The type has an 'all' model group in its "
18350 			"{content type} and thus cannot be derived from "
18351 			"a non-empty type, since this would produce a "
18352 			"'sequence' model group containing the 'all' "
18353 			"model group; 'all' model groups are not "
18354 			"allowed to appear inside other model groups",
18355 			NULL, NULL);
18356 
18357 		} else if ((WXS_TYPE_PARTICLE(baseType) != NULL) &&
18358 		    (WXS_TYPE_PARTICLE_TERM(baseType) != NULL) &&
18359 		    ((WXS_TYPE_PARTICLE_TERM(baseType))->type ==
18360 			XML_SCHEMA_TYPE_ALL))
18361 		{
18362 		    /*
18363 		    * SPEC cos-all-limited (1)
18364 		    */
18365 		    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18366 			/* TODO: error code */
18367 			XML_SCHEMAP_COS_ALL_LIMITED,
18368 			WXS_ITEM_NODE(type), NULL,
18369 			"A type cannot be derived by extension from a type "
18370 			"which has an 'all' model group in its "
18371 			"{content type}, since this would produce a "
18372 			"'sequence' model group containing the 'all' "
18373 			"model group; 'all' model groups are not "
18374 			"allowed to appear inside other model groups",
18375 			NULL, NULL);
18376 
18377 		} else if (! dummySequence) {
18378 		    xmlSchemaTreeItemPtr effectiveContent =
18379 			(xmlSchemaTreeItemPtr) type->subtypes;
18380 		    /*
18381 		    * Create the particle.
18382 		    */
18383 		    particle = xmlSchemaAddParticle(pctxt,
18384 			type->node, 1, 1);
18385 		    if (particle == NULL)
18386 			goto exit_failure;
18387 		    /*
18388 		    * Create the "sequence" model group.
18389 		    */
18390 		    particle->children = (xmlSchemaTreeItemPtr)
18391 			xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18392 			XML_SCHEMA_TYPE_SEQUENCE, type->node);
18393 		    if (particle->children == NULL)
18394 			goto exit_failure;
18395 		    WXS_TYPE_CONTENTTYPE(type) = (xmlSchemaTypePtr) particle;
18396 		    /*
18397 		    * SPEC "the particle of the {content type} of
18398 		    * the ... base ..."
18399 		    * Create a duplicate of the base type's particle
18400 		    * and assign its "term" to it.
18401 		    */
18402 		    particle->children->children =
18403 			(xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
18404 			type->node,
18405 			((xmlSchemaParticlePtr) type->subtypes)->minOccurs,
18406 			((xmlSchemaParticlePtr) type->subtypes)->maxOccurs);
18407 		    if (particle->children->children == NULL)
18408 			goto exit_failure;
18409 		    particle = (xmlSchemaParticlePtr)
18410 			particle->children->children;
18411 		    particle->children =
18412 			((xmlSchemaParticlePtr) baseType->subtypes)->children;
18413 		    /*
18414 		    * SPEC "followed by the �effective content�."
18415 		    */
18416 		    particle->next = effectiveContent;
18417 		    /*
18418 		    * This all will result in:
18419 		    * new-particle
18420 		    *   --> new-sequence(
18421 		    *         new-particle
18422 		    *           --> base-model,
18423 		    *         this-particle
18424 		    *	        --> this-model
18425 		    *	    )
18426 		    */
18427 		} else {
18428 		    /*
18429 		    * This is the case when there is already an empty
18430 		    * <sequence> with minOccurs==maxOccurs==1.
18431 		    * Just add the base types's content type.
18432 		    * NOTE that, although we miss to add an intermediate
18433 		    * <sequence>, this should produce no difference to
18434 		    * neither the regex compilation of the content model,
18435 		    * nor to the complex type contraints.
18436 		    */
18437 		    particle->children->children =
18438 			(xmlSchemaTreeItemPtr) baseType->subtypes;
18439 		}
18440 	    }
18441 	}
18442     }
18443     /*
18444     * Now fixup attribute uses:
18445     *   - expand attr. group references
18446     *     - intersect attribute wildcards
18447     *   - inherit attribute uses of the base type
18448     *   - inherit or union attr. wildcards if extending
18449     *   - apply attr. use prohibitions if restricting
18450     */
18451     res = xmlSchemaFixupTypeAttributeUses(pctxt, type);
18452     HFAILURE HERROR
18453     /*
18454     * Apply the complex type component constraints; this will not
18455     * check attributes, since this is done in
18456     * xmlSchemaFixupTypeAttributeUses().
18457     */
18458     res = xmlSchemaCheckCTComponent(pctxt, type);
18459     HFAILURE HERROR
18460 
18461 #ifdef DEBUG_TYPE
18462     xmlSchemaDebugFixedType(pctxt, type);
18463 #endif
18464     if (olderrs != pctxt->nberrors)
18465 	return(pctxt->err);
18466     else
18467 	return(0);
18468 
18469 exit_error:
18470     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18471 #ifdef DEBUG_TYPE
18472     xmlSchemaDebugFixedType(pctxt, type);
18473 #endif
18474     return(pctxt->err);
18475 
18476 exit_failure:
18477     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18478 #ifdef DEBUG_TYPE
18479     xmlSchemaDebugFixedType(pctxt, type);
18480 #endif
18481     return(-1);
18482 }
18483 
18484 
18485 /**
18486  * xmlSchemaTypeFixup:
18487  * @typeDecl:  the schema type definition
18488  * @ctxt:  the schema parser context
18489  *
18490  * Fixes the content model of the type.
18491  * URGENT TODO: We need an int result!
18492  */
18493 static int
xmlSchemaTypeFixup(xmlSchemaTypePtr type,xmlSchemaAbstractCtxtPtr actxt)18494 xmlSchemaTypeFixup(xmlSchemaTypePtr type,
18495                    xmlSchemaAbstractCtxtPtr actxt)
18496 {
18497     if (type == NULL)
18498         return(0);
18499     if (actxt->type != XML_SCHEMA_CTXT_PARSER) {
18500 	AERROR_INT("xmlSchemaTypeFixup",
18501 	    "this function needs a parser context");
18502 	return(-1);
18503     }
18504     if (! WXS_IS_TYPE_NOT_FIXED(type))
18505 	return(0);
18506     if (type->type == XML_SCHEMA_TYPE_COMPLEX)
18507 	return(xmlSchemaFixupComplexType(PCTXT_CAST actxt, type));
18508     else if (type->type == XML_SCHEMA_TYPE_SIMPLE)
18509 	return(xmlSchemaFixupSimpleTypeStageTwo(PCTXT_CAST actxt, type));
18510     return(0);
18511 }
18512 
18513 /**
18514  * xmlSchemaCheckFacet:
18515  * @facet:  the facet
18516  * @typeDecl:  the schema type definition
18517  * @pctxt:  the schema parser context or NULL
18518  * @name: the optional name of the type
18519  *
18520  * Checks and computes the values of facets.
18521  *
18522  * Returns 0 if valid, a positive error code if not valid and
18523  *         -1 in case of an internal or API error.
18524  */
18525 int
xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,xmlSchemaTypePtr typeDecl,xmlSchemaParserCtxtPtr pctxt,const xmlChar * name ATTRIBUTE_UNUSED)18526 xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
18527                     xmlSchemaTypePtr typeDecl,
18528                     xmlSchemaParserCtxtPtr pctxt,
18529 		    const xmlChar * name ATTRIBUTE_UNUSED)
18530 {
18531     int ret = 0, ctxtGiven;
18532 
18533     if ((facet == NULL) || (typeDecl == NULL))
18534         return(-1);
18535     /*
18536     * TODO: will the parser context be given if used from
18537     * the relaxNG module?
18538     */
18539     if (pctxt == NULL)
18540 	ctxtGiven = 0;
18541     else
18542 	ctxtGiven = 1;
18543 
18544     switch (facet->type) {
18545         case XML_SCHEMA_FACET_MININCLUSIVE:
18546         case XML_SCHEMA_FACET_MINEXCLUSIVE:
18547         case XML_SCHEMA_FACET_MAXINCLUSIVE:
18548         case XML_SCHEMA_FACET_MAXEXCLUSIVE:
18549 	case XML_SCHEMA_FACET_ENUMERATION: {
18550                 /*
18551                  * Okay we need to validate the value
18552                  * at that point.
18553                  */
18554 		xmlSchemaTypePtr base;
18555 
18556 		/* 4.3.5.5 Constraints on enumeration Schema Components
18557 		* Schema Component Constraint: enumeration valid restriction
18558 		* It is an �error� if any member of {value} is not in the
18559 		* �value space� of {base type definition}.
18560 		*
18561 		* minInclusive, maxInclusive, minExclusive, maxExclusive:
18562 		* The value �must� be in the
18563 		* �value space� of the �base type�.
18564 		*/
18565 		/*
18566 		* This function is intended to deliver a compiled value
18567 		* on the facet. In this implementation of XML Schemata the
18568 		* type holding a facet, won't be a built-in type.
18569 		* Thus to ensure that other API
18570 		* calls (relaxng) do work, if the given type is a built-in
18571 		* type, we will assume that the given built-in type *is
18572 		* already* the base type.
18573 		*/
18574 		if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
18575 		    base = typeDecl->baseType;
18576 		    if (base == NULL) {
18577 			PERROR_INT("xmlSchemaCheckFacet",
18578 			    "a type user derived type has no base type");
18579 			return (-1);
18580 		    }
18581 		} else
18582 		    base = typeDecl;
18583 
18584 		if (! ctxtGiven) {
18585 		    /*
18586 		    * A context is needed if called from RelaxNG.
18587 		    */
18588 		    pctxt = xmlSchemaNewParserCtxt("*");
18589 		    if (pctxt == NULL)
18590 			return (-1);
18591 		}
18592 		/*
18593 		* NOTE: This call does not check the content nodes,
18594 		* since they are not available:
18595 		* facet->node is just the node holding the facet
18596 		* definition, *not* the attribute holding the *value*
18597 		* of the facet.
18598 		*/
18599 		ret = xmlSchemaVCheckCVCSimpleType(
18600 		    ACTXT_CAST pctxt, facet->node, base,
18601 		    facet->value, &(facet->val), 1, 1, 0);
18602                 if (ret != 0) {
18603 		    if (ret < 0) {
18604 			/* No error message for RelaxNG. */
18605 			if (ctxtGiven) {
18606 			    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18607 				XML_SCHEMAP_INTERNAL, facet->node, NULL,
18608 				"Internal error: xmlSchemaCheckFacet, "
18609 				"failed to validate the value '%s' of the "
18610 				"facet '%s' against the base type",
18611 				facet->value, xmlSchemaFacetTypeToString(facet->type));
18612 			}
18613 			goto internal_error;
18614 		    }
18615 		    ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18616 		    /* No error message for RelaxNG. */
18617 		    if (ctxtGiven) {
18618 			xmlChar *str = NULL;
18619 
18620 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
18621 			    ret, facet->node, WXS_BASIC_CAST facet,
18622 			    "The value '%s' of the facet does not validate "
18623 			    "against the base type '%s'",
18624 			    facet->value,
18625 			    xmlSchemaFormatQName(&str,
18626 				base->targetNamespace, base->name));
18627 			FREE_AND_NULL(str);
18628 		    }
18629 		    goto exit;
18630                 } else if (facet->val == NULL) {
18631 		    if (ctxtGiven) {
18632 			PERROR_INT("xmlSchemaCheckFacet",
18633 			    "value was not computed");
18634 		    }
18635 		    TODO
18636 		}
18637                 break;
18638             }
18639         case XML_SCHEMA_FACET_PATTERN:
18640             facet->regexp = xmlRegexpCompile(facet->value);
18641             if (facet->regexp == NULL) {
18642 		ret = XML_SCHEMAP_REGEXP_INVALID;
18643 		/* No error message for RelaxNG. */
18644 		if (ctxtGiven) {
18645 		    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18646 			ret, facet->node, WXS_BASIC_CAST typeDecl,
18647 			"The value '%s' of the facet 'pattern' is not a "
18648 			"valid regular expression",
18649 			facet->value, NULL);
18650 		}
18651             }
18652             break;
18653         case XML_SCHEMA_FACET_TOTALDIGITS:
18654         case XML_SCHEMA_FACET_FRACTIONDIGITS:
18655         case XML_SCHEMA_FACET_LENGTH:
18656         case XML_SCHEMA_FACET_MAXLENGTH:
18657         case XML_SCHEMA_FACET_MINLENGTH:
18658 
18659 	    if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
18660 		ret = xmlSchemaValidatePredefinedType(
18661 		    xmlSchemaGetBuiltInType(XML_SCHEMAS_PINTEGER),
18662 		    facet->value, &(facet->val));
18663 	    } else {
18664 		ret = xmlSchemaValidatePredefinedType(
18665 		    xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
18666 		    facet->value, &(facet->val));
18667 	    }
18668 	    if (ret != 0) {
18669 		if (ret < 0) {
18670 		    /* No error message for RelaxNG. */
18671 		    if (ctxtGiven) {
18672 			PERROR_INT("xmlSchemaCheckFacet",
18673 			    "validating facet value");
18674 		    }
18675 		    goto internal_error;
18676 		}
18677 		ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18678 		/* No error message for RelaxNG. */
18679 		if (ctxtGiven) {
18680 		    /* error code */
18681 		    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
18682 			ret, facet->node, WXS_BASIC_CAST typeDecl,
18683 			"The value '%s' of the facet '%s' is not a valid '%s'",
18684 			facet->value,
18685 			xmlSchemaFacetTypeToString(facet->type),
18686 			(facet->type != XML_SCHEMA_FACET_TOTALDIGITS) ?
18687 			    BAD_CAST "nonNegativeInteger" :
18688 			    BAD_CAST "positiveInteger",
18689 			NULL);
18690 		}
18691 	    }
18692 	    break;
18693 
18694         case XML_SCHEMA_FACET_WHITESPACE:{
18695                 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
18696                     facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
18697                 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
18698                     facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
18699                 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
18700                     facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
18701                 } else {
18702 		    ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18703                     /* No error message for RelaxNG. */
18704 		    if (ctxtGiven) {
18705 			/* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
18706 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
18707 			    ret, facet->node, WXS_BASIC_CAST typeDecl,
18708 			    "The value '%s' of the facet 'whitespace' is not "
18709 			    "valid", facet->value, NULL);
18710                     }
18711                 }
18712             }
18713         default:
18714             break;
18715     }
18716 exit:
18717     if ((! ctxtGiven) && (pctxt != NULL))
18718 	xmlSchemaFreeParserCtxt(pctxt);
18719     return (ret);
18720 internal_error:
18721     if ((! ctxtGiven) && (pctxt != NULL))
18722 	xmlSchemaFreeParserCtxt(pctxt);
18723     return (-1);
18724 }
18725 
18726 /**
18727  * xmlSchemaCheckFacetValues:
18728  * @typeDecl:  the schema type definition
18729  * @ctxt:  the schema parser context
18730  *
18731  * Checks the default values types, especially for facets
18732  */
18733 static int
xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,xmlSchemaParserCtxtPtr pctxt)18734 xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
18735 			  xmlSchemaParserCtxtPtr pctxt)
18736 {
18737     int res, olderrs = pctxt->nberrors;
18738     const xmlChar *name = typeDecl->name;
18739     /*
18740     * NOTE: It is intended to use the facets list, instead
18741     * of facetSet.
18742     */
18743     if (typeDecl->facets != NULL) {
18744 	xmlSchemaFacetPtr facet = typeDecl->facets;
18745 
18746 	/*
18747 	* Temporarily assign the "schema" to the validation context
18748 	* of the parser context. This is needed for NOTATION validation.
18749 	*/
18750 	if (pctxt->vctxt == NULL) {
18751 	    if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1)
18752 		return(-1);
18753 	}
18754 	pctxt->vctxt->schema = pctxt->schema;
18755 	while (facet != NULL) {
18756 	    res = xmlSchemaCheckFacet(facet, typeDecl, pctxt, name);
18757 	    HFAILURE
18758 	    facet = facet->next;
18759 	}
18760 	pctxt->vctxt->schema = NULL;
18761     }
18762     if (olderrs != pctxt->nberrors)
18763 	return(pctxt->err);
18764     return(0);
18765 exit_failure:
18766     return(-1);
18767 }
18768 
18769 /**
18770  * xmlSchemaGetCircModelGrDefRef:
18771  * @ctxtMGroup: the searched model group
18772  * @selfMGroup: the second searched model group
18773  * @particle: the first particle
18774  *
18775  * This one is intended to be used by
18776  * xmlSchemaCheckGroupDefCircular only.
18777  *
18778  * Returns the particle with the circular model group definition reference,
18779  * otherwise NULL.
18780  */
18781 static xmlSchemaTreeItemPtr
xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,xmlSchemaTreeItemPtr particle)18782 xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
18783 			      xmlSchemaTreeItemPtr particle)
18784 {
18785     xmlSchemaTreeItemPtr circ = NULL;
18786     xmlSchemaTreeItemPtr term;
18787     xmlSchemaModelGroupDefPtr gdef;
18788 
18789     for (; particle != NULL; particle = particle->next) {
18790 	term = particle->children;
18791 	if (term == NULL)
18792 	    continue;
18793 	switch (term->type) {
18794 	    case XML_SCHEMA_TYPE_GROUP:
18795 		gdef = (xmlSchemaModelGroupDefPtr) term;
18796 		if (gdef == groupDef)
18797 		    return (particle);
18798 		/*
18799 		* Mark this model group definition to avoid infinite
18800 		* recursion on circular references not yet examined.
18801 		*/
18802 		if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
18803 		    continue;
18804 		if (gdef->children != NULL) {
18805 		    gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18806 		    circ = xmlSchemaGetCircModelGrDefRef(groupDef,
18807 			gdef->children->children);
18808 		    gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18809 		    if (circ != NULL)
18810 			return (circ);
18811 		}
18812 		break;
18813 	    case XML_SCHEMA_TYPE_SEQUENCE:
18814 	    case XML_SCHEMA_TYPE_CHOICE:
18815 	    case XML_SCHEMA_TYPE_ALL:
18816 		circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
18817 		if (circ != NULL)
18818 		    return (circ);
18819 		break;
18820 	    default:
18821 		break;
18822 	}
18823     }
18824     return (NULL);
18825 }
18826 
18827 /**
18828  * xmlSchemaCheckGroupDefCircular:
18829  * @item:  the model group definition
18830  * @ctxt:  the parser context
18831  * @name:  the name
18832  *
18833  * Checks for circular references to model group definitions.
18834  */
18835 static void
xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,xmlSchemaParserCtxtPtr ctxt)18836 xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
18837 			       xmlSchemaParserCtxtPtr ctxt)
18838 {
18839     /*
18840     * Schema Component Constraint: Model Group Correct
18841     * 2 Circular groups are disallowed. That is, within the {particles}
18842     * of a group there must not be at any depth a particle whose {term}
18843     * is the group itself.
18844     */
18845     if ((item == NULL) ||
18846 	(item->type != XML_SCHEMA_TYPE_GROUP) ||
18847 	(item->children == NULL))
18848 	return;
18849     {
18850 	xmlSchemaTreeItemPtr circ;
18851 
18852 	circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
18853 	if (circ != NULL) {
18854 	    xmlChar *str = NULL;
18855 	    /*
18856 	    * TODO: The error report is not adequate: this constraint
18857 	    * is defined for model groups but not definitions, but since
18858 	    * there cannot be any circular model groups without a model group
18859 	    * definition (if not using a construction API), we check those
18860 	    * defintions only.
18861 	    */
18862 	    xmlSchemaPCustomErr(ctxt,
18863 		XML_SCHEMAP_MG_PROPS_CORRECT_2,
18864 		NULL, WXS_ITEM_NODE(circ),
18865 		"Circular reference to the model group definition '%s' "
18866 		"defined", xmlSchemaFormatQName(&str,
18867 		    item->targetNamespace, item->name));
18868 	    FREE_AND_NULL(str)
18869 	    /*
18870 	    * NOTE: We will cut the reference to avoid further
18871 	    * confusion of the processor. This is a fatal error.
18872 	    */
18873 	    circ->children = NULL;
18874 	}
18875     }
18876 }
18877 
18878 /**
18879  * xmlSchemaModelGroupToModelGroupDefFixup:
18880  * @ctxt:  the parser context
18881  * @mg:  the model group
18882  *
18883  * Assigns the model group of model group definitions to the "term"
18884  * of the referencing particle.
18885  * In xmlSchemaResolveModelGroupParticleReferences the model group
18886  * definitions were assigned to the "term", since needed for the
18887  * circularity check.
18888  *
18889  * Schema Component Constraint:
18890  *     All Group Limited (cos-all-limited) (1.2)
18891  */
18892 static void
xmlSchemaModelGroupToModelGroupDefFixup(xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,xmlSchemaModelGroupPtr mg)18893 xmlSchemaModelGroupToModelGroupDefFixup(
18894     xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
18895     xmlSchemaModelGroupPtr mg)
18896 {
18897     xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
18898 
18899     while (particle != NULL) {
18900 	if ((WXS_PARTICLE_TERM(particle) == NULL) ||
18901 	    ((WXS_PARTICLE_TERM(particle))->type !=
18902 		XML_SCHEMA_TYPE_GROUP))
18903 	{
18904 	    particle = WXS_PTC_CAST particle->next;
18905 	    continue;
18906 	}
18907 	if (WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle)) == NULL) {
18908 	    /*
18909 	    * TODO: Remove the particle.
18910 	    */
18911 	    WXS_PARTICLE_TERM(particle) = NULL;
18912 	    particle = WXS_PTC_CAST particle->next;
18913 	    continue;
18914 	}
18915 	/*
18916 	* Assign the model group to the {term} of the particle.
18917 	*/
18918 	WXS_PARTICLE_TERM(particle) =
18919 	    WXS_TREE_CAST WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle));
18920 
18921 	particle = WXS_PTC_CAST particle->next;
18922     }
18923 }
18924 
18925 /**
18926  * xmlSchemaCheckAttrGroupCircularRecur:
18927  * @ctxtGr: the searched attribute group
18928  * @attr: the current attribute list to be processed
18929  *
18930  * This one is intended to be used by
18931  * xmlSchemaCheckAttrGroupCircular only.
18932  *
18933  * Returns the circular attribute grou reference, otherwise NULL.
18934  */
18935 static xmlSchemaQNameRefPtr
xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,xmlSchemaItemListPtr list)18936 xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,
18937 				     xmlSchemaItemListPtr list)
18938 {
18939     xmlSchemaAttributeGroupPtr gr;
18940     xmlSchemaQNameRefPtr ref, circ;
18941     int i;
18942     /*
18943     * We will search for an attribute group reference which
18944     * references the context attribute group.
18945     */
18946     for (i = 0; i < list->nbItems; i++) {
18947 	ref = list->items[i];
18948 	if ((ref->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
18949 	    (ref->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
18950 	    (ref->item != NULL))
18951 	{
18952 	    gr = WXS_ATTR_GROUP_CAST ref->item;
18953 	    if (gr == ctxtGr)
18954 		return(ref);
18955 	    if (gr->flags & XML_SCHEMAS_ATTRGROUP_MARKED)
18956 		continue;
18957 	    /*
18958 	    * Mark as visited to avoid infinite recursion on
18959 	    * circular references not yet examined.
18960 	    */
18961 	    if ((gr->attrUses) &&
18962 		(gr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS))
18963 	    {
18964 		gr->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
18965 		circ = xmlSchemaCheckAttrGroupCircularRecur(ctxtGr,
18966 		    (xmlSchemaItemListPtr) gr->attrUses);
18967 		gr->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
18968 		if (circ != NULL)
18969 		    return (circ);
18970 	    }
18971 
18972 	}
18973     }
18974     return (NULL);
18975 }
18976 
18977 /**
18978  * xmlSchemaCheckAttrGroupCircular:
18979  * attrGr:  the attribute group definition
18980  * @ctxt:  the parser context
18981  * @name:  the name
18982  *
18983  * Checks for circular references of attribute groups.
18984  */
18985 static int
xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,xmlSchemaParserCtxtPtr ctxt)18986 xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
18987 				xmlSchemaParserCtxtPtr ctxt)
18988 {
18989     /*
18990     * Schema Representation Constraint:
18991     * Attribute Group Definition Representation OK
18992     * 3 Circular group reference is disallowed outside <redefine>.
18993     * That is, unless this element information item's parent is
18994     * <redefine>, then among the [children], if any, there must
18995     * not be an <attributeGroup> with ref [attribute] which resolves
18996     * to the component corresponding to this <attributeGroup>. Indirect
18997     * circularity is also ruled out. That is, when QName resolution
18998     * (Schema Document) (�3.15.3) is applied to a �QName� arising from
18999     * any <attributeGroup>s with a ref [attribute] among the [children],
19000     * it must not be the case that a �QName� is encountered at any depth
19001     * which resolves to the component corresponding to this <attributeGroup>.
19002     */
19003     if (attrGr->attrUses == NULL)
19004 	return(0);
19005     else if ((attrGr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS) == 0)
19006 	return(0);
19007     else {
19008 	xmlSchemaQNameRefPtr circ;
19009 
19010 	circ = xmlSchemaCheckAttrGroupCircularRecur(attrGr,
19011 	    (xmlSchemaItemListPtr) attrGr->attrUses);
19012 	if (circ != NULL) {
19013 	    xmlChar *str = NULL;
19014 	    /*
19015 	    * TODO: Report the referenced attr group as QName.
19016 	    */
19017 	    xmlSchemaPCustomErr(ctxt,
19018 		XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
19019 		NULL, WXS_ITEM_NODE(WXS_BASIC_CAST circ),
19020 		"Circular reference to the attribute group '%s' "
19021 		"defined", xmlSchemaGetComponentQName(&str, attrGr));
19022 	    FREE_AND_NULL(str);
19023 	    /*
19024 	    * NOTE: We will cut the reference to avoid further
19025 	    * confusion of the processor.
19026 	    * BADSPEC TODO: The spec should define how to process in this case.
19027 	    */
19028 	    circ->item = NULL;
19029 	    return(ctxt->err);
19030 	}
19031     }
19032     return(0);
19033 }
19034 
19035 static int
19036 xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19037 				  xmlSchemaAttributeGroupPtr attrGr);
19038 
19039 /**
19040  * xmlSchemaExpandAttributeGroupRefs:
19041  * @pctxt: the parser context
19042  * @node: the node of the component holding the attribute uses
19043  * @completeWild: the intersected wildcard to be returned
19044  * @list: the attribute uses
19045  *
19046  * Substitutes contained attribute group references
19047  * for their attribute uses. Wilcards are intersected.
19048  * Attribute use prohibitions are removed from the list
19049  * and returned via the @prohibs list.
19050  * Pointlessness of attr. prohibs, if a matching attr. decl
19051  * is existent a well, are checked.
19052  */
19053 static int
xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBasicItemPtr item,xmlSchemaWildcardPtr * completeWild,xmlSchemaItemListPtr list,xmlSchemaItemListPtr prohibs)19054 xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
19055 				  xmlSchemaBasicItemPtr item,
19056 				  xmlSchemaWildcardPtr *completeWild,
19057 				  xmlSchemaItemListPtr list,
19058 				  xmlSchemaItemListPtr prohibs)
19059 {
19060     xmlSchemaAttributeGroupPtr gr;
19061     xmlSchemaAttributeUsePtr use;
19062     xmlSchemaItemListPtr sublist;
19063     int i, j;
19064     int created = (*completeWild == NULL) ? 0 : 1;
19065 
19066     if (prohibs)
19067 	prohibs->nbItems = 0;
19068 
19069     for (i = 0; i < list->nbItems; i++) {
19070 	use = list->items[i];
19071 
19072 	if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
19073 	    if (prohibs == NULL) {
19074 		PERROR_INT("xmlSchemaExpandAttributeGroupRefs",
19075 		    "unexpected attr prohibition found");
19076 		return(-1);
19077 	    }
19078 	    /*
19079 	    * Remove from attribute uses.
19080 	    */
19081 	    if (xmlSchemaItemListRemove(list, i) == -1)
19082 		return(-1);
19083 	    i--;
19084 	    /*
19085 	    * Note that duplicate prohibitions were already
19086 	    * handled at parsing time.
19087 	    */
19088 	    /*
19089 	    * Add to list of prohibitions.
19090 	    */
19091 	    xmlSchemaItemListAddSize(prohibs, 2, use);
19092 	    continue;
19093 	}
19094 	if ((use->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19095 	    ((WXS_QNAME_CAST use)->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP))
19096 	{
19097 	    if ((WXS_QNAME_CAST use)->item == NULL)
19098 		return(-1);
19099 	    gr = WXS_ATTR_GROUP_CAST (WXS_QNAME_CAST use)->item;
19100 	    /*
19101 	    * Expand the referenced attr. group.
19102 	    * TODO: remove this, this is done in a previous step, so
19103 	    * already done here.
19104 	    */
19105 	    if ((gr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
19106 		if (xmlSchemaAttributeGroupExpandRefs(pctxt, gr) == -1)
19107 		    return(-1);
19108 	    }
19109 	    /*
19110 	    * Build the 'complete' wildcard; i.e. intersect multiple
19111 	    * wildcards.
19112 	    */
19113 	    if (gr->attributeWildcard != NULL) {
19114 		if (*completeWild == NULL) {
19115 		    *completeWild = gr->attributeWildcard;
19116 		} else {
19117 		    if (! created) {
19118 			xmlSchemaWildcardPtr tmpWild;
19119 
19120 			 /*
19121 			* Copy the first encountered wildcard as context,
19122 			* except for the annotation.
19123 			*
19124 			* Although the complete wildcard might not correspond
19125 			* to any node in the schema, we will anchor it on
19126 			* the node of the owner component.
19127 			*/
19128 			tmpWild =  xmlSchemaAddWildcard(pctxt, pctxt->schema,
19129 			    XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
19130 			    WXS_ITEM_NODE(item));
19131 			if (tmpWild == NULL)
19132 			    return(-1);
19133 			if (xmlSchemaCloneWildcardNsConstraints(pctxt,
19134 			    tmpWild, *completeWild) == -1)
19135 			    return (-1);
19136 			tmpWild->processContents = (*completeWild)->processContents;
19137 			*completeWild = tmpWild;
19138 			created = 1;
19139 		    }
19140 
19141 		    if (xmlSchemaIntersectWildcards(pctxt, *completeWild,
19142 			gr->attributeWildcard) == -1)
19143 			return(-1);
19144 		}
19145 	    }
19146 	    /*
19147 	    * Just remove the reference if the referenced group does not
19148 	    * contain any attribute uses.
19149 	    */
19150 	    sublist = ((xmlSchemaItemListPtr) gr->attrUses);
19151 	    if ((sublist == NULL) || sublist->nbItems == 0) {
19152 		if (xmlSchemaItemListRemove(list, i) == -1)
19153 		    return(-1);
19154 		i--;
19155 		continue;
19156 	    }
19157 	    /*
19158 	    * Add the attribute uses.
19159 	    */
19160 	    list->items[i] = sublist->items[0];
19161 	    if (sublist->nbItems != 1) {
19162 		for (j = 1; j < sublist->nbItems; j++) {
19163 		    i++;
19164 		    if (xmlSchemaItemListInsert(list,
19165 			    sublist->items[j], i) == -1)
19166 			return(-1);
19167 		}
19168 	    }
19169 	}
19170 
19171     }
19172     /*
19173     * Handle pointless prohibitions of declared attributes.
19174     */
19175     if (prohibs && (prohibs->nbItems != 0) && (list->nbItems != 0)) {
19176 	xmlSchemaAttributeUseProhibPtr prohib;
19177 
19178 	for (i = prohibs->nbItems -1; i >= 0; i--) {
19179 	    prohib = prohibs->items[i];
19180 	    for (j = 0; j < list->nbItems; j++) {
19181 		use = list->items[j];
19182 
19183 		if ((prohib->name == WXS_ATTRUSE_DECL_NAME(use)) &&
19184 		    (prohib->targetNamespace == WXS_ATTRUSE_DECL_TNS(use)))
19185 		{
19186 		    xmlChar *str = NULL;
19187 
19188 		    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
19189 			XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
19190 			prohib->node, NULL,
19191 			"Skipping pointless attribute use prohibition "
19192 			"'%s', since a corresponding attribute use "
19193 			"exists already in the type definition",
19194 			xmlSchemaFormatQName(&str,
19195 			    prohib->targetNamespace, prohib->name),
19196 			NULL, NULL);
19197 		    FREE_AND_NULL(str);
19198 		    /*
19199 		    * Remove the prohibition.
19200 		    */
19201 		    if (xmlSchemaItemListRemove(prohibs, i) == -1)
19202 			return(-1);
19203 		    break;
19204 		}
19205 	    }
19206 	}
19207     }
19208     return(0);
19209 }
19210 
19211 /**
19212  * xmlSchemaAttributeGroupExpandRefs:
19213  * @pctxt:  the parser context
19214  * @attrGr:  the attribute group definition
19215  *
19216  * Computation of:
19217  * {attribute uses} property
19218  * {attribute wildcard} property
19219  *
19220  * Substitutes contained attribute group references
19221  * for their attribute uses. Wilcards are intersected.
19222  */
19223 static int
xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,xmlSchemaAttributeGroupPtr attrGr)19224 xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19225 				  xmlSchemaAttributeGroupPtr attrGr)
19226 {
19227     if ((attrGr->attrUses == NULL) ||
19228 	(attrGr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED))
19229 	return(0);
19230 
19231     attrGr->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
19232     if (xmlSchemaExpandAttributeGroupRefs(pctxt, WXS_BASIC_CAST attrGr,
19233 	&(attrGr->attributeWildcard), attrGr->attrUses, NULL) == -1)
19234 	return(-1);
19235     return(0);
19236 }
19237 
19238 /**
19239  * xmlSchemaAttributeGroupExpandRefs:
19240  * @pctxt:  the parser context
19241  * @attrGr:  the attribute group definition
19242  *
19243  * Substitutes contained attribute group references
19244  * for their attribute uses. Wilcards are intersected.
19245  *
19246  * Schema Component Constraint:
19247  *    Attribute Group Definition Properties Correct (ag-props-correct)
19248  */
19249 static int
xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,xmlSchemaAttributeGroupPtr attrGr)19250 xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19251 				  xmlSchemaAttributeGroupPtr attrGr)
19252 {
19253     /*
19254     * SPEC ag-props-correct
19255     * (1) "The values of the properties of an attribute group definition
19256     * must be as described in the property tableau in The Attribute
19257     * Group Definition Schema Component (�3.6.1), modulo the impact of
19258     * Missing Sub-components (�5.3);"
19259     */
19260 
19261     if ((attrGr->attrUses != NULL) &&
19262 	(WXS_LIST_CAST attrGr->attrUses)->nbItems > 1)
19263     {
19264 	xmlSchemaItemListPtr uses = WXS_LIST_CAST attrGr->attrUses;
19265 	xmlSchemaAttributeUsePtr use, tmp;
19266 	int i, j, hasId = 0;
19267 
19268 	for (i = uses->nbItems -1; i >= 0; i--) {
19269 	    use = uses->items[i];
19270 	    /*
19271 	    * SPEC ag-props-correct
19272 	    * (2) "Two distinct members of the {attribute uses} must not have
19273 	    * {attribute declaration}s both of whose {name}s match and whose
19274 	    * {target namespace}s are identical."
19275 	    */
19276 	    if (i > 0) {
19277 		for (j = i -1; j >= 0; j--) {
19278 		    tmp = uses->items[j];
19279 		    if ((WXS_ATTRUSE_DECL_NAME(use) ==
19280 			WXS_ATTRUSE_DECL_NAME(tmp)) &&
19281 			(WXS_ATTRUSE_DECL_TNS(use) ==
19282 			WXS_ATTRUSE_DECL_TNS(tmp)))
19283 		    {
19284 			xmlChar *str = NULL;
19285 
19286 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
19287 			    XML_SCHEMAP_AG_PROPS_CORRECT,
19288 			    attrGr->node, WXS_BASIC_CAST attrGr,
19289 			    "Duplicate %s",
19290 			    xmlSchemaGetComponentDesignation(&str, use),
19291 			    NULL);
19292 			FREE_AND_NULL(str);
19293 			/*
19294 			* Remove the duplicate.
19295 			*/
19296 			if (xmlSchemaItemListRemove(uses, i) == -1)
19297 			    return(-1);
19298 			goto next_use;
19299 		    }
19300 		}
19301 	    }
19302 	    /*
19303 	    * SPEC ag-props-correct
19304 	    * (3) "Two distinct members of the {attribute uses} must not have
19305 	    * {attribute declaration}s both of whose {type definition}s are or
19306 	    * are derived from ID."
19307 	    * TODO: Does 'derived' include member-types of unions?
19308 	    */
19309 	    if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
19310 		if (xmlSchemaIsDerivedFromBuiltInType(
19311 		    WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
19312 		{
19313 		    if (hasId) {
19314 			xmlChar *str = NULL;
19315 
19316 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
19317 			    XML_SCHEMAP_AG_PROPS_CORRECT,
19318 			    attrGr->node, WXS_BASIC_CAST attrGr,
19319 			    "There must not exist more than one attribute "
19320 			    "declaration of type 'xs:ID' "
19321 			    "(or derived from 'xs:ID'). The %s violates this "
19322 			    "constraint",
19323 			    xmlSchemaGetComponentDesignation(&str, use),
19324 			    NULL);
19325 			FREE_AND_NULL(str);
19326 			if (xmlSchemaItemListRemove(uses, i) == -1)
19327 			    return(-1);
19328 		    }
19329 		    hasId = 1;
19330 		}
19331 	    }
19332 next_use: {}
19333 	}
19334     }
19335     return(0);
19336 }
19337 
19338 /**
19339  * xmlSchemaResolveAttrGroupReferences:
19340  * @attrgrpDecl:  the schema attribute definition
19341  * @ctxt:  the schema parser context
19342  * @name:  the attribute name
19343  *
19344  * Resolves references to attribute group definitions.
19345  */
19346 static int
xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,xmlSchemaParserCtxtPtr ctxt)19347 xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,
19348 				    xmlSchemaParserCtxtPtr ctxt)
19349 {
19350     xmlSchemaAttributeGroupPtr group;
19351 
19352     if (ref->item != NULL)
19353         return(0);
19354     group = xmlSchemaGetAttributeGroup(ctxt->schema,
19355 	ref->name,
19356 	ref->targetNamespace);
19357     if (group == NULL) {
19358 	xmlSchemaPResCompAttrErr(ctxt,
19359 	    XML_SCHEMAP_SRC_RESOLVE,
19360 	    NULL, ref->node,
19361 	    "ref", ref->name, ref->targetNamespace,
19362 	    ref->itemType, NULL);
19363 	return(ctxt->err);
19364     }
19365     ref->item = WXS_BASIC_CAST group;
19366     return(0);
19367 }
19368 
19369 /**
19370  * xmlSchemaCheckAttrPropsCorrect:
19371  * @item:  an schema attribute declaration/use
19372  * @ctxt:  a schema parser context
19373  * @name:  the name of the attribute
19374  *
19375  *
19376  * Schema Component Constraint:
19377  *    Attribute Declaration Properties Correct (a-props-correct)
19378  *
19379  * Validates the value constraints of an attribute declaration/use.
19380  * NOTE that this needs the simle type definitions to be already
19381  *   builded and checked.
19382  */
19383 static int
xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,xmlSchemaAttributePtr attr)19384 xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19385 			       xmlSchemaAttributePtr attr)
19386 {
19387 
19388     /*
19389     * SPEC a-props-correct (1)
19390     * "The values of the properties of an attribute declaration must
19391     * be as described in the property tableau in The Attribute
19392     * Declaration Schema Component (�3.2.1), modulo the impact of
19393     * Missing Sub-components (�5.3)."
19394     */
19395 
19396     if (WXS_ATTR_TYPEDEF(attr) == NULL)
19397 	return(0);
19398 
19399     if (attr->defValue != NULL) {
19400 	int ret;
19401 
19402 	/*
19403 	* SPEC a-props-correct (3)
19404 	* "If the {type definition} is or is derived from ID then there
19405 	* must not be a {value constraint}."
19406 	*/
19407 	if (xmlSchemaIsDerivedFromBuiltInType(
19408 	    WXS_ATTR_TYPEDEF(attr), XML_SCHEMAS_ID))
19409 	{
19410 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
19411 		XML_SCHEMAP_A_PROPS_CORRECT_3,
19412 		NULL, WXS_BASIC_CAST attr,
19413 		"Value constraints are not allowed if the type definition "
19414 		"is or is derived from xs:ID",
19415 		NULL, NULL);
19416 	    return(pctxt->err);
19417 	}
19418 	/*
19419 	* SPEC a-props-correct (2)
19420 	* "if there is a {value constraint}, the canonical lexical
19421 	* representation of its value must be �valid� with respect
19422 	* to the {type definition} as defined in String Valid (�3.14.4)."
19423 	* TODO: Don't care about the *cononical* stuff here, this requirement
19424 	* will be removed in WXS 1.1 anyway.
19425 	*/
19426 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt,
19427 	    attr->node, WXS_ATTR_TYPEDEF(attr),
19428 	    attr->defValue, &(attr->defVal),
19429 	    1, 1, 0);
19430 	if (ret != 0) {
19431 	    if (ret < 0) {
19432 		PERROR_INT("xmlSchemaCheckAttrPropsCorrect",
19433 		    "calling xmlSchemaVCheckCVCSimpleType()");
19434 		return(-1);
19435 	    }
19436 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
19437 		XML_SCHEMAP_A_PROPS_CORRECT_2,
19438 		NULL, WXS_BASIC_CAST attr,
19439 		"The value of the value constraint is not valid",
19440 		NULL, NULL);
19441 	    return(pctxt->err);
19442 	}
19443     }
19444 
19445     return(0);
19446 }
19447 
19448 static xmlSchemaElementPtr
xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,xmlSchemaElementPtr ancestor)19449 xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
19450 				 xmlSchemaElementPtr ancestor)
19451 {
19452     xmlSchemaElementPtr ret;
19453 
19454     if (WXS_SUBST_HEAD(ancestor) == NULL)
19455 	return (NULL);
19456     if (WXS_SUBST_HEAD(ancestor) == elemDecl)
19457 	return (ancestor);
19458 
19459     if (WXS_SUBST_HEAD(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
19460 	return (NULL);
19461     WXS_SUBST_HEAD(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
19462     ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
19463 	WXS_SUBST_HEAD(ancestor));
19464     WXS_SUBST_HEAD(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
19465 
19466     return (ret);
19467 }
19468 
19469 /**
19470  * xmlSchemaCheckElemPropsCorrect:
19471  * @ctxt:  a schema parser context
19472  * @decl: the element declaration
19473  * @name:  the name of the attribute
19474  *
19475  * Schema Component Constraint:
19476  * Element Declaration Properties Correct (e-props-correct)
19477  *
19478  * STATUS:
19479  *   missing: (6)
19480  */
19481 static int
xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,xmlSchemaElementPtr elemDecl)19482 xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19483 			       xmlSchemaElementPtr elemDecl)
19484 {
19485     int ret = 0;
19486     xmlSchemaTypePtr typeDef = WXS_ELEM_TYPEDEF(elemDecl);
19487     /*
19488     * SPEC (1) "The values of the properties of an element declaration
19489     * must be as described in the property tableau in The Element
19490     * Declaration Schema Component (�3.3.1), modulo the impact of Missing
19491     * Sub-components (�5.3)."
19492     */
19493     if (WXS_SUBST_HEAD(elemDecl) != NULL) {
19494 	xmlSchemaElementPtr head = WXS_SUBST_HEAD(elemDecl), circ;
19495 
19496 	xmlSchemaCheckElementDeclComponent(head, pctxt);
19497 	/*
19498 	* SPEC (3) "If there is a non-�absent� {substitution group
19499 	* affiliation}, then {scope} must be global."
19500 	*/
19501 	if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
19502 	    xmlSchemaPCustomErr(pctxt,
19503 		XML_SCHEMAP_E_PROPS_CORRECT_3,
19504 		WXS_BASIC_CAST elemDecl, NULL,
19505 		"Only global element declarations can have a "
19506 		"substitution group affiliation", NULL);
19507 	    ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
19508 	}
19509 	/*
19510 	* TODO: SPEC (6) "Circular substitution groups are disallowed.
19511 	* That is, it must not be possible to return to an element declaration
19512 	* by repeatedly following the {substitution group affiliation}
19513 	* property."
19514 	*/
19515 	if (head == elemDecl)
19516 	    circ = head;
19517 	else if (WXS_SUBST_HEAD(head) != NULL)
19518 	    circ = xmlSchemaCheckSubstGroupCircular(head, head);
19519 	else
19520 	    circ = NULL;
19521 	if (circ != NULL) {
19522 	    xmlChar *strA = NULL, *strB = NULL;
19523 
19524 	    xmlSchemaPCustomErrExt(pctxt,
19525 		XML_SCHEMAP_E_PROPS_CORRECT_6,
19526 		WXS_BASIC_CAST circ, NULL,
19527 		"The element declaration '%s' defines a circular "
19528 		"substitution group to element declaration '%s'",
19529 		xmlSchemaGetComponentQName(&strA, circ),
19530 		xmlSchemaGetComponentQName(&strB, head),
19531 		NULL);
19532 	    FREE_AND_NULL(strA)
19533 	    FREE_AND_NULL(strB)
19534 	    ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
19535 	}
19536 	/*
19537 	* SPEC (4) "If there is a {substitution group affiliation},
19538 	* the {type definition}
19539 	* of the element declaration must be validly derived from the {type
19540 	* definition} of the {substitution group affiliation}, given the value
19541 	* of the {substitution group exclusions} of the {substitution group
19542 	* affiliation}, as defined in Type Derivation OK (Complex) (�3.4.6)
19543 	* (if the {type definition} is complex) or as defined in
19544 	* Type Derivation OK (Simple) (�3.14.6) (if the {type definition} is
19545 	* simple)."
19546 	*
19547 	* NOTE: {substitution group exclusions} means the values of the
19548 	* attribute "final".
19549 	*/
19550 
19551 	if (typeDef != WXS_ELEM_TYPEDEF(WXS_SUBST_HEAD(elemDecl))) {
19552 	    int set = 0;
19553 
19554 	    if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
19555 		set |= SUBSET_EXTENSION;
19556 	    if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
19557 		set |= SUBSET_RESTRICTION;
19558 
19559 	    if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST pctxt, typeDef,
19560 		WXS_ELEM_TYPEDEF(head), set) != 0) {
19561 		xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
19562 
19563 		ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
19564 		xmlSchemaPCustomErrExt(pctxt,
19565 		    XML_SCHEMAP_E_PROPS_CORRECT_4,
19566 		    WXS_BASIC_CAST elemDecl, NULL,
19567 		    "The type definition '%s' was "
19568 		    "either rejected by the substitution group "
19569 		    "affiliation '%s', or not validly derived from its type "
19570 		    "definition '%s'",
19571 		    xmlSchemaGetComponentQName(&strA, typeDef),
19572 		    xmlSchemaGetComponentQName(&strB, head),
19573 		    xmlSchemaGetComponentQName(&strC, WXS_ELEM_TYPEDEF(head)));
19574 		FREE_AND_NULL(strA)
19575 		FREE_AND_NULL(strB)
19576 		FREE_AND_NULL(strC)
19577 	    }
19578 	}
19579     }
19580     /*
19581     * SPEC (5) "If the {type definition} or {type definition}'s
19582     * {content type}
19583     * is or is derived from ID then there must not be a {value constraint}.
19584     * Note: The use of ID as a type definition for elements goes beyond
19585     * XML 1.0, and should be avoided if backwards compatibility is desired"
19586     */
19587     if ((elemDecl->value != NULL) &&
19588 	((WXS_IS_SIMPLE(typeDef) &&
19589 	  xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
19590 	 (WXS_IS_COMPLEX(typeDef) &&
19591 	  WXS_HAS_SIMPLE_CONTENT(typeDef) &&
19592 	  xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
19593 	    XML_SCHEMAS_ID)))) {
19594 
19595 	ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
19596 	xmlSchemaPCustomErr(pctxt,
19597 	    XML_SCHEMAP_E_PROPS_CORRECT_5,
19598 	    WXS_BASIC_CAST elemDecl, NULL,
19599 	    "The type definition (or type definition's content type) is or "
19600 	    "is derived from ID; value constraints are not allowed in "
19601 	    "conjunction with such a type definition", NULL);
19602     } else if (elemDecl->value != NULL) {
19603 	int vcret;
19604 	xmlNodePtr node = NULL;
19605 
19606 	/*
19607 	* SPEC (2) "If there is a {value constraint}, the canonical lexical
19608 	* representation of its value must be �valid� with respect to the
19609 	* {type definition} as defined in Element Default Valid (Immediate)
19610 	* (�3.3.6)."
19611 	*/
19612 	if (typeDef == NULL) {
19613 	    xmlSchemaPErr(pctxt, elemDecl->node,
19614 		XML_SCHEMAP_INTERNAL,
19615 		"Internal error: xmlSchemaCheckElemPropsCorrect, "
19616 		"type is missing... skipping validation of "
19617 		"the value constraint", NULL, NULL);
19618 	    return (-1);
19619 	}
19620 	if (elemDecl->node != NULL) {
19621 	    if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
19622 		node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19623 		    BAD_CAST "fixed");
19624 	    else
19625 		node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19626 		    BAD_CAST "default");
19627 	}
19628 	vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
19629 	    typeDef, elemDecl->value, &(elemDecl->defVal));
19630 	if (vcret != 0) {
19631 	    if (vcret < 0) {
19632 		PERROR_INT("xmlSchemaElemCheckValConstr",
19633 		    "failed to validate the value constraint of an "
19634 		    "element declaration");
19635 		return (-1);
19636 	    }
19637 	    return (vcret);
19638 	}
19639     }
19640 
19641     return (ret);
19642 }
19643 
19644 /**
19645  * xmlSchemaCheckElemSubstGroup:
19646  * @ctxt:  a schema parser context
19647  * @decl: the element declaration
19648  * @name:  the name of the attribute
19649  *
19650  * Schema Component Constraint:
19651  * Substitution Group (cos-equiv-class)
19652  *
19653  * In Libxml2 the subst. groups will be precomputed, in terms of that
19654  * a list will be built for each subst. group head, holding all direct
19655  * referents to this head.
19656  * NOTE that this function needs:
19657  *   1. circular subst. groups to be checked beforehand
19658  *   2. the declaration's type to be derived from the head's type
19659  *
19660  * STATUS:
19661  *
19662  */
19663 static void
xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,xmlSchemaElementPtr elemDecl)19664 xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
19665 			     xmlSchemaElementPtr elemDecl)
19666 {
19667     if ((WXS_SUBST_HEAD(elemDecl) == NULL) ||
19668 	/* SPEC (1) "Its {abstract} is false." */
19669 	(elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
19670 	return;
19671     {
19672 	xmlSchemaElementPtr head;
19673 	xmlSchemaTypePtr headType, type;
19674 	int set, methSet;
19675 	/*
19676 	* SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
19677 	* {disallowed substitutions} as the blocking constraint, as defined in
19678 	* Substitution Group OK (Transitive) (�3.3.6)."
19679 	*/
19680 	for (head = WXS_SUBST_HEAD(elemDecl); head != NULL;
19681 	    head = WXS_SUBST_HEAD(head)) {
19682 	    set = 0;
19683 	    methSet = 0;
19684 	    /*
19685 	    * The blocking constraints.
19686 	    */
19687 	    if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
19688 		continue;
19689 	    headType = head->subtypes;
19690 	    type = elemDecl->subtypes;
19691 	    if (headType == type)
19692 		goto add_member;
19693 	    if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
19694 		set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19695 	    if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
19696 		set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19697 	    /*
19698 	    * SPEC: Substitution Group OK (Transitive) (2.3)
19699 	    * "The set of all {derivation method}s involved in the
19700 	    * derivation of D's {type definition} from C's {type definition}
19701 	    * does not intersect with the union of the blocking constraint,
19702 	    * C's {prohibited substitutions} (if C is complex, otherwise the
19703 	    * empty set) and the {prohibited substitutions} (respectively the
19704 	    * empty set) of any intermediate {type definition}s in the
19705 	    * derivation of D's {type definition} from C's {type definition}."
19706 	    */
19707 	    /*
19708 	    * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
19709 	    * subst.head axis, the methSet does not need to be computed for
19710 	    * the full depth over and over.
19711 	    */
19712 	    /*
19713 	    * The set of all {derivation method}s involved in the derivation
19714 	    */
19715 	    while ((type != NULL) && (type != headType)) {
19716 		if ((WXS_IS_EXTENSION(type)) &&
19717 		    ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19718 		    methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19719 
19720 		if (WXS_IS_RESTRICTION(type) &&
19721 		    ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19722 		    methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19723 
19724 		type = type->baseType;
19725 	    }
19726 	    /*
19727 	    * The {prohibited substitutions} of all intermediate types +
19728 	    * the head's type.
19729 	    */
19730 	    type = elemDecl->subtypes->baseType;
19731 	    while (type != NULL) {
19732 		if (WXS_IS_COMPLEX(type)) {
19733 		    if ((type->flags &
19734 			    XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19735 			((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
19736 		    set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19737 		    if ((type->flags &
19738 			    XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19739 			((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19740 		    set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19741 		} else
19742 		    break;
19743 		if (type == headType)
19744 		    break;
19745 		type = type->baseType;
19746 	    }
19747 	    if ((set != 0) &&
19748 		(((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19749 		(methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
19750 		((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19751 		(methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
19752 		continue;
19753 	    }
19754 add_member:
19755 	    xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
19756 	    if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
19757 		head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
19758 	}
19759     }
19760 }
19761 
19762 #ifdef WXS_ELEM_DECL_CONS_ENABLED /* enable when finished */
19763 /**
19764  * xmlSchemaCheckElementDeclComponent
19765  * @pctxt: the schema parser context
19766  * @ctxtComponent: the context component (an element declaration)
19767  * @ctxtParticle: the first particle of the context component
19768  * @searchParticle: the element declaration particle to be analysed
19769  *
19770  * Schema Component Constraint: Element Declarations Consistent
19771  */
19772 static int
xmlSchemaCheckElementDeclConsistent(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBasicItemPtr ctxtComponent,xmlSchemaParticlePtr ctxtParticle,xmlSchemaParticlePtr searchParticle,xmlSchemaParticlePtr curParticle,int search)19773 xmlSchemaCheckElementDeclConsistent(xmlSchemaParserCtxtPtr pctxt,
19774 				    xmlSchemaBasicItemPtr ctxtComponent,
19775 				    xmlSchemaParticlePtr ctxtParticle,
19776 				    xmlSchemaParticlePtr searchParticle,
19777 				    xmlSchemaParticlePtr curParticle,
19778 				    int search)
19779 {
19780     return(0);
19781 
19782     int ret = 0;
19783     xmlSchemaParticlePtr cur = curParticle;
19784     if (curParticle == NULL) {
19785 	return(0);
19786     }
19787     if (WXS_PARTICLE_TERM(curParticle) == NULL) {
19788 	/*
19789 	* Just return in this case. A missing "term" of the particle
19790 	* might arise due to an invalid "term" component.
19791 	*/
19792 	return(0);
19793     }
19794     while (cur != NULL) {
19795 	switch (WXS_PARTICLE_TERM(cur)->type) {
19796 	    case XML_SCHEMA_TYPE_ANY:
19797 		break;
19798 	    case XML_SCHEMA_TYPE_ELEMENT:
19799 		if (search == 0) {
19800 		    ret = xmlSchemaCheckElementDeclConsistent(pctxt,
19801 			ctxtComponent, ctxtParticle, cur, ctxtParticle, 1);
19802 		    if (ret != 0)
19803 			return(ret);
19804 		} else {
19805 		    xmlSchemaElementPtr elem =
19806 			WXS_ELEM_CAST(WXS_PARTICLE_TERM(cur));
19807 		    /*
19808 		    * SPEC Element Declarations Consistent:
19809 		    * "If the {particles} contains, either directly,
19810 		    * indirectly (that is, within the {particles} of a
19811 		    * contained model group, recursively) or �implicitly�
19812 		    * two or more element declaration particles with
19813 		    * the same {name} and {target namespace}, then
19814 		    * all their type definitions must be the same
19815 		    * top-level definition [...]"
19816 		    */
19817 		    if (xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->name,
19818 			    WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->name) &&
19819 			xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
19820 			    WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->targetNamespace))
19821 		    {
19822 			xmlChar *strA = NULL, *strB = NULL;
19823 
19824 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
19825 			    /* TODO: error code */
19826 			    XML_SCHEMAP_COS_NONAMBIG,
19827 			    WXS_ITEM_NODE(cur), NULL,
19828 			    "In the content model of %s, there are multiple "
19829 			    "element declarations for '%s' with different "
19830 			    "type definitions",
19831 			    xmlSchemaGetComponentDesignation(&strA,
19832 				ctxtComponent),
19833 			    xmlSchemaFormatQName(&strB,
19834 				WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
19835 				WXS_PARTICLE_TERM_AS_ELEM(cur)->name));
19836 			FREE_AND_NULL(strA);
19837 			FREE_AND_NULL(strB);
19838 			return(XML_SCHEMAP_COS_NONAMBIG);
19839 		    }
19840 		}
19841 		break;
19842 	    case XML_SCHEMA_TYPE_SEQUENCE: {
19843 		break;
19844 		}
19845 	    case XML_SCHEMA_TYPE_CHOICE:{
19846 		/*
19847 		xmlSchemaTreeItemPtr sub;
19848 
19849 		sub = WXS_PARTICLE_TERM(particle)->children;  (xmlSchemaParticlePtr)
19850 		while (sub != NULL) {
19851 		    ret = xmlSchemaCheckElementDeclConsistent(pctxt, ctxtComponent,
19852 			ctxtParticle, ctxtElem);
19853 		    if (ret != 0)
19854 			return(ret);
19855 		    sub = sub->next;
19856 		}
19857 		*/
19858 		break;
19859 		}
19860 	    case XML_SCHEMA_TYPE_ALL:
19861 		break;
19862 	    case XML_SCHEMA_TYPE_GROUP:
19863 		break;
19864 	    default:
19865 		xmlSchemaInternalErr2(ACTXT_CAST pctxt,
19866 		    "xmlSchemaCheckElementDeclConsistent",
19867 		    "found unexpected term of type '%s' in content model",
19868 		    WXS_ITEM_TYPE_NAME(WXS_PARTICLE_TERM(cur)), NULL);
19869 		return(-1);
19870 	}
19871 	cur = (xmlSchemaParticlePtr) cur->next;
19872     }
19873 
19874 exit:
19875     return(ret);
19876 }
19877 #endif
19878 
19879 /**
19880  * xmlSchemaCheckElementDeclComponent
19881  * @item:  an schema element declaration/particle
19882  * @ctxt:  a schema parser context
19883  * @name:  the name of the attribute
19884  *
19885  * Validates the value constraints of an element declaration.
19886  * Adds substitution group members.
19887  */
19888 static void
xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,xmlSchemaParserCtxtPtr ctxt)19889 xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
19890 				   xmlSchemaParserCtxtPtr ctxt)
19891 {
19892     if (elemDecl == NULL)
19893 	return;
19894     if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
19895 	return;
19896     elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
19897     if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0) {
19898 	/*
19899 	* Adds substitution group members.
19900 	*/
19901 	xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
19902     }
19903 }
19904 
19905 /**
19906  * xmlSchemaResolveModelGroupParticleReferences:
19907  * @particle:  a particle component
19908  * @ctxt:  a parser context
19909  *
19910  * Resolves references of a model group's {particles} to
19911  * model group definitions and to element declarations.
19912  */
19913 static void
xmlSchemaResolveModelGroupParticleReferences(xmlSchemaParserCtxtPtr ctxt,xmlSchemaModelGroupPtr mg)19914 xmlSchemaResolveModelGroupParticleReferences(
19915     xmlSchemaParserCtxtPtr ctxt,
19916     xmlSchemaModelGroupPtr mg)
19917 {
19918     xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
19919     xmlSchemaQNameRefPtr ref;
19920     xmlSchemaBasicItemPtr refItem;
19921 
19922     /*
19923     * URGENT TODO: Test this.
19924     */
19925     while (particle != NULL) {
19926 	if ((WXS_PARTICLE_TERM(particle) == NULL) ||
19927 	    ((WXS_PARTICLE_TERM(particle))->type !=
19928 		XML_SCHEMA_EXTRA_QNAMEREF))
19929 	{
19930 	    goto next_particle;
19931 	}
19932 	ref = WXS_QNAME_CAST WXS_PARTICLE_TERM(particle);
19933 	/*
19934 	* Resolve the reference.
19935 	* NULL the {term} by default.
19936 	*/
19937 	particle->children = NULL;
19938 
19939 	refItem = xmlSchemaGetNamedComponent(ctxt->schema,
19940 	    ref->itemType, ref->name, ref->targetNamespace);
19941 	if (refItem == NULL) {
19942 	    xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
19943 		NULL, WXS_ITEM_NODE(particle), "ref", ref->name,
19944 		ref->targetNamespace, ref->itemType, NULL);
19945 	    /* TODO: remove the particle. */
19946 	    goto next_particle;
19947 	}
19948 	if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
19949 	    if (WXS_MODELGROUPDEF_MODEL(refItem) == NULL)
19950 		/* TODO: remove the particle. */
19951 		goto next_particle;
19952 	    /*
19953 	    * NOTE that we will assign the model group definition
19954 	    * itself to the "term" of the particle. This will ease
19955 	    * the check for circular model group definitions. After
19956 	    * that the "term" will be assigned the model group of the
19957 	    * model group definition.
19958 	    */
19959 	    if ((WXS_MODELGROUPDEF_MODEL(refItem))->type ==
19960 		    XML_SCHEMA_TYPE_ALL) {
19961 		/*
19962 		* SPEC cos-all-limited (1)
19963 		* SPEC cos-all-limited (1.2)
19964 		* "It appears only as the value of one or both of the
19965 		* following properties:"
19966 		* (1.1) "the {model group} property of a model group
19967 		*        definition."
19968 		* (1.2) "the {term} property of a particle [... of] the "
19969 		* {content type} of a complex type definition."
19970 		*/
19971 		xmlSchemaCustomErr(ACTXT_CAST ctxt,
19972 		    /* TODO: error code */
19973 		    XML_SCHEMAP_COS_ALL_LIMITED,
19974 		    WXS_ITEM_NODE(particle), NULL,
19975 		    "A model group definition is referenced, but "
19976 		    "it contains an 'all' model group, which "
19977 		    "cannot be contained by model groups",
19978 		    NULL, NULL);
19979 		/* TODO: remove the particle. */
19980 		goto next_particle;
19981 	    }
19982 	    particle->children = (xmlSchemaTreeItemPtr) refItem;
19983 	} else {
19984 	    /*
19985 	    * TODO: Are referenced element declarations the only
19986 	    * other components we expect here?
19987 	    */
19988 	    particle->children = (xmlSchemaTreeItemPtr) refItem;
19989 	}
19990 next_particle:
19991 	particle = WXS_PTC_CAST particle->next;
19992     }
19993 }
19994 
19995 static int
xmlSchemaAreValuesEqual(xmlSchemaValPtr x,xmlSchemaValPtr y)19996 xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
19997 		       xmlSchemaValPtr y)
19998 {
19999     xmlSchemaTypePtr tx, ty, ptx, pty;
20000     int ret;
20001 
20002     while (x != NULL) {
20003 	/* Same types. */
20004 	tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
20005 	ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
20006 	ptx = xmlSchemaGetPrimitiveType(tx);
20007 	pty = xmlSchemaGetPrimitiveType(ty);
20008 	/*
20009 	* (1) if a datatype T' is �derived� by �restriction� from an
20010 	* atomic datatype T then the �value space� of T' is a subset of
20011 	* the �value space� of T. */
20012 	/*
20013 	* (2) if datatypes T' and T'' are �derived� by �restriction�
20014 	* from a common atomic ancestor T then the �value space�s of T'
20015 	* and T'' may overlap.
20016 	*/
20017 	if (ptx != pty)
20018 	    return(0);
20019 	/*
20020 	* We assume computed values to be normalized, so do a fast
20021 	* string comparison for string based types.
20022 	*/
20023 	if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
20024 	    WXS_IS_ANY_SIMPLE_TYPE(ptx)) {
20025 	    if (! xmlStrEqual(
20026 		xmlSchemaValueGetAsString(x),
20027 		xmlSchemaValueGetAsString(y)))
20028 		return (0);
20029 	} else {
20030 	    ret = xmlSchemaCompareValuesWhtsp(
20031 		x, XML_SCHEMA_WHITESPACE_PRESERVE,
20032 		y, XML_SCHEMA_WHITESPACE_PRESERVE);
20033 	    if (ret == -2)
20034 		return(-1);
20035 	    if (ret != 0)
20036 		return(0);
20037 	}
20038 	/*
20039 	* Lists.
20040 	*/
20041 	x = xmlSchemaValueGetNext(x);
20042 	if (x != NULL) {
20043 	    y = xmlSchemaValueGetNext(y);
20044 	    if (y == NULL)
20045 		return (0);
20046 	} else if (xmlSchemaValueGetNext(y) != NULL)
20047 	    return (0);
20048 	else
20049 	    return (1);
20050     }
20051     return (0);
20052 }
20053 
20054 /**
20055  * xmlSchemaResolveAttrUseReferences:
20056  * @item:  an attribute use
20057  * @ctxt:  a parser context
20058  *
20059  * Resolves the referenced attribute declaration.
20060  */
20061 static int
xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,xmlSchemaParserCtxtPtr ctxt)20062 xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,
20063 				  xmlSchemaParserCtxtPtr ctxt)
20064 {
20065     if ((ctxt == NULL) || (ause == NULL))
20066 	return(-1);
20067     if ((ause->attrDecl == NULL) ||
20068 	(ause->attrDecl->type != XML_SCHEMA_EXTRA_QNAMEREF))
20069 	return(0);
20070 
20071     {
20072 	xmlSchemaQNameRefPtr ref = WXS_QNAME_CAST ause->attrDecl;
20073 
20074 	/*
20075 	* TODO: Evaluate, what errors could occur if the declaration is not
20076 	* found.
20077 	*/
20078 	ause->attrDecl = xmlSchemaGetAttributeDecl(ctxt->schema,
20079 	    ref->name, ref->targetNamespace);
20080         if (ause->attrDecl == NULL) {
20081 	    xmlSchemaPResCompAttrErr(ctxt,
20082 	    	XML_SCHEMAP_SRC_RESOLVE,
20083 		WXS_BASIC_CAST ause, ause->node,
20084 		"ref", ref->name, ref->targetNamespace,
20085 		XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20086             return(ctxt->err);;
20087         }
20088     }
20089     return(0);
20090 }
20091 
20092 /**
20093  * xmlSchemaCheckAttrUsePropsCorrect:
20094  * @ctxt:  a parser context
20095  * @use:  an attribute use
20096  *
20097  * Schema Component Constraint:
20098  * Attribute Use Correct (au-props-correct)
20099  *
20100  */
20101 static int
xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,xmlSchemaAttributeUsePtr use)20102 xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,
20103 			     xmlSchemaAttributeUsePtr use)
20104 {
20105     if ((ctxt == NULL) || (use == NULL))
20106 	return(-1);
20107     if ((use->defValue == NULL) || (WXS_ATTRUSE_DECL(use) == NULL) ||
20108 	((WXS_ATTRUSE_DECL(use))->type != XML_SCHEMA_TYPE_ATTRIBUTE))
20109 	return(0);
20110 
20111     /*
20112     * SPEC au-props-correct (1)
20113     * "The values of the properties of an attribute use must be as
20114     * described in the property tableau in The Attribute Use Schema
20115     * Component (�3.5.1), modulo the impact of Missing
20116     * Sub-components (�5.3)."
20117     */
20118 
20119     if (((WXS_ATTRUSE_DECL(use))->defValue != NULL) &&
20120 	((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMAS_ATTR_FIXED) &&
20121         ((use->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20122     {
20123 	xmlSchemaPCustomErr(ctxt,
20124 	    XML_SCHEMAP_AU_PROPS_CORRECT_2,
20125 	    WXS_BASIC_CAST use, NULL,
20126 	    "The attribute declaration has a 'fixed' value constraint "
20127 	    ", thus the attribute use must also have a 'fixed' value "
20128 	    "constraint",
20129 	    NULL);
20130 	return(ctxt->err);
20131     }
20132     /*
20133     * Compute and check the value constraint's value.
20134     */
20135     if ((use->defVal != NULL) && (WXS_ATTRUSE_TYPEDEF(use) != NULL)) {
20136 	int ret;
20137 	/*
20138 	* TODO: The spec seems to be missing a check of the
20139 	* value constraint of the attribute use. We will do it here.
20140 	*/
20141 	/*
20142 	* SPEC a-props-correct (3)
20143 	*/
20144 	if (xmlSchemaIsDerivedFromBuiltInType(
20145 	    WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
20146 	{
20147 	    xmlSchemaCustomErr(ACTXT_CAST ctxt,
20148 		XML_SCHEMAP_AU_PROPS_CORRECT,
20149 		NULL, WXS_BASIC_CAST use,
20150 		"Value constraints are not allowed if the type definition "
20151 		"is or is derived from xs:ID",
20152 		NULL, NULL);
20153 	    return(ctxt->err);
20154 	}
20155 
20156 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST ctxt,
20157 	    use->node, WXS_ATTRUSE_TYPEDEF(use),
20158 	    use->defValue, &(use->defVal),
20159 	    1, 1, 0);
20160 	if (ret != 0) {
20161 	    if (ret < 0) {
20162 		PERROR_INT2("xmlSchemaCheckAttrUsePropsCorrect",
20163 		    "calling xmlSchemaVCheckCVCSimpleType()");
20164 		return(-1);
20165 	    }
20166 	    xmlSchemaCustomErr(ACTXT_CAST ctxt,
20167 		XML_SCHEMAP_AU_PROPS_CORRECT,
20168 		NULL, WXS_BASIC_CAST use,
20169 		"The value of the value constraint is not valid",
20170 		NULL, NULL);
20171 	    return(ctxt->err);
20172 	}
20173     }
20174     /*
20175     * SPEC au-props-correct (2)
20176     * "If the {attribute declaration} has a fixed
20177     * {value constraint}, then if the attribute use itself has a
20178     * {value constraint}, it must also be fixed and its value must match
20179     * that of the {attribute declaration}'s {value constraint}."
20180     */
20181     if (((WXS_ATTRUSE_DECL(use))->defVal != NULL) &&
20182 	(((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20183     {
20184 	if (! xmlSchemaAreValuesEqual(use->defVal,
20185 		(WXS_ATTRUSE_DECL(use))->defVal))
20186 	{
20187 	    xmlSchemaPCustomErr(ctxt,
20188 		XML_SCHEMAP_AU_PROPS_CORRECT_2,
20189 		WXS_BASIC_CAST use, NULL,
20190 		"The 'fixed' value constraint of the attribute use "
20191 		"must match the attribute declaration's value "
20192 		"constraint '%s'",
20193 		(WXS_ATTRUSE_DECL(use))->defValue);
20194 	}
20195 	return(ctxt->err);
20196     }
20197     return(0);
20198 }
20199 
20200 
20201 
20202 
20203 /**
20204  * xmlSchemaResolveAttrTypeReferences:
20205  * @item:  an attribute declaration
20206  * @ctxt:  a parser context
20207  *
20208  * Resolves the referenced type definition component.
20209  */
20210 static int
xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,xmlSchemaParserCtxtPtr ctxt)20211 xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,
20212 				   xmlSchemaParserCtxtPtr ctxt)
20213 {
20214     /*
20215     * The simple type definition corresponding to the <simpleType> element
20216     * information item in the [children], if present, otherwise the simple
20217     * type definition �resolved� to by the �actual value� of the type
20218     * [attribute], if present, otherwise the �simple ur-type definition�.
20219     */
20220     if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
20221 	return(0);
20222     item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
20223     if (item->subtypes != NULL)
20224         return(0);
20225     if (item->typeName != NULL) {
20226         xmlSchemaTypePtr type;
20227 
20228 	type = xmlSchemaGetType(ctxt->schema, item->typeName,
20229 	    item->typeNs);
20230 	if ((type == NULL) || (! WXS_IS_SIMPLE(type))) {
20231 	    xmlSchemaPResCompAttrErr(ctxt,
20232 		XML_SCHEMAP_SRC_RESOLVE,
20233 		WXS_BASIC_CAST item, item->node,
20234 		"type", item->typeName, item->typeNs,
20235 		XML_SCHEMA_TYPE_SIMPLE, NULL);
20236 	    return(ctxt->err);
20237 	} else
20238 	    item->subtypes = type;
20239 
20240     } else {
20241 	/*
20242 	* The type defaults to the xs:anySimpleType.
20243 	*/
20244 	item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
20245     }
20246     return(0);
20247 }
20248 
20249 /**
20250  * xmlSchemaResolveIDCKeyReferences:
20251  * @idc:  the identity-constraint definition
20252  * @ctxt:  the schema parser context
20253  * @name:  the attribute name
20254  *
20255  * Resolve keyRef references to key/unique IDCs.
20256  * Schema Component Constraint:
20257  *   Identity-constraint Definition Properties Correct (c-props-correct)
20258  */
20259 static int
xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,xmlSchemaParserCtxtPtr pctxt)20260 xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,
20261 			  xmlSchemaParserCtxtPtr pctxt)
20262 {
20263     if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
20264         return(0);
20265     if (idc->ref->name != NULL) {
20266 	idc->ref->item = (xmlSchemaBasicItemPtr)
20267 	    xmlSchemaGetIDC(pctxt->schema, idc->ref->name,
20268 		idc->ref->targetNamespace);
20269         if (idc->ref->item == NULL) {
20270 	    /*
20271 	    * TODO: It is actually not an error to fail to resolve
20272 	    * at this stage. BUT we need to be that strict!
20273 	    */
20274 	    xmlSchemaPResCompAttrErr(pctxt,
20275 		XML_SCHEMAP_SRC_RESOLVE,
20276 		WXS_BASIC_CAST idc, idc->node,
20277 		"refer", idc->ref->name,
20278 		idc->ref->targetNamespace,
20279 		XML_SCHEMA_TYPE_IDC_KEY, NULL);
20280             return(pctxt->err);
20281 	} else if (idc->ref->item->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20282 	    /*
20283 	    * SPEC c-props-correct (1)
20284 	    */
20285 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20286 		XML_SCHEMAP_C_PROPS_CORRECT,
20287 		NULL, WXS_BASIC_CAST idc,
20288 		"The keyref references a keyref",
20289 		NULL, NULL);
20290 	    idc->ref->item = NULL;
20291 	    return(pctxt->err);
20292 	} else {
20293 	    if (idc->nbFields !=
20294 		((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
20295 		xmlChar *str = NULL;
20296 		xmlSchemaIDCPtr refer;
20297 
20298 		refer = (xmlSchemaIDCPtr) idc->ref->item;
20299 		/*
20300 		* SPEC c-props-correct(2)
20301 		* "If the {identity-constraint category} is keyref,
20302 		* the cardinality of the {fields} must equal that of
20303 		* the {fields} of the {referenced key}.
20304 		*/
20305 		xmlSchemaCustomErr(ACTXT_CAST pctxt,
20306 		    XML_SCHEMAP_C_PROPS_CORRECT,
20307 		    NULL, WXS_BASIC_CAST idc,
20308 		    "The cardinality of the keyref differs from the "
20309 		    "cardinality of the referenced key/unique '%s'",
20310 		    xmlSchemaFormatQName(&str, refer->targetNamespace,
20311 			refer->name),
20312 		    NULL);
20313 		FREE_AND_NULL(str)
20314 		return(pctxt->err);
20315 	    }
20316 	}
20317     }
20318     return(0);
20319 }
20320 
20321 static int
xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,xmlSchemaParserCtxtPtr pctxt)20322 xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,
20323 				       xmlSchemaParserCtxtPtr pctxt)
20324 {
20325     if (xmlSchemaGetAttributeDecl(pctxt->schema, prohib->name,
20326 	prohib->targetNamespace) == NULL) {
20327 
20328 	xmlSchemaPResCompAttrErr(pctxt,
20329 	    XML_SCHEMAP_SRC_RESOLVE,
20330 	    NULL, prohib->node,
20331 	    "ref", prohib->name, prohib->targetNamespace,
20332 	    XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20333 	return(XML_SCHEMAP_SRC_RESOLVE);
20334     }
20335     return(0);
20336 }
20337 
20338 #define WXS_REDEFINED_TYPE(c) \
20339 (((xmlSchemaTypePtr) item)->flags & XML_SCHEMAS_TYPE_REDEFINED)
20340 
20341 #define WXS_REDEFINED_MODEL_GROUP_DEF(c) \
20342 (((xmlSchemaModelGroupDefPtr) item)->flags & XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20343 
20344 #define WXS_REDEFINED_ATTR_GROUP(c) \
20345 (((xmlSchemaAttributeGroupPtr) item)->flags & XML_SCHEMAS_ATTRGROUP_REDEFINED)
20346 
20347 static int
xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)20348 xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)
20349 {
20350     int err = 0;
20351     xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20352     xmlSchemaBasicItemPtr prev, item;
20353     int wasRedefined;
20354 
20355     if (redef == NULL)
20356 	return(0);
20357 
20358     do {
20359 	item = redef->item;
20360 	/*
20361 	* First try to locate the redefined component in the
20362 	* schema graph starting with the redefined schema.
20363 	* NOTE: According to this schema bug entry:
20364 	*   http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005OctDec/0019.html
20365 	*   it's not clear if the referenced component needs to originate
20366 	*   from the <redefine>d schema _document_ or the schema; the latter
20367 	*   would include all imported and included sub-schemas of the
20368 	*   <redefine>d schema. Currenlty we latter approach is used.
20369 	*   SUPPLEMENT: It seems that the WG moves towards the latter
20370 	*   approach, so we are doing it right.
20371 	*
20372 	*/
20373 	prev = xmlSchemaFindRedefCompInGraph(
20374 	    redef->targetBucket, item->type,
20375 	    redef->refName, redef->refTargetNs);
20376 	if (prev == NULL) {
20377 	    xmlChar *str = NULL;
20378 	    xmlNodePtr node;
20379 
20380 	    /*
20381 	    * SPEC src-redefine:
20382 	    * (6.2.1) "The �actual value� of its own name attribute plus
20383 	    * target namespace must successfully �resolve� to a model
20384 	    * group definition in I."
20385 	    * (7.2.1) "The �actual value� of its own name attribute plus
20386 	    * target namespace must successfully �resolve� to an attribute
20387 	    * group definition in I."
20388 
20389 	    *
20390 	    * Note that, if we are redefining with the use of references
20391 	    * to components, the spec assumes the src-resolve to be used;
20392 	    * but this won't assure that we search only *inside* the
20393 	    * redefined schema.
20394 	    */
20395 	    if (redef->reference)
20396 		node = WXS_ITEM_NODE(redef->reference);
20397 	    else
20398 		node = WXS_ITEM_NODE(item);
20399 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20400 		/*
20401 		* TODO: error code.
20402 		* Probably XML_SCHEMAP_SRC_RESOLVE, if this is using the
20403 		* reference kind.
20404 		*/
20405 		XML_SCHEMAP_SRC_REDEFINE, node, NULL,
20406 		"The %s '%s' to be redefined could not be found in "
20407 		"the redefined schema",
20408 		WXS_ITEM_TYPE_NAME(item),
20409 		xmlSchemaFormatQName(&str, redef->refTargetNs,
20410 		    redef->refName));
20411 	    FREE_AND_NULL(str);
20412 	    err = pctxt->err;
20413 	    redef = redef->next;
20414 	    continue;
20415 	}
20416 	/*
20417 	* TODO: Obtaining and setting the redefinition state is really
20418 	* clumsy.
20419 	*/
20420 	wasRedefined = 0;
20421 	switch (item->type) {
20422 	    case XML_SCHEMA_TYPE_COMPLEX:
20423 	    case XML_SCHEMA_TYPE_SIMPLE:
20424 		if ((WXS_TYPE_CAST prev)->flags &
20425 		    XML_SCHEMAS_TYPE_REDEFINED)
20426 		{
20427 		    wasRedefined = 1;
20428 		    break;
20429 		}
20430 		/* Mark it as redefined. */
20431 		(WXS_TYPE_CAST prev)->flags |= XML_SCHEMAS_TYPE_REDEFINED;
20432 		/*
20433 		* Assign the redefined type to the
20434 		* base type of the redefining type.
20435 		* TODO: How
20436 		*/
20437 		((xmlSchemaTypePtr) item)->baseType =
20438 		    (xmlSchemaTypePtr) prev;
20439 		break;
20440 	    case XML_SCHEMA_TYPE_GROUP:
20441 		if ((WXS_MODEL_GROUPDEF_CAST prev)->flags &
20442 		    XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20443 		{
20444 		    wasRedefined = 1;
20445 		    break;
20446 		}
20447 		/* Mark it as redefined. */
20448 		(WXS_MODEL_GROUPDEF_CAST prev)->flags |=
20449 		    XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED;
20450 		if (redef->reference != NULL) {
20451 		    /*
20452 		    * Overwrite the QName-reference with the
20453 		    * referenced model group def.
20454 		    */
20455 		    (WXS_PTC_CAST redef->reference)->children =
20456 			WXS_TREE_CAST prev;
20457 		}
20458 		redef->target = prev;
20459 		break;
20460 	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20461 		if ((WXS_ATTR_GROUP_CAST prev)->flags &
20462 		    XML_SCHEMAS_ATTRGROUP_REDEFINED)
20463 		{
20464 		    wasRedefined = 1;
20465 		    break;
20466 		}
20467 		(WXS_ATTR_GROUP_CAST prev)->flags |=
20468 		    XML_SCHEMAS_ATTRGROUP_REDEFINED;
20469 		if (redef->reference != NULL) {
20470 		    /*
20471 		    * Assign the redefined attribute group to the
20472 		    * QName-reference component.
20473 		    * This is the easy case, since we will just
20474 		    * expand the redefined group.
20475 		    */
20476 		    (WXS_QNAME_CAST redef->reference)->item = prev;
20477 		    redef->target = NULL;
20478 		} else {
20479 		    /*
20480 		    * This is the complicated case: we need
20481 		    * to apply src-redefine (7.2.2) at a later
20482 		    * stage, i.e. when attribute group references
20483 		    * have beed expanded and simple types have
20484 		    * beed fixed.
20485 		    */
20486 		    redef->target = prev;
20487 		}
20488 		break;
20489 	    default:
20490 		PERROR_INT("xmlSchemaResolveRedefReferences",
20491 		    "Unexpected redefined component type");
20492 		return(-1);
20493 	}
20494 	if (wasRedefined) {
20495 	    xmlChar *str = NULL;
20496 	    xmlNodePtr node;
20497 
20498 	    if (redef->reference)
20499 		node = WXS_ITEM_NODE(redef->reference);
20500 	    else
20501 		node = WXS_ITEM_NODE(redef->item);
20502 
20503 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20504 		/* TODO: error code. */
20505 		XML_SCHEMAP_SRC_REDEFINE,
20506 		node, NULL,
20507 		"The referenced %s was already redefined. Multiple "
20508 		"redefinition of the same component is not supported",
20509 		xmlSchemaGetComponentDesignation(&str, prev),
20510 		NULL);
20511 	    FREE_AND_NULL(str)
20512 	    err = pctxt->err;
20513 	    redef = redef->next;
20514 	    continue;
20515 	}
20516 	redef = redef->next;
20517     } while (redef != NULL);
20518 
20519     return(err);
20520 }
20521 
20522 static int
xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)20523 xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)
20524 {
20525     int err = 0;
20526     xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20527     xmlSchemaBasicItemPtr item;
20528 
20529     if (redef == NULL)
20530 	return(0);
20531 
20532     do {
20533 	if (redef->target == NULL) {
20534 	    redef = redef->next;
20535 	    continue;
20536 	}
20537 	item = redef->item;
20538 
20539 	switch (item->type) {
20540 	    case XML_SCHEMA_TYPE_SIMPLE:
20541 	    case XML_SCHEMA_TYPE_COMPLEX:
20542 		/*
20543 		* Since the spec wants the {name} of the redefined
20544 		* type to be 'absent', we'll NULL it.
20545 		*/
20546 		(WXS_TYPE_CAST redef->target)->name = NULL;
20547 
20548 		/*
20549 		* TODO: Seems like there's nothing more to do. The normal
20550 		* inheritance mechanism is used. But not 100% sure.
20551 		*/
20552 		break;
20553 	    case XML_SCHEMA_TYPE_GROUP:
20554 		/*
20555 		* URGENT TODO:
20556 		* SPEC src-redefine:
20557 		* (6.2.2) "The {model group} of the model group definition
20558 		* which corresponds to it per XML Representation of Model
20559 		* Group Definition Schema Components (�3.7.2) must be a
20560 		* �valid restriction� of the {model group} of that model
20561 		* group definition in I, as defined in Particle Valid
20562 		* (Restriction) (�3.9.6)."
20563 		*/
20564 		break;
20565 	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20566 		/*
20567 		* SPEC src-redefine:
20568 		* (7.2.2) "The {attribute uses} and {attribute wildcard} of
20569 		* the attribute group definition which corresponds to it
20570 		* per XML Representation of Attribute Group Definition Schema
20571 		* Components (�3.6.2) must be �valid restrictions� of the
20572 		* {attribute uses} and {attribute wildcard} of that attribute
20573 		* group definition in I, as defined in clause 2, clause 3 and
20574 		* clause 4 of Derivation Valid (Restriction, Complex)
20575 		* (�3.4.6) (where references to the base type definition are
20576 		* understood as references to the attribute group definition
20577 		* in I)."
20578 		*/
20579 		err = xmlSchemaCheckDerivationOKRestriction2to4(pctxt,
20580 		    XML_SCHEMA_ACTION_REDEFINE,
20581 		    item, redef->target,
20582 		    (WXS_ATTR_GROUP_CAST item)->attrUses,
20583 		    (WXS_ATTR_GROUP_CAST redef->target)->attrUses,
20584 		    (WXS_ATTR_GROUP_CAST item)->attributeWildcard,
20585 		    (WXS_ATTR_GROUP_CAST redef->target)->attributeWildcard);
20586 		if (err == -1)
20587 		    return(-1);
20588 		break;
20589 	    default:
20590 		break;
20591 	}
20592 	redef = redef->next;
20593     } while (redef != NULL);
20594     return(0);
20595 }
20596 
20597 
20598 static int
xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBucketPtr bucket)20599 xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,
20600 		       xmlSchemaBucketPtr bucket)
20601 {
20602     xmlSchemaBasicItemPtr item;
20603     int err;
20604     xmlHashTablePtr *table;
20605     const xmlChar *name;
20606     int i;
20607 
20608 #define WXS_GET_GLOBAL_HASH(c, slot) { \
20609     if (WXS_IS_BUCKET_IMPMAIN((c)->type)) \
20610 	table = &(WXS_IMPBUCKET((c))->schema->slot); \
20611     else \
20612 	table = &(WXS_INCBUCKET((c))->ownerImport->schema->slot); }
20613 
20614     /*
20615     * Add global components to the schema's hash tables.
20616     * This is the place where duplicate components will be
20617     * detected.
20618     * TODO: I think normally we should support imports of the
20619     *   same namespace from multiple locations. We don't do currently,
20620     *   but if we do then according to:
20621     *   http://www.w3.org/Bugs/Public/show_bug.cgi?id=2224
20622     *   we would need, if imported directly, to import redefined
20623     *   components as well to be able to catch clashing components.
20624     *   (I hope I'll still know what this means after some months :-()
20625     */
20626     if (bucket == NULL)
20627 	return(-1);
20628     if (bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED)
20629 	return(0);
20630     bucket->flags |= XML_SCHEMA_BUCKET_COMPS_ADDED;
20631 
20632     for (i = 0; i < bucket->globals->nbItems; i++) {
20633 	item = bucket->globals->items[i];
20634 	table = NULL;
20635 	switch (item->type) {
20636 	    case XML_SCHEMA_TYPE_COMPLEX:
20637 	    case XML_SCHEMA_TYPE_SIMPLE:
20638 		if (WXS_REDEFINED_TYPE(item))
20639 		    continue;
20640 		name = (WXS_TYPE_CAST item)->name;
20641 		WXS_GET_GLOBAL_HASH(bucket, typeDecl)
20642 		break;
20643 	    case XML_SCHEMA_TYPE_ELEMENT:
20644 		name = (WXS_ELEM_CAST item)->name;
20645 		WXS_GET_GLOBAL_HASH(bucket, elemDecl)
20646 		break;
20647 	    case XML_SCHEMA_TYPE_ATTRIBUTE:
20648 		name = (WXS_ATTR_CAST item)->name;
20649 		WXS_GET_GLOBAL_HASH(bucket, attrDecl)
20650 		break;
20651 	    case XML_SCHEMA_TYPE_GROUP:
20652 		if (WXS_REDEFINED_MODEL_GROUP_DEF(item))
20653 		    continue;
20654 		name = (WXS_MODEL_GROUPDEF_CAST item)->name;
20655 		WXS_GET_GLOBAL_HASH(bucket, groupDecl)
20656 		break;
20657 	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20658 		if (WXS_REDEFINED_ATTR_GROUP(item))
20659 		    continue;
20660 		name = (WXS_ATTR_GROUP_CAST item)->name;
20661 		WXS_GET_GLOBAL_HASH(bucket, attrgrpDecl)
20662 		break;
20663 	    case XML_SCHEMA_TYPE_IDC_KEY:
20664 	    case XML_SCHEMA_TYPE_IDC_UNIQUE:
20665 	    case XML_SCHEMA_TYPE_IDC_KEYREF:
20666 		name = (WXS_IDC_CAST item)->name;
20667 		WXS_GET_GLOBAL_HASH(bucket, idcDef)
20668 		break;
20669 	    case XML_SCHEMA_TYPE_NOTATION:
20670 		name = ((xmlSchemaNotationPtr) item)->name;
20671 		WXS_GET_GLOBAL_HASH(bucket, notaDecl)
20672 		break;
20673 	    default:
20674 		PERROR_INT("xmlSchemaAddComponents",
20675 		    "Unexpected global component type");
20676 		continue;
20677 	}
20678 	if (*table == NULL) {
20679 	    *table = xmlHashCreateDict(10, pctxt->dict);
20680 	    if (*table == NULL) {
20681 		PERROR_INT("xmlSchemaAddComponents",
20682 		    "failed to create a component hash table");
20683 		return(-1);
20684 	    }
20685 	}
20686 	err = xmlHashAddEntry(*table, name, item);
20687 	if (err != 0) {
20688 	    xmlChar *str = NULL;
20689 
20690 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20691 		XML_SCHEMAP_REDEFINED_TYPE,
20692 		WXS_ITEM_NODE(item),
20693 		WXS_BASIC_CAST item,
20694 		"A global %s '%s' does already exist",
20695 		WXS_ITEM_TYPE_NAME(item),
20696 		xmlSchemaGetComponentQName(&str, item));
20697 	    FREE_AND_NULL(str);
20698 	}
20699     }
20700     /*
20701     * Process imported/included schemas.
20702     */
20703     if (bucket->relations != NULL) {
20704 	xmlSchemaSchemaRelationPtr rel = bucket->relations;
20705 	do {
20706 	    if ((rel->bucket != NULL) &&
20707 		((rel->bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED) == 0)) {
20708 		if (xmlSchemaAddComponents(pctxt, rel->bucket) == -1)
20709 		    return(-1);
20710 	    }
20711 	    rel = rel->next;
20712 	} while (rel != NULL);
20713     }
20714     return(0);
20715 }
20716 
20717 static int
xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBucketPtr rootBucket)20718 xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt,
20719 			 xmlSchemaBucketPtr rootBucket)
20720 {
20721     xmlSchemaConstructionCtxtPtr con = pctxt->constructor;
20722     xmlSchemaTreeItemPtr item, *items;
20723     int nbItems, i, ret = 0;
20724     xmlSchemaBucketPtr oldbucket = con->bucket;
20725     xmlSchemaElementPtr elemDecl;
20726 
20727 #define FIXHFAILURE if (pctxt->err == XML_SCHEMAP_INTERNAL) goto exit_failure;
20728 
20729     if ((con->pending == NULL) ||
20730 	(con->pending->nbItems == 0))
20731 	return(0);
20732 
20733     /*
20734     * Since xmlSchemaFixupComplexType() will create new particles
20735     * (local components), and those particle components need a bucket
20736     * on the constructor, we'll assure here that the constructor has
20737     * a bucket.
20738     * TODO: Think about storing locals _only_ on the main bucket.
20739     */
20740     if (con->bucket == NULL)
20741 	con->bucket = rootBucket;
20742 
20743     /* TODO:
20744     * SPEC (src-redefine):
20745     * (6.2) "If it has no such self-reference, then all of the
20746     * following must be true:"
20747 
20748     * (6.2.2) The {model group} of the model group definition which
20749     * corresponds to it per XML Representation of Model Group
20750     * Definition Schema Components (�3.7.2) must be a �valid
20751     * restriction� of the {model group} of that model group definition
20752     * in I, as defined in Particle Valid (Restriction) (�3.9.6)."
20753     */
20754     xmlSchemaCheckSRCRedefineFirst(pctxt);
20755 
20756     /*
20757     * Add global components to the schemata's hash tables.
20758     */
20759     xmlSchemaAddComponents(pctxt, rootBucket);
20760 
20761     pctxt->ctxtType = NULL;
20762     items = (xmlSchemaTreeItemPtr *) con->pending->items;
20763     nbItems = con->pending->nbItems;
20764     /*
20765     * Now that we have parsed *all* the schema document(s) and converted
20766     * them to schema components, we can resolve references, apply component
20767     * constraints, create the FSA from the content model, etc.
20768     */
20769     /*
20770     * Resolve references of..
20771     *
20772     * 1. element declarations:
20773     *   - the type definition
20774     *   - the substitution group affiliation
20775     * 2. simple/complex types:
20776     *   - the base type definition
20777     *   - the memberTypes of union types
20778     *   - the itemType of list types
20779     * 3. attributes declarations and attribute uses:
20780     *   - the type definition
20781     *   - if an attribute use, then the attribute declaration
20782     * 4. attribute group references:
20783     *   - the attribute group definition
20784     * 5. particles:
20785     *   - the term of the particle (e.g. a model group)
20786     * 6. IDC key-references:
20787     *   - the referenced IDC 'key' or 'unique' definition
20788     * 7. Attribute prohibitions which had a "ref" attribute.
20789     */
20790     for (i = 0; i < nbItems; i++) {
20791 	item = items[i];
20792 	switch (item->type) {
20793 	    case XML_SCHEMA_TYPE_ELEMENT:
20794 		xmlSchemaResolveElementReferences(
20795 		    (xmlSchemaElementPtr) item, pctxt);
20796 		FIXHFAILURE;
20797 		break;
20798 	    case XML_SCHEMA_TYPE_COMPLEX:
20799 	    case XML_SCHEMA_TYPE_SIMPLE:
20800 		xmlSchemaResolveTypeReferences(
20801 		    (xmlSchemaTypePtr) item, pctxt);
20802 		FIXHFAILURE;
20803 		break;
20804 	    case XML_SCHEMA_TYPE_ATTRIBUTE:
20805 		xmlSchemaResolveAttrTypeReferences(
20806 		    (xmlSchemaAttributePtr) item, pctxt);
20807 		FIXHFAILURE;
20808 		break;
20809 	    case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
20810 		xmlSchemaResolveAttrUseReferences(
20811 		    (xmlSchemaAttributeUsePtr) item, pctxt);
20812 		FIXHFAILURE;
20813 		break;
20814 	    case XML_SCHEMA_EXTRA_QNAMEREF:
20815 		if ((WXS_QNAME_CAST item)->itemType ==
20816 		    XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
20817 		{
20818 		    xmlSchemaResolveAttrGroupReferences(
20819 			WXS_QNAME_CAST item, pctxt);
20820 		}
20821 		FIXHFAILURE;
20822 		break;
20823 	    case XML_SCHEMA_TYPE_SEQUENCE:
20824 	    case XML_SCHEMA_TYPE_CHOICE:
20825 	    case XML_SCHEMA_TYPE_ALL:
20826 		xmlSchemaResolveModelGroupParticleReferences(pctxt,
20827 		    WXS_MODEL_GROUP_CAST item);
20828 		FIXHFAILURE;
20829 		break;
20830 	    case XML_SCHEMA_TYPE_IDC_KEY:
20831 	    case XML_SCHEMA_TYPE_IDC_UNIQUE:
20832 	    case XML_SCHEMA_TYPE_IDC_KEYREF:
20833 		xmlSchemaResolveIDCKeyReferences(
20834 		    (xmlSchemaIDCPtr) item, pctxt);
20835 		FIXHFAILURE;
20836 		break;
20837 	    case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
20838 		/*
20839 		* Handle attribue prohibition which had a
20840 		* "ref" attribute.
20841 		*/
20842 		xmlSchemaResolveAttrUseProhibReferences(
20843 		    WXS_ATTR_PROHIB_CAST item, pctxt);
20844 		FIXHFAILURE;
20845 		break;
20846 	    default:
20847 		break;
20848 	}
20849     }
20850     if (pctxt->nberrors != 0)
20851 	goto exit_error;
20852 
20853     /*
20854     * Now that all references are resolved we
20855     * can check for circularity of...
20856     * 1. the base axis of type definitions
20857     * 2. nested model group definitions
20858     * 3. nested attribute group definitions
20859     * TODO: check for circual substitution groups.
20860     */
20861     for (i = 0; i < nbItems; i++) {
20862 	item = items[i];
20863 	/*
20864 	* Let's better stop on the first error here.
20865 	*/
20866 	switch (item->type) {
20867 	    case XML_SCHEMA_TYPE_COMPLEX:
20868 	    case XML_SCHEMA_TYPE_SIMPLE:
20869 		xmlSchemaCheckTypeDefCircular(
20870 		    (xmlSchemaTypePtr) item, pctxt);
20871 		FIXHFAILURE;
20872 		if (pctxt->nberrors != 0)
20873 		    goto exit_error;
20874 		break;
20875 	    case XML_SCHEMA_TYPE_GROUP:
20876 		xmlSchemaCheckGroupDefCircular(
20877 		    (xmlSchemaModelGroupDefPtr) item, pctxt);
20878 		FIXHFAILURE;
20879 		if (pctxt->nberrors != 0)
20880 		    goto exit_error;
20881 		break;
20882 	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20883 		xmlSchemaCheckAttrGroupCircular(
20884 		    (xmlSchemaAttributeGroupPtr) item, pctxt);
20885 		FIXHFAILURE;
20886 		if (pctxt->nberrors != 0)
20887 		    goto exit_error;
20888 		break;
20889 	    default:
20890 		break;
20891 	}
20892     }
20893     if (pctxt->nberrors != 0)
20894 	goto exit_error;
20895     /*
20896     * Model group definition references:
20897     * Such a reference is reflected by a particle at the component
20898     * level. Until now the 'term' of such particles pointed
20899     * to the model group definition; this was done, in order to
20900     * ease circularity checks. Now we need to set the 'term' of
20901     * such particles to the model group of the model group definition.
20902     */
20903     for (i = 0; i < nbItems; i++) {
20904 	item = items[i];
20905 	switch (item->type) {
20906 	    case XML_SCHEMA_TYPE_SEQUENCE:
20907 	    case XML_SCHEMA_TYPE_CHOICE:
20908 		xmlSchemaModelGroupToModelGroupDefFixup(pctxt,
20909 		    WXS_MODEL_GROUP_CAST item);
20910 		break;
20911 	    default:
20912 		break;
20913 	}
20914     }
20915     if (pctxt->nberrors != 0)
20916 	goto exit_error;
20917     /*
20918     * Expand attribute group references of attribute group definitions.
20919     */
20920     for (i = 0; i < nbItems; i++) {
20921 	item = items[i];
20922 	switch (item->type) {
20923             case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20924 		if ((! WXS_ATTR_GROUP_EXPANDED(item)) &&
20925 		    WXS_ATTR_GROUP_HAS_REFS(item))
20926 		{
20927 		    xmlSchemaAttributeGroupExpandRefs(pctxt,
20928 			WXS_ATTR_GROUP_CAST item);
20929 		    FIXHFAILURE;
20930 		}
20931 		break;
20932 	    default:
20933 		break;
20934 	}
20935     }
20936     if (pctxt->nberrors != 0)
20937 	goto exit_error;
20938     /*
20939     * First compute the variety of simple types. This is needed as
20940     * a seperate step, since otherwise we won't be able to detect
20941     * circular union types in all cases.
20942     */
20943     for (i = 0; i < nbItems; i++) {
20944 	item = items[i];
20945 	switch (item->type) {
20946             case XML_SCHEMA_TYPE_SIMPLE:
20947 		if (WXS_IS_TYPE_NOT_FIXED_1((xmlSchemaTypePtr) item)) {
20948 		    xmlSchemaFixupSimpleTypeStageOne(pctxt,
20949 			(xmlSchemaTypePtr) item);
20950 		    FIXHFAILURE;
20951 		}
20952 		break;
20953 	    default:
20954 		break;
20955 	}
20956     }
20957     if (pctxt->nberrors != 0)
20958 	goto exit_error;
20959     /*
20960     * Detect circular union types. Note that this needs the variety to
20961     * be already computed.
20962     */
20963     for (i = 0; i < nbItems; i++) {
20964 	item = items[i];
20965 	switch (item->type) {
20966             case XML_SCHEMA_TYPE_SIMPLE:
20967 		if (((xmlSchemaTypePtr) item)->memberTypes != NULL) {
20968 		    xmlSchemaCheckUnionTypeDefCircular(pctxt,
20969 			(xmlSchemaTypePtr) item);
20970 		    FIXHFAILURE;
20971 		}
20972 		break;
20973 	    default:
20974 		break;
20975 	}
20976     }
20977     if (pctxt->nberrors != 0)
20978 	goto exit_error;
20979 
20980     /*
20981     * Do the complete type fixup for simple types.
20982     */
20983     for (i = 0; i < nbItems; i++) {
20984 	item = items[i];
20985 	switch (item->type) {
20986             case XML_SCHEMA_TYPE_SIMPLE:
20987 		if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
20988 		    xmlSchemaFixupSimpleTypeStageTwo(pctxt, WXS_TYPE_CAST item);
20989 		    FIXHFAILURE;
20990 		}
20991 		break;
20992 	    default:
20993 		break;
20994 	}
20995     }
20996     if (pctxt->nberrors != 0)
20997 	goto exit_error;
20998     /*
20999     * At this point we need build and check all simple types.
21000     */
21001     /*
21002     * Apply contraints for attribute declarations.
21003     */
21004     for (i = 0; i < nbItems; i++) {
21005 	item = items[i];
21006 	switch (item->type) {
21007 	    case XML_SCHEMA_TYPE_ATTRIBUTE:
21008 		xmlSchemaCheckAttrPropsCorrect(pctxt, WXS_ATTR_CAST item);
21009 		FIXHFAILURE;
21010 		break;
21011 	    default:
21012 		break;
21013 	}
21014     }
21015     if (pctxt->nberrors != 0)
21016 	goto exit_error;
21017     /*
21018     * Apply constraints for attribute uses.
21019     */
21020     for (i = 0; i < nbItems; i++) {
21021 	item = items[i];
21022 	switch (item->type) {
21023 	    case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
21024 		if (((xmlSchemaAttributeUsePtr)item)->defValue != NULL) {
21025 		    xmlSchemaCheckAttrUsePropsCorrect(pctxt,
21026 			WXS_ATTR_USE_CAST item);
21027 		    FIXHFAILURE;
21028 		}
21029 		break;
21030 	    default:
21031 		break;
21032 	}
21033     }
21034     if (pctxt->nberrors != 0)
21035 	goto exit_error;
21036 
21037     /*
21038     * Apply constraints for attribute group definitions.
21039     */
21040     for (i = 0; i < nbItems; i++) {
21041 	item = items[i];
21042 	switch (item->type) {
21043 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21044 	    if (( (WXS_ATTR_GROUP_CAST item)->attrUses != NULL) &&
21045 		( (WXS_LIST_CAST (WXS_ATTR_GROUP_CAST item)->attrUses)->nbItems > 1))
21046 	    {
21047 		xmlSchemaCheckAGPropsCorrect(pctxt, WXS_ATTR_GROUP_CAST item);
21048 		FIXHFAILURE;
21049 	    }
21050 	    break;
21051 	default:
21052 	    break;
21053 	}
21054     }
21055     if (pctxt->nberrors != 0)
21056 	goto exit_error;
21057 
21058     /*
21059     * Apply constraints for redefinitions.
21060     */
21061     if (WXS_CONSTRUCTOR(pctxt)->redefs != NULL)
21062 	xmlSchemaCheckSRCRedefineSecond(pctxt);
21063     if (pctxt->nberrors != 0)
21064 	goto exit_error;
21065 
21066     /*
21067     * Complex types are builded and checked.
21068     */
21069     for (i = 0; i < nbItems; i++) {
21070 	item = con->pending->items[i];
21071 	switch (item->type) {
21072 	    case XML_SCHEMA_TYPE_COMPLEX:
21073 		if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21074 		    xmlSchemaFixupComplexType(pctxt, WXS_TYPE_CAST item);
21075 		    FIXHFAILURE;
21076 		}
21077 		break;
21078 	    default:
21079 		break;
21080 	}
21081     }
21082     if (pctxt->nberrors != 0)
21083 	goto exit_error;
21084 
21085     /*
21086     * The list could have changed, since xmlSchemaFixupComplexType()
21087     * will create particles and model groups in some cases.
21088     */
21089     items = (xmlSchemaTreeItemPtr *) con->pending->items;
21090     nbItems = con->pending->nbItems;
21091 
21092     /*
21093     * Apply some constraints for element declarations.
21094     */
21095     for (i = 0; i < nbItems; i++) {
21096 	item = items[i];
21097 	switch (item->type) {
21098 	    case XML_SCHEMA_TYPE_ELEMENT:
21099 		elemDecl = (xmlSchemaElementPtr) item;
21100 
21101 		if ((elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED) == 0)
21102 		{
21103 		    xmlSchemaCheckElementDeclComponent(
21104 			(xmlSchemaElementPtr) elemDecl, pctxt);
21105 		    FIXHFAILURE;
21106 		}
21107 
21108 #ifdef WXS_ELEM_DECL_CONS_ENABLED
21109 		/*
21110 		* Schema Component Constraint: Element Declarations Consistent
21111 		* Apply this constraint to local types of element declarations.
21112 		*/
21113 		if ((WXS_ELEM_TYPEDEF(elemDecl) != NULL) &&
21114 		    (WXS_IS_COMPLEX(WXS_ELEM_TYPEDEF(elemDecl))) &&
21115 		    (WXS_TYPE_IS_LOCAL(WXS_ELEM_TYPEDEF(elemDecl))))
21116 		{
21117 		    xmlSchemaCheckElementDeclConsistent(pctxt,
21118 			WXS_BASIC_CAST elemDecl,
21119 			WXS_TYPE_PARTICLE(WXS_ELEM_TYPEDEF(elemDecl)),
21120 			NULL, NULL, 0);
21121 		}
21122 #endif
21123 		break;
21124 	    default:
21125 		break;
21126 	}
21127     }
21128     if (pctxt->nberrors != 0)
21129 	goto exit_error;
21130 
21131     /*
21132     * Finally we can build the automaton from the content model of
21133     * complex types.
21134     */
21135 
21136     for (i = 0; i < nbItems; i++) {
21137 	item = items[i];
21138 	switch (item->type) {
21139 	    case XML_SCHEMA_TYPE_COMPLEX:
21140 		xmlSchemaBuildContentModel((xmlSchemaTypePtr) item, pctxt);
21141 		/* FIXHFAILURE; */
21142 		break;
21143 	    default:
21144 		break;
21145 	}
21146     }
21147     if (pctxt->nberrors != 0)
21148 	goto exit_error;
21149     /*
21150     * URGENT TODO: cos-element-consistent
21151     */
21152     goto exit;
21153 
21154 exit_error:
21155     ret = pctxt->err;
21156     goto exit;
21157 
21158 exit_failure:
21159     ret = -1;
21160 
21161 exit:
21162     /*
21163     * Reset the constructor. This is needed for XSI acquisition, since
21164     * those items will be processed over and over again for every XSI
21165     * if not cleared here.
21166     */
21167     con->bucket = oldbucket;
21168     con->pending->nbItems = 0;
21169     if (con->substGroups != NULL) {
21170 	xmlHashFree(con->substGroups,
21171 	    (xmlHashDeallocator) xmlSchemaSubstGroupFree);
21172 	con->substGroups = NULL;
21173     }
21174     if (con->redefs != NULL) {
21175 	xmlSchemaRedefListFree(con->redefs);
21176 	con->redefs = NULL;
21177     }
21178     return(ret);
21179 }
21180 /**
21181  * xmlSchemaParse:
21182  * @ctxt:  a schema validation context
21183  *
21184  * parse a schema definition resource and build an internal
21185  * XML Shema struture which can be used to validate instances.
21186  *
21187  * Returns the internal XML Schema structure built from the resource or
21188  *         NULL in case of error
21189  */
21190 xmlSchemaPtr
xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)21191 xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
21192 {
21193     xmlSchemaPtr mainSchema = NULL;
21194     xmlSchemaBucketPtr bucket = NULL;
21195     int res;
21196 
21197     /*
21198     * This one is used if the schema to be parsed was specified via
21199     * the API; i.e. not automatically by the validated instance document.
21200     */
21201 
21202     xmlSchemaInitTypes();
21203 
21204     if (ctxt == NULL)
21205         return (NULL);
21206 
21207     /* TODO: Init the context. Is this all we need?*/
21208     ctxt->nberrors = 0;
21209     ctxt->err = 0;
21210     ctxt->counter = 0;
21211 
21212     /* Create the *main* schema. */
21213     mainSchema = xmlSchemaNewSchema(ctxt);
21214     if (mainSchema == NULL)
21215 	goto exit_failure;
21216     /*
21217     * Create the schema constructor.
21218     */
21219     if (ctxt->constructor == NULL) {
21220 	ctxt->constructor = xmlSchemaConstructionCtxtCreate(ctxt->dict);
21221 	if (ctxt->constructor == NULL)
21222 	    return(NULL);
21223 	/* Take ownership of the constructor to be able to free it. */
21224 	ctxt->ownsConstructor = 1;
21225     }
21226     ctxt->constructor->mainSchema = mainSchema;
21227     /*
21228     * Locate and add the schema document.
21229     */
21230     res = xmlSchemaAddSchemaDoc(ctxt, XML_SCHEMA_SCHEMA_MAIN,
21231 	ctxt->URL, ctxt->doc, ctxt->buffer, ctxt->size, NULL,
21232 	NULL, NULL, &bucket);
21233     if (res == -1)
21234 	goto exit_failure;
21235     if (res != 0)
21236 	goto exit;
21237 
21238     if (bucket == NULL) {
21239 	/* TODO: Error code, actually we failed to *locate* the schema. */
21240 	if (ctxt->URL)
21241 	    xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21242 		NULL, NULL,
21243 		"Failed to locate the main schema resource at '%s'",
21244 		ctxt->URL, NULL);
21245 	else
21246 	    xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21247 		NULL, NULL,
21248 		"Failed to locate the main schema resource",
21249 		    NULL, NULL);
21250 	goto exit;
21251     }
21252     /* Then do the parsing for good. */
21253     if (xmlSchemaParseNewDocWithContext(ctxt, mainSchema, bucket) == -1)
21254 	goto exit_failure;
21255     if (ctxt->nberrors != 0)
21256 	goto exit;
21257 
21258     mainSchema->doc = bucket->doc;
21259     mainSchema->preserve = ctxt->preserve;
21260 
21261     ctxt->schema = mainSchema;
21262 
21263     if (xmlSchemaFixupComponents(ctxt, WXS_CONSTRUCTOR(ctxt)->mainBucket) == -1)
21264 	goto exit_failure;
21265 
21266     /*
21267     * TODO: This is not nice, since we cannot distinguish from the
21268     * result if there was an internal error or not.
21269     */
21270 exit:
21271     if (ctxt->nberrors != 0) {
21272 	if (mainSchema) {
21273 	    xmlSchemaFree(mainSchema);
21274 	    mainSchema = NULL;
21275 	}
21276 	if (ctxt->constructor) {
21277 	    xmlSchemaConstructionCtxtFree(ctxt->constructor);
21278 	    ctxt->constructor = NULL;
21279 	    ctxt->ownsConstructor = 0;
21280 	}
21281     }
21282     ctxt->schema = NULL;
21283     return(mainSchema);
21284 exit_failure:
21285     /*
21286     * Quite verbose, but should catch internal errors, which were
21287     * not communitated.
21288     */
21289     if (mainSchema) {
21290         xmlSchemaFree(mainSchema);
21291 	mainSchema = NULL;
21292     }
21293     if (ctxt->constructor) {
21294 	xmlSchemaConstructionCtxtFree(ctxt->constructor);
21295 	ctxt->constructor = NULL;
21296 	ctxt->ownsConstructor = 0;
21297     }
21298     PERROR_INT2("xmlSchemaParse",
21299 	"An internal error occured");
21300     ctxt->schema = NULL;
21301     return(NULL);
21302 }
21303 
21304 /**
21305  * xmlSchemaSetParserErrors:
21306  * @ctxt:  a schema validation context
21307  * @err:  the error callback
21308  * @warn:  the warning callback
21309  * @ctx:  contextual data for the callbacks
21310  *
21311  * Set the callback functions used to handle errors for a validation context
21312  */
21313 void
xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,xmlSchemaValidityErrorFunc err,xmlSchemaValidityWarningFunc warn,void * ctx)21314 xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21315                          xmlSchemaValidityErrorFunc err,
21316                          xmlSchemaValidityWarningFunc warn, void *ctx)
21317 {
21318     if (ctxt == NULL)
21319         return;
21320     ctxt->error = err;
21321     ctxt->warning = warn;
21322     ctxt->errCtxt = ctx;
21323     if (ctxt->vctxt != NULL)
21324 	xmlSchemaSetValidErrors(ctxt->vctxt, err, warn, ctx);
21325 }
21326 
21327 /**
21328  * xmlSchemaSetParserStructuredErrors:
21329  * @ctxt:  a schema parser context
21330  * @serror:  the structured error function
21331  * @ctx: the functions context
21332  *
21333  * Set the structured error callback
21334  */
21335 void
xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,xmlStructuredErrorFunc serror,void * ctx)21336 xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,
21337 				   xmlStructuredErrorFunc serror,
21338 				   void *ctx)
21339 {
21340     if (ctxt == NULL)
21341 	return;
21342     ctxt->serror = serror;
21343     ctxt->errCtxt = ctx;
21344     if (ctxt->vctxt != NULL)
21345 	xmlSchemaSetValidStructuredErrors(ctxt->vctxt, serror, ctx);
21346 }
21347 
21348 /**
21349  * xmlSchemaGetParserErrors:
21350  * @ctxt:  a XMl-Schema parser context
21351  * @err: the error callback result
21352  * @warn: the warning callback result
21353  * @ctx: contextual data for the callbacks result
21354  *
21355  * Get the callback information used to handle errors for a parser context
21356  *
21357  * Returns -1 in case of failure, 0 otherwise
21358  */
21359 int
xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,xmlSchemaValidityErrorFunc * err,xmlSchemaValidityWarningFunc * warn,void ** ctx)21360 xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21361 			 xmlSchemaValidityErrorFunc * err,
21362 			 xmlSchemaValidityWarningFunc * warn, void **ctx)
21363 {
21364 	if (ctxt == NULL)
21365 		return(-1);
21366 	if (err != NULL)
21367 		*err = ctxt->error;
21368 	if (warn != NULL)
21369 		*warn = ctxt->warning;
21370 	if (ctx != NULL)
21371 		*ctx = ctxt->errCtxt;
21372 	return(0);
21373 }
21374 
21375 /**
21376  * xmlSchemaFacetTypeToString:
21377  * @type:  the facet type
21378  *
21379  * Convert the xmlSchemaTypeType to a char string.
21380  *
21381  * Returns the char string representation of the facet type if the
21382  *     type is a facet and an "Internal Error" string otherwise.
21383  */
21384 static const xmlChar *
xmlSchemaFacetTypeToString(xmlSchemaTypeType type)21385 xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
21386 {
21387     switch (type) {
21388         case XML_SCHEMA_FACET_PATTERN:
21389             return (BAD_CAST "pattern");
21390         case XML_SCHEMA_FACET_MAXEXCLUSIVE:
21391             return (BAD_CAST "maxExclusive");
21392         case XML_SCHEMA_FACET_MAXINCLUSIVE:
21393             return (BAD_CAST "maxInclusive");
21394         case XML_SCHEMA_FACET_MINEXCLUSIVE:
21395             return (BAD_CAST "minExclusive");
21396         case XML_SCHEMA_FACET_MININCLUSIVE:
21397             return (BAD_CAST "minInclusive");
21398         case XML_SCHEMA_FACET_WHITESPACE:
21399             return (BAD_CAST "whiteSpace");
21400         case XML_SCHEMA_FACET_ENUMERATION:
21401             return (BAD_CAST "enumeration");
21402         case XML_SCHEMA_FACET_LENGTH:
21403             return (BAD_CAST "length");
21404         case XML_SCHEMA_FACET_MAXLENGTH:
21405             return (BAD_CAST "maxLength");
21406         case XML_SCHEMA_FACET_MINLENGTH:
21407             return (BAD_CAST "minLength");
21408         case XML_SCHEMA_FACET_TOTALDIGITS:
21409             return (BAD_CAST "totalDigits");
21410         case XML_SCHEMA_FACET_FRACTIONDIGITS:
21411             return (BAD_CAST "fractionDigits");
21412         default:
21413             break;
21414     }
21415     return (BAD_CAST "Internal Error");
21416 }
21417 
21418 static xmlSchemaWhitespaceValueType
xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)21419 xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
21420 {
21421     /*
21422     * The normalization type can be changed only for types which are derived
21423     * from xsd:string.
21424     */
21425     if (type->type == XML_SCHEMA_TYPE_BASIC) {
21426 	/*
21427 	* Note that we assume a whitespace of preserve for anySimpleType.
21428 	*/
21429 	if ((type->builtInType == XML_SCHEMAS_STRING) ||
21430 	    (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
21431 	    return(XML_SCHEMA_WHITESPACE_PRESERVE);
21432 	else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
21433 	    return(XML_SCHEMA_WHITESPACE_REPLACE);
21434 	else {
21435 	    /*
21436 	    * For all �atomic� datatypes other than string (and types �derived�
21437 	    * by �restriction� from it) the value of whiteSpace is fixed to
21438 	    * collapse
21439 	    * Note that this includes built-in list datatypes.
21440 	    */
21441 	    return(XML_SCHEMA_WHITESPACE_COLLAPSE);
21442 	}
21443     } else if (WXS_IS_LIST(type)) {
21444 	/*
21445 	* For list types the facet "whiteSpace" is fixed to "collapse".
21446 	*/
21447 	return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21448     } else if (WXS_IS_UNION(type)) {
21449 	return (XML_SCHEMA_WHITESPACE_UNKNOWN);
21450     } else if (WXS_IS_ATOMIC(type)) {
21451 	if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
21452 	    return (XML_SCHEMA_WHITESPACE_PRESERVE);
21453 	else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
21454 	    return (XML_SCHEMA_WHITESPACE_REPLACE);
21455 	else
21456 	    return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21457     }
21458     return (-1);
21459 }
21460 
21461 /************************************************************************
21462  * 									*
21463  * 			Simple type validation				*
21464  * 									*
21465  ************************************************************************/
21466 
21467 
21468 /************************************************************************
21469  * 									*
21470  * 			DOM Validation code				*
21471  * 									*
21472  ************************************************************************/
21473 
21474 /**
21475  * xmlSchemaAssembleByLocation:
21476  * @pctxt:  a schema parser context
21477  * @vctxt:  a schema validation context
21478  * @schema: the existing schema
21479  * @node: the node that fired the assembling
21480  * @nsName: the namespace name of the new schema
21481  * @location: the location of the schema
21482  *
21483  * Expands an existing schema by an additional schema.
21484  *
21485  * Returns 0 if the new schema is correct, a positive error code
21486  * number otherwise and -1 in case of an internal or API error.
21487  */
21488 static int
xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,xmlSchemaPtr schema,xmlNodePtr node,const xmlChar * nsName,const xmlChar * location)21489 xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
21490 			    xmlSchemaPtr schema,
21491 			    xmlNodePtr node,
21492 			    const xmlChar *nsName,
21493 			    const xmlChar *location)
21494 {
21495     int ret = 0;
21496     xmlSchemaParserCtxtPtr pctxt;
21497     xmlSchemaBucketPtr bucket = NULL;
21498 
21499     if ((vctxt == NULL) || (schema == NULL))
21500 	return (-1);
21501 
21502     if (vctxt->pctxt == NULL) {
21503 	VERROR_INT("xmlSchemaAssembleByLocation",
21504 	    "no parser context available");
21505 	return(-1);
21506     }
21507     pctxt = vctxt->pctxt;
21508     if (pctxt->constructor == NULL) {
21509 	PERROR_INT("xmlSchemaAssembleByLocation",
21510 	    "no constructor");
21511 	return(-1);
21512     }
21513     /*
21514     * Acquire the schema document.
21515     */
21516     location = xmlSchemaBuildAbsoluteURI(pctxt->dict,
21517 	location, node);
21518     /*
21519     * Note that we pass XML_SCHEMA_SCHEMA_IMPORT here;
21520     * the process will automatically change this to
21521     * XML_SCHEMA_SCHEMA_MAIN if it is the first schema document.
21522     */
21523     ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
21524 	location, NULL, NULL, 0, node, NULL, nsName,
21525 	&bucket);
21526     if (ret != 0)
21527 	return(ret);
21528     if (bucket == NULL) {
21529 	/*
21530 	* Generate a warning that the document could not be located.
21531 	*/
21532 	xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21533 	    node, NULL,
21534 	    "The document at location '%s' could not be acquired",
21535 	    location, NULL, NULL);
21536 	return(ret);
21537     }
21538     /*
21539     * The first located schema will be handled as if all other
21540     * schemas imported by XSI were imported by this first schema.
21541     */
21542     if ((bucket != NULL) &&
21543 	(WXS_CONSTRUCTOR(pctxt)->bucket == NULL))
21544 	WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
21545     /*
21546     * TODO: Is this handled like an import? I.e. is it not an error
21547     * if the schema cannot be located?
21548     */
21549     if ((bucket == NULL) || (! CAN_PARSE_SCHEMA(bucket)))
21550 	return(0);
21551     /*
21552     * We will reuse the parser context for every schema imported
21553     * directly via XSI. So reset the context.
21554     */
21555     pctxt->nberrors = 0;
21556     pctxt->err = 0;
21557     pctxt->doc = bucket->doc;
21558 
21559     ret = xmlSchemaParseNewDocWithContext(pctxt, schema, bucket);
21560     if (ret == -1) {
21561 	pctxt->doc = NULL;
21562 	goto exit_failure;
21563     }
21564     /* Paranoid error channelling. */
21565     if ((ret == 0) && (pctxt->nberrors != 0))
21566 	ret = pctxt->err;
21567     if (pctxt->nberrors == 0) {
21568 	/*
21569 	* Only bother to fixup pending components, if there was
21570 	* no error yet.
21571 	* For every XSI acquired schema (and its sub-schemata) we will
21572 	* fixup the components.
21573 	*/
21574 	xmlSchemaFixupComponents(pctxt, bucket);
21575 	ret = pctxt->err;
21576 	/*
21577 	* Not nice, but we need somehow to channel the schema parser
21578 	* error to the validation context.
21579 	*/
21580 	if ((ret != 0) && (vctxt->err == 0))
21581 	    vctxt->err = ret;
21582 	vctxt->nberrors += pctxt->nberrors;
21583     } else {
21584 	/* Add to validation error sum. */
21585 	vctxt->nberrors += pctxt->nberrors;
21586     }
21587     pctxt->doc = NULL;
21588     return(ret);
21589 exit_failure:
21590     pctxt->doc = NULL;
21591     return (-1);
21592 }
21593 
21594 static xmlSchemaAttrInfoPtr
xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,int metaType)21595 xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
21596 			 int metaType)
21597 {
21598     if (vctxt->nbAttrInfos == 0)
21599 	return (NULL);
21600     {
21601 	int i;
21602 	xmlSchemaAttrInfoPtr iattr;
21603 
21604 	for (i = 0; i < vctxt->nbAttrInfos; i++) {
21605 	    iattr = vctxt->attrInfos[i];
21606 	    if (iattr->metaType == metaType)
21607 		return (iattr);
21608 	}
21609 
21610     }
21611     return (NULL);
21612 }
21613 
21614 /**
21615  * xmlSchemaAssembleByXSI:
21616  * @vctxt:  a schema validation context
21617  *
21618  * Expands an existing schema by an additional schema using
21619  * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
21620  * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
21621  * must be set to 1.
21622  *
21623  * Returns 0 if the new schema is correct, a positive error code
21624  * number otherwise and -1 in case of an internal or API error.
21625  */
21626 static int
xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)21627 xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
21628 {
21629     const xmlChar *cur, *end;
21630     const xmlChar *nsname = NULL, *location;
21631     int count = 0;
21632     int ret = 0;
21633     xmlSchemaAttrInfoPtr iattr;
21634 
21635     /*
21636     * Parse the value; we will assume an even number of values
21637     * to be given (this is how Xerces and XSV work).
21638     *
21639     * URGENT TODO: !! This needs to work for both
21640     * @noNamespaceSchemaLocation AND @schemaLocation on the same
21641     * element !!
21642     */
21643     iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21644 	XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
21645     if (iattr == NULL)
21646 	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21647 	XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
21648     if (iattr == NULL)
21649 	return (0);
21650     cur = iattr->value;
21651     do {
21652 	/*
21653 	* TODO: Move the string parsing mechanism away from here.
21654 	*/
21655 	if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
21656 	    /*
21657 	    * Get the namespace name.
21658 	    */
21659 	    while (IS_BLANK_CH(*cur))
21660 		cur++;
21661 	    end = cur;
21662 	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21663 		end++;
21664 	    if (end == cur)
21665 		break;
21666 	    count++; /* TODO: Don't use the schema's dict. */
21667 	    nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21668 	    cur = end;
21669 	}
21670 	/*
21671 	* Get the URI.
21672 	*/
21673 	while (IS_BLANK_CH(*cur))
21674 	    cur++;
21675 	end = cur;
21676 	while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21677 	    end++;
21678 	if (end == cur) {
21679 	    if (iattr->metaType ==
21680 		XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC)
21681 	    {
21682 		/*
21683 		* If using @schemaLocation then tuples are expected.
21684 		* I.e. the namespace name *and* the document's URI.
21685 		*/
21686 		xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21687 		    iattr->node, NULL,
21688 		    "The value must consist of tuples: the target namespace "
21689 		    "name and the document's URI", NULL, NULL, NULL);
21690 	    }
21691 	    break;
21692 	}
21693 	count++; /* TODO: Don't use the schema's dict. */
21694 	location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21695 	cur = end;
21696 	ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
21697 	    iattr->node, nsname, location);
21698 	if (ret == -1) {
21699 	    VERROR_INT("xmlSchemaAssembleByXSI",
21700 		"assembling schemata");
21701 	    return (-1);
21702 	}
21703     } while (*cur != 0);
21704     return (ret);
21705 }
21706 
21707 static const xmlChar *
xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,const xmlChar * prefix)21708 xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
21709 			 const xmlChar *prefix)
21710 {
21711     if (vctxt->sax != NULL) {
21712 	int i, j;
21713 	xmlSchemaNodeInfoPtr inode;
21714 
21715 	for (i = vctxt->depth; i >= 0; i--) {
21716 	    if (vctxt->elemInfos[i]->nbNsBindings != 0) {
21717 		inode = vctxt->elemInfos[i];
21718 		for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
21719 		    if (((prefix == NULL) &&
21720 			    (inode->nsBindings[j] == NULL)) ||
21721 			((prefix != NULL) && xmlStrEqual(prefix,
21722 			    inode->nsBindings[j]))) {
21723 
21724 			/*
21725 			* Note that the namespace bindings are already
21726 			* in a string dict.
21727 			*/
21728 			return (inode->nsBindings[j+1]);
21729 		    }
21730 		}
21731 	    }
21732 	}
21733 	return (NULL);
21734 #ifdef LIBXML_WRITER_ENABLED
21735     } else if (vctxt->reader != NULL) {
21736 	xmlChar *nsName;
21737 
21738 	nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
21739 	if (nsName != NULL) {
21740 	    const xmlChar *ret;
21741 
21742 	    ret = xmlDictLookup(vctxt->dict, nsName, -1);
21743 	    xmlFree(nsName);
21744 	    return (ret);
21745 	} else
21746 	    return (NULL);
21747 #endif
21748     } else {
21749 	xmlNsPtr ns;
21750 
21751 	if ((vctxt->inode->node == NULL) ||
21752 	    (vctxt->inode->node->doc == NULL)) {
21753 	    VERROR_INT("xmlSchemaLookupNamespace",
21754 		"no node or node's doc avaliable");
21755 	    return (NULL);
21756 	}
21757 	ns = xmlSearchNs(vctxt->inode->node->doc,
21758 	    vctxt->inode->node, prefix);
21759 	if (ns != NULL)
21760 	    return (ns->href);
21761 	return (NULL);
21762     }
21763 }
21764 
21765 /*
21766 * This one works on the schema of the validation context.
21767 */
21768 static int
xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,xmlSchemaPtr schema,xmlNodePtr node,const xmlChar * value,xmlSchemaValPtr * val,int valNeeded)21769 xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
21770 			  xmlSchemaPtr schema,
21771 			  xmlNodePtr node,
21772 			  const xmlChar *value,
21773 			  xmlSchemaValPtr *val,
21774 			  int valNeeded)
21775 {
21776     int ret;
21777 
21778     if (vctxt && (vctxt->schema == NULL)) {
21779 	VERROR_INT("xmlSchemaValidateNotation",
21780 	    "a schema is needed on the validation context");
21781 	return (-1);
21782     }
21783     ret = xmlValidateQName(value, 1);
21784     if (ret != 0)
21785 	return (ret);
21786     {
21787 	xmlChar *localName = NULL;
21788 	xmlChar *prefix = NULL;
21789 
21790 	localName = xmlSplitQName2(value, &prefix);
21791 	if (prefix != NULL) {
21792 	    const xmlChar *nsName = NULL;
21793 
21794 	    if (vctxt != NULL)
21795 		nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
21796 	    else if (node != NULL) {
21797 		xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
21798 		if (ns != NULL)
21799 		    nsName = ns->href;
21800 	    } else {
21801 		xmlFree(prefix);
21802 		xmlFree(localName);
21803 		return (1);
21804 	    }
21805 	    if (nsName == NULL) {
21806 		xmlFree(prefix);
21807 		xmlFree(localName);
21808 		return (1);
21809 	    }
21810 	    if (xmlSchemaGetNotation(schema, localName, nsName) != NULL) {
21811 		if ((valNeeded) && (val != NULL)) {
21812 		    (*val) = xmlSchemaNewNOTATIONValue(xmlStrdup(localName),
21813 						       xmlStrdup(nsName));
21814 		    if (*val == NULL)
21815 			ret = -1;
21816 		}
21817 	    } else
21818 		ret = 1;
21819 	    xmlFree(prefix);
21820 	    xmlFree(localName);
21821 	} else {
21822 	    if (xmlSchemaGetNotation(schema, value, NULL) != NULL) {
21823 		if (valNeeded && (val != NULL)) {
21824 		    (*val) = xmlSchemaNewNOTATIONValue(
21825 			BAD_CAST xmlStrdup(value), NULL);
21826 		    if (*val == NULL)
21827 			ret = -1;
21828 		}
21829 	    } else
21830 		return (1);
21831 	}
21832     }
21833     return (ret);
21834 }
21835 
21836 static int
xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,const xmlChar * lname,const xmlChar * nsname)21837 xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,
21838 		       const xmlChar* lname,
21839 		       const xmlChar* nsname)
21840 {
21841     int i;
21842 
21843     lname = xmlDictLookup(vctxt->dict, lname, -1);
21844     if (lname == NULL)
21845 	return(-1);
21846     if (nsname != NULL) {
21847 	nsname = xmlDictLookup(vctxt->dict, nsname, -1);
21848 	if (nsname == NULL)
21849 	    return(-1);
21850     }
21851     for (i = 0; i < vctxt->nodeQNames->nbItems; i += 2) {
21852 	if ((vctxt->nodeQNames->items [i] == lname) &&
21853 	    (vctxt->nodeQNames->items[i +1] == nsname))
21854 	    /* Already there */
21855 	    return(i);
21856     }
21857     /* Add new entry. */
21858     i = vctxt->nodeQNames->nbItems;
21859     xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) lname);
21860     xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) nsname);
21861     return(i);
21862 }
21863 
21864 /************************************************************************
21865  * 									*
21866  *  Validation of identity-constraints (IDC)                            *
21867  * 									*
21868  ************************************************************************/
21869 
21870 /**
21871  * xmlSchemaAugmentIDC:
21872  * @idcDef: the IDC definition
21873  *
21874  * Creates an augmented IDC definition item.
21875  *
21876  * Returns the item, or NULL on internal errors.
21877  */
21878 static void
xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,xmlSchemaValidCtxtPtr vctxt)21879 xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
21880 		    xmlSchemaValidCtxtPtr vctxt)
21881 {
21882     xmlSchemaIDCAugPtr aidc;
21883 
21884     aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
21885     if (aidc == NULL) {
21886 	xmlSchemaVErrMemory(vctxt,
21887 	    "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
21888 	    NULL);
21889 	return;
21890     }
21891     aidc->keyrefDepth = -1;
21892     aidc->def = idcDef;
21893     aidc->next = NULL;
21894     if (vctxt->aidcs == NULL)
21895 	vctxt->aidcs = aidc;
21896     else {
21897 	aidc->next = vctxt->aidcs;
21898 	vctxt->aidcs = aidc;
21899     }
21900     /*
21901     * Save if we have keyrefs at all.
21902     */
21903     if ((vctxt->hasKeyrefs == 0) &&
21904 	(idcDef->type == XML_SCHEMA_TYPE_IDC_KEYREF))
21905 	vctxt->hasKeyrefs = 1;
21906 }
21907 
21908 /**
21909  * xmlSchemaAugmentImportedIDC:
21910  * @imported: the imported schema
21911  *
21912  * Creates an augmented IDC definition for the imported schema.
21913  */
21914 static void
xmlSchemaAugmentImportedIDC(xmlSchemaImportPtr imported,xmlSchemaValidCtxtPtr vctxt)21915 xmlSchemaAugmentImportedIDC(xmlSchemaImportPtr imported, xmlSchemaValidCtxtPtr vctxt) {
21916     if (imported->schema->idcDef != NULL) {
21917 	    xmlHashScan(imported->schema->idcDef ,
21918 	    (xmlHashScanner) xmlSchemaAugmentIDC, vctxt);
21919     }
21920 }
21921 
21922 /**
21923  * xmlSchemaIDCNewBinding:
21924  * @idcDef: the IDC definition of this binding
21925  *
21926  * Creates a new IDC binding.
21927  *
21928  * Returns the new IDC binding, NULL on internal errors.
21929  */
21930 static xmlSchemaPSVIIDCBindingPtr
xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)21931 xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
21932 {
21933     xmlSchemaPSVIIDCBindingPtr ret;
21934 
21935     ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
21936 	    sizeof(xmlSchemaPSVIIDCBinding));
21937     if (ret == NULL) {
21938 	xmlSchemaVErrMemory(NULL,
21939 	    "allocating a PSVI IDC binding item", NULL);
21940 	return (NULL);
21941     }
21942     memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
21943     ret->definition = idcDef;
21944     return (ret);
21945 }
21946 
21947 /**
21948  * xmlSchemaIDCStoreNodeTableItem:
21949  * @vctxt: the WXS validation context
21950  * @item: the IDC node table item
21951  *
21952  * The validation context is used to store IDC node table items.
21953  * They are stored to avoid copying them if IDC node-tables are merged
21954  * with corresponding parent IDC node-tables (bubbling).
21955  *
21956  * Returns 0 if succeeded, -1 on internal errors.
21957  */
21958 static int
xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,xmlSchemaPSVIIDCNodePtr item)21959 xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
21960 			       xmlSchemaPSVIIDCNodePtr item)
21961 {
21962     /*
21963     * Add to gobal list.
21964     */
21965     if (vctxt->idcNodes == NULL) {
21966 	vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
21967 	    xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
21968 	if (vctxt->idcNodes == NULL) {
21969 	    xmlSchemaVErrMemory(vctxt,
21970 		"allocating the IDC node table item list", NULL);
21971 	    return (-1);
21972 	}
21973 	vctxt->sizeIdcNodes = 20;
21974     } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
21975 	vctxt->sizeIdcNodes *= 2;
21976 	vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
21977 	    xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
21978 	    sizeof(xmlSchemaPSVIIDCNodePtr));
21979 	if (vctxt->idcNodes == NULL) {
21980 	    xmlSchemaVErrMemory(vctxt,
21981 		"re-allocating the IDC node table item list", NULL);
21982 	    return (-1);
21983 	}
21984     }
21985     vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
21986 
21987     return (0);
21988 }
21989 
21990 /**
21991  * xmlSchemaIDCStoreKey:
21992  * @vctxt: the WXS validation context
21993  * @item: the IDC key
21994  *
21995  * The validation context is used to store an IDC key.
21996  *
21997  * Returns 0 if succeeded, -1 on internal errors.
21998  */
21999 static int
xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,xmlSchemaPSVIIDCKeyPtr key)22000 xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
22001 		     xmlSchemaPSVIIDCKeyPtr key)
22002 {
22003     /*
22004     * Add to gobal list.
22005     */
22006     if (vctxt->idcKeys == NULL) {
22007 	vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22008 	    xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
22009 	if (vctxt->idcKeys == NULL) {
22010 	    xmlSchemaVErrMemory(vctxt,
22011 		"allocating the IDC key storage list", NULL);
22012 	    return (-1);
22013 	}
22014 	vctxt->sizeIdcKeys = 40;
22015     } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
22016 	vctxt->sizeIdcKeys *= 2;
22017 	vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22018 	    xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
22019 	    sizeof(xmlSchemaPSVIIDCKeyPtr));
22020 	if (vctxt->idcKeys == NULL) {
22021 	    xmlSchemaVErrMemory(vctxt,
22022 		"re-allocating the IDC key storage list", NULL);
22023 	    return (-1);
22024 	}
22025     }
22026     vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
22027 
22028     return (0);
22029 }
22030 
22031 /**
22032  * xmlSchemaIDCAppendNodeTableItem:
22033  * @bind: the IDC binding
22034  * @ntItem: the node-table item
22035  *
22036  * Appends the IDC node-table item to the binding.
22037  *
22038  * Returns 0 on success and -1 on internal errors.
22039  */
22040 static int
xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,xmlSchemaPSVIIDCNodePtr ntItem)22041 xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
22042 				xmlSchemaPSVIIDCNodePtr ntItem)
22043 {
22044     if (bind->nodeTable == NULL) {
22045 	bind->sizeNodes = 10;
22046 	bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22047 	    xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
22048 	if (bind->nodeTable == NULL) {
22049 	    xmlSchemaVErrMemory(NULL,
22050 		"allocating an array of IDC node-table items", NULL);
22051 	    return(-1);
22052 	}
22053     } else if (bind->sizeNodes <= bind->nbNodes) {
22054 	bind->sizeNodes *= 2;
22055 	bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22056 	    xmlRealloc(bind->nodeTable, bind->sizeNodes *
22057 		sizeof(xmlSchemaPSVIIDCNodePtr));
22058 	if (bind->nodeTable == NULL) {
22059 	    xmlSchemaVErrMemory(NULL,
22060 		"re-allocating an array of IDC node-table items", NULL);
22061 	    return(-1);
22062 	}
22063     }
22064     bind->nodeTable[bind->nbNodes++] = ntItem;
22065     return(0);
22066 }
22067 
22068 /**
22069  * xmlSchemaIDCAcquireBinding:
22070  * @vctxt: the WXS validation context
22071  * @matcher: the IDC matcher
22072  *
22073  * Looks up an PSVI IDC binding, for the IDC definition and
22074  * of the given matcher. If none found, a new one is created
22075  * and added to the IDC table.
22076  *
22077  * Returns an IDC binding or NULL on internal errors.
22078  */
22079 static xmlSchemaPSVIIDCBindingPtr
xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,xmlSchemaIDCMatcherPtr matcher)22080 xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,
22081 			  xmlSchemaIDCMatcherPtr matcher)
22082 {
22083     xmlSchemaNodeInfoPtr ielem;
22084 
22085     ielem = vctxt->elemInfos[matcher->depth];
22086 
22087     if (ielem->idcTable == NULL) {
22088 	ielem->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
22089 	if (ielem->idcTable == NULL)
22090 	    return (NULL);
22091 	return(ielem->idcTable);
22092     } else {
22093 	xmlSchemaPSVIIDCBindingPtr bind = NULL;
22094 
22095 	bind = ielem->idcTable;
22096 	do {
22097 	    if (bind->definition == matcher->aidc->def)
22098 		return(bind);
22099 	    if (bind->next == NULL) {
22100 		bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
22101 		if (bind->next == NULL)
22102 		    return (NULL);
22103 		return(bind->next);
22104 	    }
22105 	    bind = bind->next;
22106 	} while (bind != NULL);
22107     }
22108     return (NULL);
22109 }
22110 
22111 static xmlSchemaItemListPtr
xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,xmlSchemaIDCMatcherPtr matcher)22112 xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
22113 			     xmlSchemaIDCMatcherPtr matcher)
22114 {
22115     if (matcher->targets == NULL)
22116 	matcher->targets = xmlSchemaItemListCreate();
22117     return(matcher->targets);
22118 }
22119 
22120 /**
22121  * xmlSchemaIDCFreeKey:
22122  * @key: the IDC key
22123  *
22124  * Frees an IDC key together with its compiled value.
22125  */
22126 static void
xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)22127 xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
22128 {
22129     if (key->val != NULL)
22130 	xmlSchemaFreeValue(key->val);
22131     xmlFree(key);
22132 }
22133 
22134 /**
22135  * xmlSchemaIDCFreeBinding:
22136  *
22137  * Frees an IDC binding. Note that the node table-items
22138  * are not freed.
22139  */
22140 static void
xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)22141 xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
22142 {
22143     if (bind->nodeTable != NULL)
22144 	xmlFree(bind->nodeTable);
22145     if (bind->dupls != NULL)
22146 	xmlSchemaItemListFree(bind->dupls);
22147     xmlFree(bind);
22148 }
22149 
22150 /**
22151  * xmlSchemaIDCFreeIDCTable:
22152  * @bind: the first IDC binding in the list
22153  *
22154  * Frees an IDC table, i.e. all the IDC bindings in the list.
22155  */
22156 static void
xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)22157 xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
22158 {
22159     xmlSchemaPSVIIDCBindingPtr prev;
22160 
22161     while (bind != NULL) {
22162 	prev = bind;
22163 	bind = bind->next;
22164 	xmlSchemaIDCFreeBinding(prev);
22165     }
22166 }
22167 
22168 /**
22169  * xmlSchemaIDCFreeMatcherList:
22170  * @matcher: the first IDC matcher in the list
22171  *
22172  * Frees a list of IDC matchers.
22173  */
22174 static void
xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)22175 xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
22176 {
22177     xmlSchemaIDCMatcherPtr next;
22178 
22179     while (matcher != NULL) {
22180 	next = matcher->next;
22181 	if (matcher->keySeqs != NULL) {
22182 	    int i;
22183 	    for (i = 0; i < matcher->sizeKeySeqs; i++)
22184 		if (matcher->keySeqs[i] != NULL)
22185 		    xmlFree(matcher->keySeqs[i]);
22186 	    xmlFree(matcher->keySeqs);
22187 	}
22188 	if (matcher->targets != NULL) {
22189 	    if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22190 		int i;
22191 		xmlSchemaPSVIIDCNodePtr idcNode;
22192 		/*
22193 		* Node-table items for keyrefs are not stored globally
22194 		* to the validation context, since they are not bubbled.
22195 		* We need to free them here.
22196 		*/
22197 		for (i = 0; i < matcher->targets->nbItems; i++) {
22198 		    idcNode =
22199 			(xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22200 		    xmlFree(idcNode->keys);
22201 		    xmlFree(idcNode);
22202 		}
22203 	    }
22204 	    xmlSchemaItemListFree(matcher->targets);
22205 	}
22206 	xmlFree(matcher);
22207 	matcher = next;
22208     }
22209 }
22210 
22211 /**
22212  * xmlSchemaIDCReleaseMatcherList:
22213  * @vctxt: the WXS validation context
22214  * @matcher: the first IDC matcher in the list
22215  *
22216  * Caches a list of IDC matchers for reuse.
22217  */
22218 static void
xmlSchemaIDCReleaseMatcherList(xmlSchemaValidCtxtPtr vctxt,xmlSchemaIDCMatcherPtr matcher)22219 xmlSchemaIDCReleaseMatcherList(xmlSchemaValidCtxtPtr vctxt,
22220 			       xmlSchemaIDCMatcherPtr matcher)
22221 {
22222     xmlSchemaIDCMatcherPtr next;
22223 
22224     while (matcher != NULL) {
22225 	next = matcher->next;
22226 	if (matcher->keySeqs != NULL) {
22227 	    int i;
22228 	    /*
22229 	    * Don't free the array, but only the content.
22230 	    */
22231 	    for (i = 0; i < matcher->sizeKeySeqs; i++)
22232 		if (matcher->keySeqs[i] != NULL) {
22233 		    xmlFree(matcher->keySeqs[i]);
22234 		    matcher->keySeqs[i] = NULL;
22235 		}
22236 	}
22237 	if (matcher->targets) {
22238 	    if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22239 		int i;
22240 		xmlSchemaPSVIIDCNodePtr idcNode;
22241 		/*
22242 		* Node-table items for keyrefs are not stored globally
22243 		* to the validation context, since they are not bubbled.
22244 		* We need to free them here.
22245 		*/
22246 		for (i = 0; i < matcher->targets->nbItems; i++) {
22247 		    idcNode =
22248 			(xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22249 		    xmlFree(idcNode->keys);
22250 		    xmlFree(idcNode);
22251 		}
22252 	    }
22253 	    xmlSchemaItemListFree(matcher->targets);
22254 	    matcher->targets = NULL;
22255 	}
22256 	matcher->next = NULL;
22257 	/*
22258 	* Cache the matcher.
22259 	*/
22260 	if (vctxt->idcMatcherCache != NULL)
22261 	    matcher->nextCached = vctxt->idcMatcherCache;
22262 	vctxt->idcMatcherCache = matcher;
22263 
22264 	matcher = next;
22265     }
22266 }
22267 
22268 /**
22269  * xmlSchemaIDCAddStateObject:
22270  * @vctxt: the WXS validation context
22271  * @matcher: the IDC matcher
22272  * @sel: the XPath information
22273  * @parent: the parent "selector" state object if any
22274  * @type: "selector" or "field"
22275  *
22276  * Creates/reuses and activates state objects for the given
22277  * XPath information; if the XPath expression consists of unions,
22278  * multiple state objects are created for every unioned expression.
22279  *
22280  * Returns 0 on success and -1 on internal errors.
22281  */
22282 static int
xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,xmlSchemaIDCMatcherPtr matcher,xmlSchemaIDCSelectPtr sel,int type)22283 xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
22284 			xmlSchemaIDCMatcherPtr matcher,
22285 			xmlSchemaIDCSelectPtr sel,
22286 			int type)
22287 {
22288     xmlSchemaIDCStateObjPtr sto;
22289 
22290     /*
22291     * Reuse the state objects from the pool.
22292     */
22293     if (vctxt->xpathStatePool != NULL) {
22294 	sto = vctxt->xpathStatePool;
22295 	vctxt->xpathStatePool = sto->next;
22296 	sto->next = NULL;
22297     } else {
22298 	/*
22299 	* Create a new state object.
22300 	*/
22301 	sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
22302 	if (sto == NULL) {
22303 	    xmlSchemaVErrMemory(NULL,
22304 		"allocating an IDC state object", NULL);
22305 	    return (-1);
22306 	}
22307 	memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
22308     }
22309     /*
22310     * Add to global list.
22311     */
22312     if (vctxt->xpathStates != NULL)
22313 	sto->next = vctxt->xpathStates;
22314     vctxt->xpathStates = sto;
22315 
22316     /*
22317     * Free the old xpath validation context.
22318     */
22319     if (sto->xpathCtxt != NULL)
22320 	xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
22321 
22322     /*
22323     * Create a new XPath (pattern) validation context.
22324     */
22325     sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
22326 	(xmlPatternPtr) sel->xpathComp);
22327     if (sto->xpathCtxt == NULL) {
22328 	VERROR_INT("xmlSchemaIDCAddStateObject",
22329 	    "failed to create an XPath validation context");
22330 	return (-1);
22331     }
22332     sto->type = type;
22333     sto->depth = vctxt->depth;
22334     sto->matcher = matcher;
22335     sto->sel = sel;
22336     sto->nbHistory = 0;
22337 
22338 #ifdef DEBUG_IDC
22339     xmlGenericError(xmlGenericErrorContext, "IDC:   STO push '%s'\n",
22340 	sto->sel->xpath);
22341 #endif
22342     return (0);
22343 }
22344 
22345 /**
22346  * xmlSchemaXPathEvaluate:
22347  * @vctxt: the WXS validation context
22348  * @nodeType: the nodeType of the current node
22349  *
22350  * Evaluates all active XPath state objects.
22351  *
22352  * Returns the number of IC "field" state objects which resolved to
22353  * this node, 0 if none resolved and -1 on internal errors.
22354  */
22355 static int
xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,xmlElementType nodeType)22356 xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
22357 		       xmlElementType nodeType)
22358 {
22359     xmlSchemaIDCStateObjPtr sto, head = NULL, first;
22360     int res, resolved = 0, depth = vctxt->depth;
22361 
22362     if (vctxt->xpathStates == NULL)
22363 	return (0);
22364 
22365     if (nodeType == XML_ATTRIBUTE_NODE)
22366 	depth++;
22367 #ifdef DEBUG_IDC
22368     {
22369 	xmlChar *str = NULL;
22370 	xmlGenericError(xmlGenericErrorContext,
22371 	    "IDC: EVAL on %s, depth %d, type %d\n",
22372 	    xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22373 		vctxt->inode->localName), depth, nodeType);
22374 	FREE_AND_NULL(str)
22375     }
22376 #endif
22377     /*
22378     * Process all active XPath state objects.
22379     */
22380     first = vctxt->xpathStates;
22381     sto = first;
22382     while (sto != head) {
22383 #ifdef DEBUG_IDC
22384 	if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
22385 	    xmlGenericError(xmlGenericErrorContext, "IDC:   ['%s'] selector '%s'\n",
22386 		sto->matcher->aidc->def->name, sto->sel->xpath);
22387 	else
22388 	    xmlGenericError(xmlGenericErrorContext, "IDC:   ['%s'] field '%s'\n",
22389 		sto->matcher->aidc->def->name, sto->sel->xpath);
22390 #endif
22391 	if (nodeType == XML_ELEMENT_NODE)
22392 	    res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
22393 		vctxt->inode->localName, vctxt->inode->nsName);
22394 	else
22395 	    res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
22396 		vctxt->inode->localName, vctxt->inode->nsName);
22397 
22398 	if (res == -1) {
22399 	    VERROR_INT("xmlSchemaXPathEvaluate",
22400 		"calling xmlStreamPush()");
22401 	    return (-1);
22402 	}
22403 	if (res == 0)
22404 	    goto next_sto;
22405 	/*
22406 	* Full match.
22407 	*/
22408 #ifdef DEBUG_IDC
22409 	xmlGenericError(xmlGenericErrorContext, "IDC:     "
22410 	    "MATCH\n");
22411 #endif
22412 	/*
22413 	* Register a match in the state object history.
22414 	*/
22415 	if (sto->history == NULL) {
22416 	    sto->history = (int *) xmlMalloc(5 * sizeof(int));
22417 	    if (sto->history == NULL) {
22418 		xmlSchemaVErrMemory(NULL,
22419 		    "allocating the state object history", NULL);
22420 		return(-1);
22421 	    }
22422 	    sto->sizeHistory = 5;
22423 	} else if (sto->sizeHistory <= sto->nbHistory) {
22424 	    sto->sizeHistory *= 2;
22425 	    sto->history = (int *) xmlRealloc(sto->history,
22426 		sto->sizeHistory * sizeof(int));
22427 	    if (sto->history == NULL) {
22428 		xmlSchemaVErrMemory(NULL,
22429 		    "re-allocating the state object history", NULL);
22430 		return(-1);
22431 	    }
22432 	}
22433 	sto->history[sto->nbHistory++] = depth;
22434 
22435 #ifdef DEBUG_IDC
22436 	xmlGenericError(xmlGenericErrorContext, "IDC:       push match '%d'\n",
22437 	    vctxt->depth);
22438 #endif
22439 
22440 	if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22441 	    xmlSchemaIDCSelectPtr sel;
22442 	    /*
22443 	    * Activate state objects for the IDC fields of
22444 	    * the IDC selector.
22445 	    */
22446 #ifdef DEBUG_IDC
22447 	    xmlGenericError(xmlGenericErrorContext, "IDC:     "
22448 		"activating field states\n");
22449 #endif
22450 	    sel = sto->matcher->aidc->def->fields;
22451 	    while (sel != NULL) {
22452 		if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
22453 		    sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
22454 		    return (-1);
22455 		sel = sel->next;
22456 	    }
22457 	} else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22458 	    /*
22459 	    * An IDC key node was found by the IDC field.
22460 	    */
22461 #ifdef DEBUG_IDC
22462 	    xmlGenericError(xmlGenericErrorContext,
22463 		"IDC:     key found\n");
22464 #endif
22465 	    /*
22466 	    * Notify that the character value of this node is
22467 	    * needed.
22468 	    */
22469 	    if (resolved == 0) {
22470 		if ((vctxt->inode->flags &
22471 		    XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
22472 		vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
22473 	    }
22474 	    resolved++;
22475 	}
22476 next_sto:
22477 	if (sto->next == NULL) {
22478 	    /*
22479 	    * Evaluate field state objects created on this node as well.
22480 	    */
22481 	    head = first;
22482 	    sto = vctxt->xpathStates;
22483 	} else
22484 	    sto = sto->next;
22485     }
22486     return (resolved);
22487 }
22488 
22489 static const xmlChar *
xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,xmlChar ** buf,xmlSchemaPSVIIDCKeyPtr * seq,int count)22490 xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
22491 			      xmlChar **buf,
22492 			      xmlSchemaPSVIIDCKeyPtr *seq,
22493 			      int count)
22494 {
22495     int i, res;
22496     xmlChar *value = NULL;
22497 
22498     *buf = xmlStrdup(BAD_CAST "[");
22499     for (i = 0; i < count; i++) {
22500 	*buf = xmlStrcat(*buf, BAD_CAST "'");
22501 	res = xmlSchemaGetCanonValueWhtspExt(seq[i]->val,
22502 	    xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type),
22503 	    &value);
22504 	if (res == 0)
22505 	    *buf = xmlStrcat(*buf, BAD_CAST value);
22506 	else {
22507 	    VERROR_INT("xmlSchemaFormatIDCKeySequence",
22508 		"failed to compute a canonical value");
22509 	    *buf = xmlStrcat(*buf, BAD_CAST "???");
22510 	}
22511 	if (i < count -1)
22512 	    *buf = xmlStrcat(*buf, BAD_CAST "', ");
22513 	else
22514 	    *buf = xmlStrcat(*buf, BAD_CAST "'");
22515 	if (value != NULL) {
22516 	    xmlFree(value);
22517 	    value = NULL;
22518 	}
22519     }
22520     *buf = xmlStrcat(*buf, BAD_CAST "]");
22521 
22522     return (BAD_CAST *buf);
22523 }
22524 
22525 /**
22526  * xmlSchemaXPathPop:
22527  * @vctxt: the WXS validation context
22528  *
22529  * Pops all XPath states.
22530  *
22531  * Returns 0 on success and -1 on internal errors.
22532  */
22533 static int
xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)22534 xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)
22535 {
22536     xmlSchemaIDCStateObjPtr sto;
22537     int res;
22538 
22539     if (vctxt->xpathStates == NULL)
22540 	return(0);
22541     sto = vctxt->xpathStates;
22542     do {
22543 	res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22544 	if (res == -1)
22545 	    return (-1);
22546 	sto = sto->next;
22547     } while (sto != NULL);
22548     return(0);
22549 }
22550 
22551 /**
22552  * xmlSchemaXPathProcessHistory:
22553  * @vctxt: the WXS validation context
22554  * @type: the simple/complex type of the current node if any at all
22555  * @val: the precompiled value
22556  *
22557  * Processes and pops the history items of the IDC state objects.
22558  * IDC key-sequences are validated/created on IDC bindings.
22559  *
22560  * Returns 0 on success and -1 on internal errors.
22561  */
22562 static int
xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,int depth)22563 xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
22564 			     int depth)
22565 {
22566     xmlSchemaIDCStateObjPtr sto, nextsto;
22567     int res, matchDepth;
22568     xmlSchemaPSVIIDCKeyPtr key = NULL;
22569     xmlSchemaTypePtr type = vctxt->inode->typeDef, simpleType = NULL;
22570 
22571     if (vctxt->xpathStates == NULL)
22572 	return (0);
22573     sto = vctxt->xpathStates;
22574 
22575 #ifdef DEBUG_IDC
22576     {
22577 	xmlChar *str = NULL;
22578 	xmlGenericError(xmlGenericErrorContext,
22579 	    "IDC: BACK on %s, depth %d\n",
22580 	    xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22581 		vctxt->inode->localName), vctxt->depth);
22582 	FREE_AND_NULL(str)
22583     }
22584 #endif
22585     /*
22586     * Evaluate the state objects.
22587     */
22588     while (sto != NULL) {
22589 	res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22590 	if (res == -1) {
22591 	    VERROR_INT("xmlSchemaXPathProcessHistory",
22592 		"calling xmlStreamPop()");
22593 	    return (-1);
22594 	}
22595 #ifdef DEBUG_IDC
22596 	xmlGenericError(xmlGenericErrorContext, "IDC:   stream pop '%s'\n",
22597 	    sto->sel->xpath);
22598 #endif
22599 	if (sto->nbHistory == 0)
22600 	    goto deregister_check;
22601 
22602 	matchDepth = sto->history[sto->nbHistory -1];
22603 
22604 	/*
22605 	* Only matches at the current depth are of interest.
22606 	*/
22607 	if (matchDepth != depth) {
22608 	    sto = sto->next;
22609 	    continue;
22610 	}
22611 	if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22612 	    /*
22613 	    * NOTE: According to
22614 	    *   http://www.w3.org/Bugs/Public/show_bug.cgi?id=2198
22615 	    *   ... the simple-content of complex types is also allowed.
22616 	    */
22617 
22618 	    if (WXS_IS_COMPLEX(type)) {
22619 		if (WXS_HAS_SIMPLE_CONTENT(type)) {
22620 		    /*
22621 		    * Sanity check for complex types with simple content.
22622 		    */
22623 		    simpleType = type->contentTypeDef;
22624 		    if (simpleType == NULL) {
22625 			VERROR_INT("xmlSchemaXPathProcessHistory",
22626 			    "field resolves to a CT with simple content "
22627 			    "but the CT is missing the ST definition");
22628 			return (-1);
22629 		    }
22630 		} else
22631 		    simpleType = NULL;
22632 	    } else
22633 		simpleType = type;
22634 	    if (simpleType == NULL) {
22635 		xmlChar *str = NULL;
22636 
22637 		/*
22638 		* Not qualified if the field resolves to a node of non
22639 		* simple type.
22640 		*/
22641 		xmlSchemaCustomErr(ACTXT_CAST vctxt,
22642 		    XML_SCHEMAV_CVC_IDC, NULL,
22643 		    WXS_BASIC_CAST sto->matcher->aidc->def,
22644 		    "The XPath '%s' of a field of %s does evaluate to a node of "
22645 		    "non-simple type",
22646 		    sto->sel->xpath,
22647 		    xmlSchemaGetIDCDesignation(&str, sto->matcher->aidc->def));
22648 		FREE_AND_NULL(str);
22649 		sto->nbHistory--;
22650 		goto deregister_check;
22651 	    }
22652 
22653 	    if ((key == NULL) && (vctxt->inode->val == NULL)) {
22654 		/*
22655 		* Failed to provide the normalized value; maybe
22656 		* the value was invalid.
22657 		*/
22658 		VERROR(XML_SCHEMAV_CVC_IDC,
22659 		    WXS_BASIC_CAST sto->matcher->aidc->def,
22660 		    "Warning: No precomputed value available, the value "
22661 		    "was either invalid or something strange happend");
22662 		sto->nbHistory--;
22663 		goto deregister_check;
22664 	    } else {
22665 		xmlSchemaIDCMatcherPtr matcher = sto->matcher;
22666 		xmlSchemaPSVIIDCKeyPtr *keySeq;
22667 		int pos, idx;
22668 
22669 		/*
22670 		* The key will be anchored on the matcher's list of
22671 		* key-sequences. The position in this list is determined
22672 		* by the target node's depth relative to the matcher's
22673 		* depth of creation (i.e. the depth of the scope element).
22674 		*
22675 		* Element        Depth    Pos   List-entries
22676 		* <scope>          0              NULL
22677 		*   <bar>          1              NULL
22678 		*     <target/>    2       2      target
22679 		*   <bar>
22680                 * </scope>
22681 		*
22682 		* The size of the list is only dependant on the depth of
22683 		* the tree.
22684 		* An entry will be NULLed in selector_leave, i.e. when
22685 		* we hit the target's
22686 		*/
22687 		pos = sto->depth - matcher->depth;
22688 		idx = sto->sel->index;
22689 
22690 		/*
22691 		* Create/grow the array of key-sequences.
22692 		*/
22693 		if (matcher->keySeqs == NULL) {
22694 		    if (pos > 9)
22695 			matcher->sizeKeySeqs = pos * 2;
22696 		    else
22697 			matcher->sizeKeySeqs = 10;
22698 		    matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22699 			xmlMalloc(matcher->sizeKeySeqs *
22700 			sizeof(xmlSchemaPSVIIDCKeyPtr *));
22701 		    if (matcher->keySeqs == NULL) {
22702 			xmlSchemaVErrMemory(NULL,
22703 			    "allocating an array of key-sequences",
22704 			    NULL);
22705 			return(-1);
22706 		    }
22707 		    memset(matcher->keySeqs, 0,
22708 			matcher->sizeKeySeqs *
22709 			sizeof(xmlSchemaPSVIIDCKeyPtr *));
22710 		} else if (pos >= matcher->sizeKeySeqs) {
22711 		    int i = matcher->sizeKeySeqs;
22712 
22713 		    matcher->sizeKeySeqs *= 2;
22714 		    matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22715 			xmlRealloc(matcher->keySeqs,
22716 			matcher->sizeKeySeqs *
22717 			sizeof(xmlSchemaPSVIIDCKeyPtr *));
22718 		    if (matcher->keySeqs == NULL) {
22719 			xmlSchemaVErrMemory(NULL,
22720 			    "reallocating an array of key-sequences",
22721 			    NULL);
22722 			return (-1);
22723 		    }
22724 		    /*
22725 		    * The array needs to be NULLed.
22726 		    * TODO: Use memset?
22727 		    */
22728 		    for (; i < matcher->sizeKeySeqs; i++)
22729 			matcher->keySeqs[i] = NULL;
22730 		}
22731 
22732 		/*
22733 		* Get/create the key-sequence.
22734 		*/
22735 		keySeq = matcher->keySeqs[pos];
22736 		if (keySeq == NULL) {
22737 		    goto create_sequence;
22738 		} else if (keySeq[idx] != NULL) {
22739 		    xmlChar *str = NULL;
22740 		    /*
22741 		    * cvc-identity-constraint:
22742 		    * 3 For each node in the �target node set� all
22743 		    * of the {fields}, with that node as the context
22744 		    * node, evaluate to either an empty node-set or
22745 		    * a node-set with exactly one member, which must
22746 		    * have a simple type.
22747 		    *
22748 		    * The key was already set; report an error.
22749 		    */
22750 		    xmlSchemaCustomErr(ACTXT_CAST vctxt,
22751 			XML_SCHEMAV_CVC_IDC, NULL,
22752 			WXS_BASIC_CAST matcher->aidc->def,
22753 			"The XPath '%s' of a field of %s evaluates to a "
22754 			"node-set with more than one member",
22755 			sto->sel->xpath,
22756 			xmlSchemaGetIDCDesignation(&str, matcher->aidc->def));
22757 		    FREE_AND_NULL(str);
22758 		    sto->nbHistory--;
22759 		    goto deregister_check;
22760 		} else
22761 		    goto create_key;
22762 
22763 create_sequence:
22764 		/*
22765 		* Create a key-sequence.
22766 		*/
22767 		keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
22768 		    matcher->aidc->def->nbFields *
22769 		    sizeof(xmlSchemaPSVIIDCKeyPtr));
22770 		if (keySeq == NULL) {
22771 		    xmlSchemaVErrMemory(NULL,
22772 			"allocating an IDC key-sequence", NULL);
22773 		    return(-1);
22774 		}
22775 		memset(keySeq, 0, matcher->aidc->def->nbFields *
22776 		    sizeof(xmlSchemaPSVIIDCKeyPtr));
22777 		matcher->keySeqs[pos] = keySeq;
22778 create_key:
22779 		/*
22780 		* Create a key once per node only.
22781 		*/
22782 		if (key == NULL) {
22783 		    key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
22784 			sizeof(xmlSchemaPSVIIDCKey));
22785 		    if (key == NULL) {
22786 			xmlSchemaVErrMemory(NULL,
22787 			    "allocating a IDC key", NULL);
22788 			xmlFree(keySeq);
22789 			matcher->keySeqs[pos] = NULL;
22790 			return(-1);
22791 		    }
22792 		    /*
22793 		    * Consume the compiled value.
22794 		    */
22795 		    key->type = simpleType;
22796 		    key->val = vctxt->inode->val;
22797 		    vctxt->inode->val = NULL;
22798 		    /*
22799 		    * Store the key in a global list.
22800 		    */
22801 		    if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
22802 			xmlSchemaIDCFreeKey(key);
22803 			return (-1);
22804 		    }
22805 		}
22806 		keySeq[idx] = key;
22807 	    }
22808 	} else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22809 
22810 	    xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
22811 	    /* xmlSchemaPSVIIDCBindingPtr bind; */
22812 	    xmlSchemaPSVIIDCNodePtr ntItem;
22813 	    xmlSchemaIDCMatcherPtr matcher;
22814 	    xmlSchemaIDCPtr idc;
22815 	    xmlSchemaItemListPtr targets;
22816 	    int pos, i, j, nbKeys;
22817 	    /*
22818 	    * Here we have the following scenario:
22819 	    * An IDC 'selector' state object resolved to a target node,
22820 	    * during the time this target node was in the
22821 	    * ancestor-or-self axis, the 'field' state object(s) looked
22822 	    * out for matching nodes to create a key-sequence for this
22823 	    * target node. Now we are back to this target node and need
22824 	    * to put the key-sequence, together with the target node
22825 	    * itself, into the node-table of the corresponding IDC
22826 	    * binding.
22827 	    */
22828 	    matcher = sto->matcher;
22829 	    idc = matcher->aidc->def;
22830 	    nbKeys = idc->nbFields;
22831 	    pos = depth - matcher->depth;
22832 	    /*
22833 	    * Check if the matcher has any key-sequences at all, plus
22834 	    * if it has a key-sequence for the current target node.
22835 	    */
22836 	    if ((matcher->keySeqs == NULL) ||
22837 		(matcher->sizeKeySeqs <= pos)) {
22838 		if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22839 		    goto selector_key_error;
22840 		else
22841 		    goto selector_leave;
22842 	    }
22843 
22844 	    keySeq = &(matcher->keySeqs[pos]);
22845 	    if (*keySeq == NULL) {
22846 		if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22847 		    goto selector_key_error;
22848 		else
22849 		    goto selector_leave;
22850 	    }
22851 
22852 	    for (i = 0; i < nbKeys; i++) {
22853 		if ((*keySeq)[i] == NULL) {
22854 		    /*
22855 		    * Not qualified, if not all fields did resolve.
22856 		    */
22857 		    if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
22858 			/*
22859 			* All fields of a "key" IDC must resolve.
22860 			*/
22861 			goto selector_key_error;
22862 		    }
22863 		    goto selector_leave;
22864 		}
22865 	    }
22866 	    /*
22867 	    * All fields did resolve.
22868 	    */
22869 
22870 	    /*
22871 	    * 4.1 If the {identity-constraint category} is unique(/key),
22872 	    * then no two members of the �qualified node set� have
22873 	    * �key-sequences� whose members are pairwise equal, as
22874 	    * defined by Equal in [XML Schemas: Datatypes].
22875 	    *
22876 	    * Get the IDC binding from the matcher and check for
22877 	    * duplicate key-sequences.
22878 	    */
22879 #if 0
22880 	    bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
22881 #endif
22882 	    targets = xmlSchemaIDCAcquireTargetList(vctxt, matcher);
22883 	    if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
22884 		(targets->nbItems != 0)) {
22885 		xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
22886 
22887 		i = 0;
22888 		res = 0;
22889 		/*
22890 		* Compare the key-sequences, key by key.
22891 		*/
22892 		do {
22893 		    bkeySeq =
22894 			((xmlSchemaPSVIIDCNodePtr) targets->items[i])->keys;
22895 		    for (j = 0; j < nbKeys; j++) {
22896 			ckey = (*keySeq)[j];
22897 			bkey = bkeySeq[j];
22898 			res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
22899 			if (res == -1) {
22900 			    return (-1);
22901 			} else if (res == 0) {
22902 			    /*
22903 			    * One of the keys differs, so the key-sequence
22904 			    * won't be equal; get out.
22905 			    */
22906 			    break;
22907 			}
22908 		    }
22909 		    if (res == 1) {
22910 			/*
22911 			* Duplicate key-sequence found.
22912 			*/
22913 			break;
22914 		    }
22915 		    i++;
22916 		} while (i < targets->nbItems);
22917 		if (i != targets->nbItems) {
22918 		    xmlChar *str = NULL, *strB = NULL;
22919 		    /*
22920 		    * TODO: Try to report the key-sequence.
22921 		    */
22922 		    xmlSchemaCustomErr(ACTXT_CAST vctxt,
22923 			XML_SCHEMAV_CVC_IDC, NULL,
22924 			WXS_BASIC_CAST idc,
22925 			"Duplicate key-sequence %s in %s",
22926 			xmlSchemaFormatIDCKeySequence(vctxt, &str,
22927 			    (*keySeq), nbKeys),
22928 			xmlSchemaGetIDCDesignation(&strB, idc));
22929 		    FREE_AND_NULL(str);
22930 		    FREE_AND_NULL(strB);
22931 		    goto selector_leave;
22932 		}
22933 	    }
22934 	    /*
22935 	    * Add a node-table item to the IDC binding.
22936 	    */
22937 	    ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
22938 		sizeof(xmlSchemaPSVIIDCNode));
22939 	    if (ntItem == NULL) {
22940 		xmlSchemaVErrMemory(NULL,
22941 		    "allocating an IDC node-table item", NULL);
22942 		xmlFree(*keySeq);
22943 		*keySeq = NULL;
22944 		return(-1);
22945 	    }
22946 	    memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
22947 
22948 	    /*
22949 	    * Store the node-table item in a global list.
22950 	    */
22951 	    if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
22952 		if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
22953 		    xmlFree(ntItem);
22954 		    xmlFree(*keySeq);
22955 		    *keySeq = NULL;
22956 		    return (-1);
22957 		}
22958 		ntItem->nodeQNameID = -1;
22959 	    } else {
22960 		/*
22961 		* Save a cached QName for this node on the IDC node, to be
22962 		* able to report it, even if the node is not saved.
22963 		*/
22964 		ntItem->nodeQNameID = xmlSchemaVAddNodeQName(vctxt,
22965 		    vctxt->inode->localName, vctxt->inode->nsName);
22966 		if (ntItem->nodeQNameID == -1) {
22967 		    xmlFree(ntItem);
22968 		    xmlFree(*keySeq);
22969 		    *keySeq = NULL;
22970 		    return (-1);
22971 		}
22972 	    }
22973 	    /*
22974 	    * Init the node-table item: Save the node, position and
22975 	    * consume the key-sequence.
22976 	    */
22977 	    ntItem->node = vctxt->node;
22978 	    ntItem->nodeLine = vctxt->inode->nodeLine;
22979 	    ntItem->keys = *keySeq;
22980 	    *keySeq = NULL;
22981 #if 0
22982 	    if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) {
22983 #endif
22984 	    if (xmlSchemaItemListAdd(targets, ntItem) == -1) {
22985 		if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
22986 		    /*
22987 		    * Free the item, since keyref items won't be
22988 		    * put on a global list.
22989 		    */
22990 		    xmlFree(ntItem->keys);
22991 		    xmlFree(ntItem);
22992 		}
22993 		return (-1);
22994 	    }
22995 
22996 	    goto selector_leave;
22997 selector_key_error:
22998 	    {
22999 		xmlChar *str = NULL;
23000 		/*
23001 		* 4.2.1 (KEY) The �target node set� and the
23002 		* �qualified node set� are equal, that is, every
23003 		* member of the �target node set� is also a member
23004 		* of the �qualified node set� and vice versa.
23005 		*/
23006 		xmlSchemaCustomErr(ACTXT_CAST vctxt,
23007 		    XML_SCHEMAV_CVC_IDC, NULL,
23008 		    WXS_BASIC_CAST idc,
23009 		    "Not all fields of %s evaluate to a node",
23010 		    xmlSchemaGetIDCDesignation(&str, idc), NULL);
23011 		FREE_AND_NULL(str);
23012 	    }
23013 selector_leave:
23014 	    /*
23015 	    * Free the key-sequence if not added to the IDC table.
23016 	    */
23017 	    if ((keySeq != NULL) && (*keySeq != NULL)) {
23018 		xmlFree(*keySeq);
23019 		*keySeq = NULL;
23020 	    }
23021 	} /* if selector */
23022 
23023 	sto->nbHistory--;
23024 
23025 deregister_check:
23026 	/*
23027 	* Deregister state objects if they reach the depth of creation.
23028 	*/
23029 	if ((sto->nbHistory == 0) && (sto->depth == depth)) {
23030 #ifdef DEBUG_IDC
23031 	    xmlGenericError(xmlGenericErrorContext, "IDC:   STO pop '%s'\n",
23032 		sto->sel->xpath);
23033 #endif
23034 	    if (vctxt->xpathStates != sto) {
23035 		VERROR_INT("xmlSchemaXPathProcessHistory",
23036 		    "The state object to be removed is not the first "
23037 		    "in the list");
23038 	    }
23039 	    nextsto = sto->next;
23040 	    /*
23041 	    * Unlink from the list of active XPath state objects.
23042 	    */
23043 	    vctxt->xpathStates = sto->next;
23044 	    sto->next = vctxt->xpathStatePool;
23045 	    /*
23046 	    * Link it to the pool of reusable state objects.
23047 	    */
23048 	    vctxt->xpathStatePool = sto;
23049 	    sto = nextsto;
23050 	} else
23051 	    sto = sto->next;
23052     } /* while (sto != NULL) */
23053     return (0);
23054 }
23055 
23056 /**
23057  * xmlSchemaIDCRegisterMatchers:
23058  * @vctxt: the WXS validation context
23059  * @elemDecl: the element declaration
23060  *
23061  * Creates helper objects to evaluate IDC selectors/fields
23062  * successively.
23063  *
23064  * Returns 0 if OK and -1 on internal errors.
23065  */
23066 static int
23067 xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
23068 			     xmlSchemaElementPtr elemDecl)
23069 {
23070     xmlSchemaIDCMatcherPtr matcher, last = NULL;
23071     xmlSchemaIDCPtr idc, refIdc;
23072     xmlSchemaIDCAugPtr aidc;
23073 
23074     idc = (xmlSchemaIDCPtr) elemDecl->idcs;
23075     if (idc == NULL)
23076 	return (0);
23077 
23078 #ifdef DEBUG_IDC
23079     {
23080 	xmlChar *str = NULL;
23081 	xmlGenericError(xmlGenericErrorContext,
23082 	    "IDC: REGISTER on %s, depth %d\n",
23083 	    (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
23084 		vctxt->inode->localName), vctxt->depth);
23085 	FREE_AND_NULL(str)
23086     }
23087 #endif
23088     if (vctxt->inode->idcMatchers != NULL) {
23089 	VERROR_INT("xmlSchemaIDCRegisterMatchers",
23090 	    "The chain of IDC matchers is expected to be empty");
23091 	return (-1);
23092     }
23093     do {
23094 	if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23095 	    /*
23096 	    * Since IDCs bubbles are expensive we need to know the
23097 	    * depth at which the bubbles should stop; this will be
23098 	    * the depth of the top-most keyref IDC. If no keyref
23099 	    * references a key/unique IDC, the keyrefDepth will
23100 	    * be -1, indicating that no bubbles are needed.
23101 	    */
23102 	    refIdc = (xmlSchemaIDCPtr) idc->ref->item;
23103 	    if (refIdc != NULL) {
23104 		/*
23105 		* Remember that we have keyrefs on this node.
23106 		*/
23107 		vctxt->inode->hasKeyrefs = 1;
23108 		/*
23109 		* Lookup the referenced augmented IDC info.
23110 		*/
23111 		aidc = vctxt->aidcs;
23112 		while (aidc != NULL) {
23113 		    if (aidc->def == refIdc)
23114 			break;
23115 		    aidc = aidc->next;
23116 		}
23117 		if (aidc == NULL) {
23118 		    VERROR_INT("xmlSchemaIDCRegisterMatchers",
23119 			"Could not find an augmented IDC item for an IDC "
23120 			"definition");
23121 		    return (-1);
23122 		}
23123 		if ((aidc->keyrefDepth == -1) ||
23124 		    (vctxt->depth < aidc->keyrefDepth))
23125 		    aidc->keyrefDepth = vctxt->depth;
23126 	    }
23127 	}
23128 	/*
23129 	* Lookup the augmented IDC item for the IDC definition.
23130 	*/
23131 	aidc = vctxt->aidcs;
23132 	while (aidc != NULL) {
23133 	    if (aidc->def == idc)
23134 		break;
23135 	    aidc = aidc->next;
23136 	}
23137 	if (aidc == NULL) {
23138 	    VERROR_INT("xmlSchemaIDCRegisterMatchers",
23139 		"Could not find an augmented IDC item for an IDC definition");
23140 	    return (-1);
23141 	}
23142 	/*
23143 	* Create an IDC matcher for every IDC definition.
23144 	*/
23145 	if (vctxt->idcMatcherCache != NULL) {
23146 	    /*
23147 	    * Reuse a cached matcher.
23148 	    */
23149 	    matcher = vctxt->idcMatcherCache;
23150 	    vctxt->idcMatcherCache = matcher->nextCached;
23151 	    matcher->nextCached = NULL;
23152 	} else {
23153 	    matcher = (xmlSchemaIDCMatcherPtr)
23154 		xmlMalloc(sizeof(xmlSchemaIDCMatcher));
23155 	    if (matcher == NULL) {
23156 		xmlSchemaVErrMemory(vctxt,
23157 		    "allocating an IDC matcher", NULL);
23158 		return (-1);
23159 	    }
23160 	    memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
23161 	}
23162 	if (last == NULL)
23163 	    vctxt->inode->idcMatchers = matcher;
23164 	else
23165 	    last->next = matcher;
23166 	last = matcher;
23167 
23168 	matcher->type = IDC_MATCHER;
23169 	matcher->depth = vctxt->depth;
23170 	matcher->aidc = aidc;
23171 	matcher->idcType = aidc->def->type;
23172 #ifdef DEBUG_IDC
23173 	xmlGenericError(xmlGenericErrorContext, "IDC:   register matcher\n");
23174 #endif
23175 	/*
23176 	* Init the automaton state object.
23177 	*/
23178 	if (xmlSchemaIDCAddStateObject(vctxt, matcher,
23179 	    idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
23180 	    return (-1);
23181 
23182 	idc = idc->next;
23183     } while (idc != NULL);
23184     return (0);
23185 }
23186 
23187 static int
23188 xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,
23189 			   xmlSchemaNodeInfoPtr ielem)
23190 {
23191     xmlSchemaPSVIIDCBindingPtr bind;
23192     int res, i, j, k, nbTargets, nbFields, nbDupls, nbNodeTable;
23193     xmlSchemaPSVIIDCKeyPtr *keys, *ntkeys;
23194     xmlSchemaPSVIIDCNodePtr *targets, *dupls;
23195 
23196     xmlSchemaIDCMatcherPtr matcher = ielem->idcMatchers;
23197     /* vctxt->createIDCNodeTables */
23198     while (matcher != NULL) {
23199 	/*
23200 	* Skip keyref IDCs and empty IDC target-lists.
23201 	*/
23202 	if ((matcher->aidc->def->type == XML_SCHEMA_TYPE_IDC_KEYREF) ||
23203 	    WXS_ILIST_IS_EMPTY(matcher->targets))
23204 	{
23205 	    matcher = matcher->next;
23206 	    continue;
23207 	}
23208 	/*
23209 	* If we _want_ the IDC node-table to be created in any case
23210 	* then do so. Otherwise create them only if keyrefs need them.
23211 	*/
23212 	if ((! vctxt->createIDCNodeTables) &&
23213 	    ((matcher->aidc->keyrefDepth == -1) ||
23214 	     (matcher->aidc->keyrefDepth > vctxt->depth)))
23215 	{
23216 	    matcher = matcher->next;
23217 	    continue;
23218 	}
23219 	/*
23220 	* Get/create the IDC binding on this element for the IDC definition.
23221 	*/
23222 	bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
23223 
23224 	if (! WXS_ILIST_IS_EMPTY(bind->dupls)) {
23225 	    dupls = (xmlSchemaPSVIIDCNodePtr *) bind->dupls->items;
23226 	    nbDupls = bind->dupls->nbItems;
23227 	} else {
23228 	    dupls = NULL;
23229 	    nbDupls = 0;
23230 	}
23231 	if (bind->nodeTable != NULL) {
23232 	    nbNodeTable = bind->nbNodes;
23233 	} else {
23234 	    nbNodeTable = 0;
23235 	}
23236 
23237 	if ((nbNodeTable == 0) && (nbDupls == 0)) {
23238 	    /*
23239 	    * Transfer all IDC target-nodes to the IDC node-table.
23240 	    */
23241 	    bind->nodeTable =
23242 		(xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23243 	    bind->sizeNodes = matcher->targets->sizeItems;
23244 	    bind->nbNodes = matcher->targets->nbItems;
23245 
23246 	    matcher->targets->items = NULL;
23247 	    matcher->targets->sizeItems = 0;
23248 	    matcher->targets->nbItems = 0;
23249 	} else {
23250 	    /*
23251 	    * Compare the key-sequences and add to the IDC node-table.
23252 	    */
23253 	    nbTargets = matcher->targets->nbItems;
23254 	    targets = (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23255 	    nbFields = matcher->aidc->def->nbFields;
23256 	    i = 0;
23257 	    do {
23258 		keys = targets[i]->keys;
23259 		if (nbDupls) {
23260 		    /*
23261 		    * Search in already found duplicates first.
23262 		    */
23263 		    j = 0;
23264 		    do {
23265 			if (nbFields == 1) {
23266 			    res = xmlSchemaAreValuesEqual(keys[0]->val,
23267 				dupls[j]->keys[0]->val);
23268 			    if (res == -1)
23269 				goto internal_error;
23270 			    if (res == 1) {
23271 				/*
23272 				* Equal key-sequence.
23273 				*/
23274 				goto next_target;
23275 			    }
23276 			} else {
23277 			    res = 0;
23278 			    ntkeys = dupls[j]->keys;
23279 			    for (k = 0; k < nbFields; k++) {
23280 				res = xmlSchemaAreValuesEqual(keys[k]->val,
23281 				    ntkeys[k]->val);
23282 				if (res == -1)
23283 				    goto internal_error;
23284 				if (res == 0) {
23285 				    /*
23286 				    * One of the keys differs.
23287 				    */
23288 				    break;
23289 				}
23290 			    }
23291 			    if (res == 1) {
23292 				/*
23293 				* Equal key-sequence found.
23294 				*/
23295 				goto next_target;
23296 			    }
23297 			}
23298 			j++;
23299 		    } while (j < nbDupls);
23300 		}
23301 		if (nbNodeTable) {
23302 		    j = 0;
23303 		    do {
23304 			if (nbFields == 1) {
23305 			    res = xmlSchemaAreValuesEqual(keys[0]->val,
23306 				bind->nodeTable[j]->keys[0]->val);
23307 			    if (res == -1)
23308 				goto internal_error;
23309 			    if (res == 0) {
23310 				/*
23311 				* The key-sequence differs.
23312 				*/
23313 				goto next_node_table_entry;
23314 			    }
23315 			} else {
23316 			    res = 0;
23317 			    ntkeys = bind->nodeTable[j]->keys;
23318 			    for (k = 0; k < nbFields; k++) {
23319 				res = xmlSchemaAreValuesEqual(keys[k]->val,
23320 				    ntkeys[k]->val);
23321 				if (res == -1)
23322 				    goto internal_error;
23323 				if (res == 0) {
23324 				    /*
23325 				    * One of the keys differs.
23326 				    */
23327 				    goto next_node_table_entry;
23328 				}
23329 			    }
23330 			}
23331 			/*
23332 			* Add the duplicate to the list of duplicates.
23333 			*/
23334 			if (bind->dupls == NULL) {
23335 			    bind->dupls = xmlSchemaItemListCreate();
23336 			    if (bind->dupls == NULL)
23337 				goto internal_error;
23338 			}
23339 			if (xmlSchemaItemListAdd(bind->dupls, bind->nodeTable[j]) == -1)
23340 			    goto internal_error;
23341 			/*
23342 			* Remove the duplicate entry from the IDC node-table.
23343 			*/
23344 			bind->nodeTable[j] = bind->nodeTable[bind->nbNodes -1];
23345 			bind->nbNodes--;
23346 
23347 			goto next_target;
23348 
23349 next_node_table_entry:
23350 			j++;
23351 		    } while (j < nbNodeTable);
23352 		}
23353 		/*
23354 		* If everything is fine, then add the IDC target-node to
23355 		* the IDC node-table.
23356 		*/
23357 		if (xmlSchemaIDCAppendNodeTableItem(bind, targets[i]) == -1)
23358 		    goto internal_error;
23359 
23360 next_target:
23361 		i++;
23362 	    } while (i < nbTargets);
23363 	}
23364 	matcher = matcher->next;
23365     }
23366     return(0);
23367 
23368 internal_error:
23369     return(-1);
23370 }
23371 
23372 /**
23373  * xmlSchemaBubbleIDCNodeTables:
23374  * @depth: the current tree depth
23375  *
23376  * Merges IDC bindings of an element at @depth into the corresponding IDC
23377  * bindings of its parent element. If a duplicate note-table entry is found,
23378  * both, the parent node-table entry and child entry are discarded from the
23379  * node-table of the parent.
23380  *
23381  * Returns 0 if OK and -1 on internal errors.
23382  */
23383 static int
23384 xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
23385 {
23386     xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
23387     xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL; /* parent IDC bindings. */
23388     xmlSchemaPSVIIDCNodePtr node, parNode = NULL, *dupls, *parNodes; /* node-table entries. */
23389     xmlSchemaIDCAugPtr aidc;
23390     int i, j, k, ret = 0, nbFields, oldNum, oldDupls;
23391 
23392     bind = vctxt->inode->idcTable;
23393     if (bind == NULL) {
23394 	/* Fine, no table, no bubbles. */
23395 	return (0);
23396     }
23397 
23398     parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
23399     /*
23400     * Walk all bindings; create new or add to existing bindings.
23401     * Remove duplicate key-sequences.
23402     */
23403     while (bind != NULL) {
23404 
23405 	if ((bind->nbNodes == 0) && WXS_ILIST_IS_EMPTY(bind->dupls))
23406 	    goto next_binding;
23407 	/*
23408 	* Check if the key/unique IDC table needs to be bubbled.
23409 	*/
23410 	if (! vctxt->createIDCNodeTables) {
23411 	    aidc = vctxt->aidcs;
23412 	    do {
23413 		if (aidc->def == bind->definition) {
23414 		    if ((aidc->keyrefDepth == -1) ||
23415 			(aidc->keyrefDepth >= vctxt->depth)) {
23416 			goto next_binding;
23417 		    }
23418 		    break;
23419 		}
23420 		aidc = aidc->next;
23421 	    } while (aidc != NULL);
23422 	}
23423 
23424 	if (parTable != NULL)
23425 	    parBind = *parTable;
23426 	/*
23427 	* Search a matching parent binding for the
23428 	* IDC definition.
23429 	*/
23430 	while (parBind != NULL) {
23431 	    if (parBind->definition == bind->definition)
23432 		break;
23433 	    parBind = parBind->next;
23434 	}
23435 
23436 	if (parBind != NULL) {
23437 	    /*
23438 	    * Compare every node-table entry of the child node,
23439 	    * i.e. the key-sequence within, ...
23440 	    */
23441 	    oldNum = parBind->nbNodes; /* Skip newly added items. */
23442 
23443 	    if (! WXS_ILIST_IS_EMPTY(parBind->dupls)) {
23444 		oldDupls = parBind->dupls->nbItems;
23445 		dupls = (xmlSchemaPSVIIDCNodePtr *) parBind->dupls->items;
23446 	    } else {
23447 		dupls = NULL;
23448 		oldDupls = 0;
23449 	    }
23450 
23451 	    parNodes = parBind->nodeTable;
23452 	    nbFields = bind->definition->nbFields;
23453 
23454 	    for (i = 0; i < bind->nbNodes; i++) {
23455 		node = bind->nodeTable[i];
23456 		if (node == NULL)
23457 		    continue;
23458 		/*
23459 		* ...with every key-sequence of the parent node, already
23460 		* evaluated to be a duplicate key-sequence.
23461 		*/
23462 		if (oldDupls) {
23463 		    j = 0;
23464 		    while (j < oldDupls) {
23465 			if (nbFields == 1) {
23466 			    ret = xmlSchemaAreValuesEqual(
23467 				node->keys[0]->val,
23468 				dupls[j]->keys[0]->val);
23469 			    if (ret == -1)
23470 				goto internal_error;
23471 			    if (ret == 0) {
23472 				j++;
23473 				continue;
23474 			    }
23475 			} else {
23476 			    parNode = dupls[j];
23477 			    for (k = 0; k < nbFields; k++) {
23478 				ret = xmlSchemaAreValuesEqual(
23479 				    node->keys[k]->val,
23480 				    parNode->keys[k]->val);
23481 				if (ret == -1)
23482 				    goto internal_error;
23483 				if (ret == 0)
23484 				    break;
23485 			    }
23486 			}
23487 			if (ret == 1)
23488 			    /* Duplicate found. */
23489 			    break;
23490 			j++;
23491 		    }
23492 		    if (j != oldDupls) {
23493 			/* Duplicate found. Skip this entry. */
23494 			continue;
23495 		    }
23496 		}
23497 		/*
23498 		* ... and with every key-sequence of the parent node.
23499 		*/
23500 		if (oldNum) {
23501 		    j = 0;
23502 		    while (j < oldNum) {
23503 			parNode = parNodes[j];
23504 			if (nbFields == 1) {
23505 			    ret = xmlSchemaAreValuesEqual(
23506 				node->keys[0]->val,
23507 				parNode->keys[0]->val);
23508 			    if (ret == -1)
23509 				goto internal_error;
23510 			    if (ret == 0) {
23511 				j++;
23512 				continue;
23513 			    }
23514 			} else {
23515 			    for (k = 0; k < nbFields; k++) {
23516 				ret = xmlSchemaAreValuesEqual(
23517 				    node->keys[k]->val,
23518 				    parNode->keys[k]->val);
23519 				if (ret == -1)
23520 				    goto internal_error;
23521 				if (ret == 0)
23522 				    break;
23523 			    }
23524 			}
23525 			if (ret == 1)
23526 			    /* Duplicate found. */
23527 			    break;
23528 			j++;
23529 		    }
23530 		    if (j != oldNum) {
23531 			/*
23532 			* Handle duplicates. Move the duplicate in
23533 			* the parent's node-table to the list of
23534 			* duplicates.
23535 			*/
23536 			oldNum--;
23537 			parBind->nbNodes--;
23538 			/*
23539 			* Move last old item to pos of duplicate.
23540 			*/
23541 			parNodes[j] = parNodes[oldNum];
23542 
23543 			if (parBind->nbNodes != oldNum) {
23544 			    /*
23545 			    * If new items exist, move last new item to
23546 			    * last of old items.
23547 			    */
23548 			    parNodes[oldNum] =
23549 				parNodes[parBind->nbNodes];
23550 			}
23551 			if (parBind->dupls == NULL) {
23552 			    parBind->dupls = xmlSchemaItemListCreate();
23553 			    if (parBind->dupls == NULL)
23554 				goto internal_error;
23555 			}
23556 			xmlSchemaItemListAdd(parBind->dupls, parNode);
23557 		    } else {
23558 			/*
23559 			* Add the node-table entry (node and key-sequence) of
23560 			* the child node to the node table of the parent node.
23561 			*/
23562 			if (parBind->nodeTable == NULL) {
23563 			    parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23564 				xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
23565 			    if (parBind->nodeTable == NULL) {
23566 				xmlSchemaVErrMemory(NULL,
23567 				    "allocating IDC list of node-table items", NULL);
23568 				goto internal_error;
23569 			    }
23570 			    parBind->sizeNodes = 1;
23571 			} else if (parBind->nbNodes >= parBind->sizeNodes) {
23572 			    parBind->sizeNodes *= 2;
23573 			    parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23574 				xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
23575 				sizeof(xmlSchemaPSVIIDCNodePtr));
23576 			    if (parBind->nodeTable == NULL) {
23577 				xmlSchemaVErrMemory(NULL,
23578 				    "re-allocating IDC list of node-table items", NULL);
23579 				goto internal_error;
23580 			    }
23581 			}
23582 			parNodes = parBind->nodeTable;
23583 			/*
23584 			* Append the new node-table entry to the 'new node-table
23585 			* entries' section.
23586 			*/
23587 			parNodes[parBind->nbNodes++] = node;
23588 		    }
23589 
23590 		}
23591 
23592 	    }
23593 	} else {
23594 	    /*
23595 	    * No binding for the IDC was found: create a new one and
23596 	    * copy all node-tables.
23597 	    */
23598 	    parBind = xmlSchemaIDCNewBinding(bind->definition);
23599 	    if (parBind == NULL)
23600 		goto internal_error;
23601 
23602 	    /*
23603 	    * TODO: Hmm, how to optimize the initial number of
23604 	    * allocated entries?
23605 	    */
23606 	    if (bind->nbNodes != 0) {
23607 		/*
23608 		* Add all IDC node-table entries.
23609 		*/
23610 		if (! vctxt->psviExposeIDCNodeTables) {
23611 		    /*
23612 		    * Just move the entries.
23613 		    * NOTE: this is quite save here, since
23614 		    * all the keyref lookups have already been
23615 		    * performed.
23616 		    */
23617 		    parBind->nodeTable = bind->nodeTable;
23618 		    bind->nodeTable = NULL;
23619 		    parBind->sizeNodes = bind->sizeNodes;
23620 		    bind->sizeNodes = 0;
23621 		    parBind->nbNodes = bind->nbNodes;
23622 		    bind->nbNodes = 0;
23623 		} else {
23624 		    /*
23625 		    * Copy the entries.
23626 		    */
23627 		    parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23628 			xmlMalloc(bind->nbNodes *
23629 			sizeof(xmlSchemaPSVIIDCNodePtr));
23630 		    if (parBind->nodeTable == NULL) {
23631 			xmlSchemaVErrMemory(NULL,
23632 			    "allocating an array of IDC node-table "
23633 			    "items", NULL);
23634 			xmlSchemaIDCFreeBinding(parBind);
23635 			goto internal_error;
23636 		    }
23637 		    parBind->sizeNodes = bind->nbNodes;
23638 		    parBind->nbNodes = bind->nbNodes;
23639 		    memcpy(parBind->nodeTable, bind->nodeTable,
23640 			bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
23641 		}
23642 	    }
23643 	    if (bind->dupls) {
23644 		/*
23645 		* Move the duplicates.
23646 		*/
23647 		if (parBind->dupls != NULL)
23648 		    xmlSchemaItemListFree(parBind->dupls);
23649 		parBind->dupls = bind->dupls;
23650 		bind->dupls = NULL;
23651 	    }
23652 	    if (*parTable == NULL)
23653 		*parTable = parBind;
23654 	    else {
23655 		parBind->next = *parTable;
23656 		*parTable = parBind;
23657 	    }
23658 	}
23659 
23660 next_binding:
23661 	bind = bind->next;
23662     }
23663     return (0);
23664 
23665 internal_error:
23666     return(-1);
23667 }
23668 
23669 /**
23670  * xmlSchemaCheckCVCIDCKeyRef:
23671  * @vctxt: the WXS validation context
23672  * @elemDecl: the element declaration
23673  *
23674  * Check the cvc-idc-keyref constraints.
23675  */
23676 static int
23677 xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
23678 {
23679     xmlSchemaIDCMatcherPtr matcher;
23680     xmlSchemaPSVIIDCBindingPtr bind;
23681 
23682     matcher = vctxt->inode->idcMatchers;
23683     /*
23684     * Find a keyref.
23685     */
23686     while (matcher != NULL) {
23687 	if ((matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) &&
23688 	    matcher->targets &&
23689 	    matcher->targets->nbItems)
23690 	{
23691 	    int i, j, k, res, nbFields, hasDupls;
23692 	    xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
23693 	    xmlSchemaPSVIIDCNodePtr refNode = NULL;
23694 
23695 	    nbFields = matcher->aidc->def->nbFields;
23696 
23697 	    /*
23698 	    * Find the IDC node-table for the referenced IDC key/unique.
23699 	    */
23700 	    bind = vctxt->inode->idcTable;
23701 	    while (bind != NULL) {
23702 		if ((xmlSchemaIDCPtr) matcher->aidc->def->ref->item ==
23703 		    bind->definition)
23704 		    break;
23705 		bind = bind->next;
23706 	    }
23707 	    hasDupls = (bind && bind->dupls && bind->dupls->nbItems) ? 1 : 0;
23708 	    /*
23709 	    * Search for a matching key-sequences.
23710 	    */
23711 	    for (i = 0; i < matcher->targets->nbItems; i++) {
23712 		res = 0;
23713 		refNode = matcher->targets->items[i];
23714 		if (bind != NULL) {
23715 		    refKeys = refNode->keys;
23716 		    for (j = 0; j < bind->nbNodes; j++) {
23717 			keys = bind->nodeTable[j]->keys;
23718 			for (k = 0; k < nbFields; k++) {
23719 			    res = xmlSchemaAreValuesEqual(keys[k]->val,
23720 				refKeys[k]->val);
23721 			    if (res == 0)
23722 				break;
23723 			    else if (res == -1) {
23724 				return (-1);
23725 			    }
23726 			}
23727 			if (res == 1) {
23728 			    /*
23729 			    * Match found.
23730 			    */
23731 			    break;
23732 			}
23733 		    }
23734 		    if ((res == 0) && hasDupls) {
23735 			/*
23736 			* Search in duplicates
23737 			*/
23738 			for (j = 0; j < bind->dupls->nbItems; j++) {
23739 			    keys = ((xmlSchemaPSVIIDCNodePtr)
23740 				bind->dupls->items[j])->keys;
23741 			    for (k = 0; k < nbFields; k++) {
23742 				res = xmlSchemaAreValuesEqual(keys[k]->val,
23743 				    refKeys[k]->val);
23744 				if (res == 0)
23745 				    break;
23746 				else if (res == -1) {
23747 				    return (-1);
23748 				}
23749 			    }
23750 			    if (res == 1) {
23751 				/*
23752 				* Match in duplicates found.
23753 				*/
23754 				xmlChar *str = NULL, *strB = NULL;
23755 				xmlSchemaKeyrefErr(vctxt,
23756 				    XML_SCHEMAV_CVC_IDC, refNode,
23757 				    (xmlSchemaTypePtr) matcher->aidc->def,
23758 				    "More than one match found for "
23759 				    "key-sequence %s of keyref '%s'",
23760 				    xmlSchemaFormatIDCKeySequence(vctxt, &str,
23761 					refNode->keys, nbFields),
23762 				    xmlSchemaGetComponentQName(&strB,
23763 					matcher->aidc->def));
23764 				FREE_AND_NULL(str);
23765 				FREE_AND_NULL(strB);
23766 				break;
23767 			    }
23768 			}
23769 		    }
23770 		}
23771 
23772 		if (res == 0) {
23773 		    xmlChar *str = NULL, *strB = NULL;
23774 		    xmlSchemaKeyrefErr(vctxt,
23775 			XML_SCHEMAV_CVC_IDC, refNode,
23776 			(xmlSchemaTypePtr) matcher->aidc->def,
23777 			"No match found for key-sequence %s of keyref '%s'",
23778 			xmlSchemaFormatIDCKeySequence(vctxt, &str,
23779 			    refNode->keys, nbFields),
23780 			xmlSchemaGetComponentQName(&strB, matcher->aidc->def));
23781 		    FREE_AND_NULL(str);
23782 		    FREE_AND_NULL(strB);
23783 		}
23784 	    }
23785 	}
23786 	matcher = matcher->next;
23787     }
23788     /* TODO: Return an error if any error encountered. */
23789     return (0);
23790 }
23791 
23792 /************************************************************************
23793  * 									*
23794  * 			XML Reader validation code                      *
23795  * 									*
23796  ************************************************************************/
23797 
23798 static xmlSchemaAttrInfoPtr
23799 xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
23800 {
23801     xmlSchemaAttrInfoPtr iattr;
23802     /*
23803     * Grow/create list of attribute infos.
23804     */
23805     if (vctxt->attrInfos == NULL) {
23806 	vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23807 	    xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
23808 	vctxt->sizeAttrInfos = 1;
23809 	if (vctxt->attrInfos == NULL) {
23810 	    xmlSchemaVErrMemory(vctxt,
23811 		"allocating attribute info list", NULL);
23812 	    return (NULL);
23813 	}
23814     } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
23815 	vctxt->sizeAttrInfos++;
23816 	vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23817 	    xmlRealloc(vctxt->attrInfos,
23818 		vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
23819 	if (vctxt->attrInfos == NULL) {
23820 	    xmlSchemaVErrMemory(vctxt,
23821 		"re-allocating attribute info list", NULL);
23822 	    return (NULL);
23823 	}
23824     } else {
23825 	iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
23826 	if (iattr->localName != NULL) {
23827 	    VERROR_INT("xmlSchemaGetFreshAttrInfo",
23828 		"attr info not cleared");
23829 	    return (NULL);
23830 	}
23831 	iattr->nodeType = XML_ATTRIBUTE_NODE;
23832 	return (iattr);
23833     }
23834     /*
23835     * Create an attribute info.
23836     */
23837     iattr = (xmlSchemaAttrInfoPtr)
23838 	xmlMalloc(sizeof(xmlSchemaAttrInfo));
23839     if (iattr == NULL) {
23840 	xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
23841 	return (NULL);
23842     }
23843     memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
23844     iattr->nodeType = XML_ATTRIBUTE_NODE;
23845     vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
23846 
23847     return (iattr);
23848 }
23849 
23850 static int
23851 xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
23852 			xmlNodePtr attrNode,
23853 			int nodeLine,
23854 			const xmlChar *localName,
23855 			const xmlChar *nsName,
23856 			int ownedNames,
23857 			xmlChar *value,
23858 			int ownedValue)
23859 {
23860     xmlSchemaAttrInfoPtr attr;
23861 
23862     attr = xmlSchemaGetFreshAttrInfo(vctxt);
23863     if (attr == NULL) {
23864 	VERROR_INT("xmlSchemaPushAttribute",
23865 	    "calling xmlSchemaGetFreshAttrInfo()");
23866 	return (-1);
23867     }
23868     attr->node = attrNode;
23869     attr->nodeLine = nodeLine;
23870     attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
23871     attr->localName = localName;
23872     attr->nsName = nsName;
23873     if (ownedNames)
23874 	attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
23875     /*
23876     * Evaluate if it's an XSI attribute.
23877     */
23878     if (nsName != NULL) {
23879 	if (xmlStrEqual(localName, BAD_CAST "nil")) {
23880 	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23881 		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
23882 	    }
23883 	} else if (xmlStrEqual(localName, BAD_CAST "type")) {
23884 	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23885 		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
23886 	    }
23887 	} else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
23888 	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23889 		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
23890 	    }
23891 	} else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
23892 	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23893 		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
23894 	    }
23895 	} else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
23896 	    attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
23897 	}
23898     }
23899     attr->value = value;
23900     if (ownedValue)
23901 	attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
23902     if (attr->metaType != 0)
23903 	attr->state = XML_SCHEMAS_ATTR_META;
23904     return (0);
23905 }
23906 
23907 /**
23908  * xmlSchemaClearElemInfo:
23909  * @vctxt: the WXS validation context
23910  * @ielem: the element information item
23911  */
23912 static void
23913 xmlSchemaClearElemInfo(xmlSchemaValidCtxtPtr vctxt,
23914 		       xmlSchemaNodeInfoPtr ielem)
23915 {
23916     ielem->hasKeyrefs = 0;
23917     ielem->appliedXPath = 0;
23918     if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
23919 	FREE_AND_NULL(ielem->localName);
23920 	FREE_AND_NULL(ielem->nsName);
23921     } else {
23922 	ielem->localName = NULL;
23923 	ielem->nsName = NULL;
23924     }
23925     if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
23926 	FREE_AND_NULL(ielem->value);
23927     } else {
23928 	ielem->value = NULL;
23929     }
23930     if (ielem->val != NULL) {
23931 	/*
23932 	* PSVI TODO: Be careful not to free it when the value is
23933 	* exposed via PSVI.
23934 	*/
23935 	xmlSchemaFreeValue(ielem->val);
23936 	ielem->val = NULL;
23937     }
23938     if (ielem->idcMatchers != NULL) {
23939 	/*
23940 	* REVISIT OPTIMIZE TODO: Use a pool of IDC matchers.
23941 	*   Does it work?
23942 	*/
23943 	xmlSchemaIDCReleaseMatcherList(vctxt, ielem->idcMatchers);
23944 #if 0
23945 	xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
23946 #endif
23947 	ielem->idcMatchers = NULL;
23948     }
23949     if (ielem->idcTable != NULL) {
23950 	/*
23951 	* OPTIMIZE TODO: Use a pool of IDC tables??.
23952 	*/
23953 	xmlSchemaIDCFreeIDCTable(ielem->idcTable);
23954 	ielem->idcTable = NULL;
23955     }
23956     if (ielem->regexCtxt != NULL) {
23957 	xmlRegFreeExecCtxt(ielem->regexCtxt);
23958 	ielem->regexCtxt = NULL;
23959     }
23960     if (ielem->nsBindings != NULL) {
23961 	xmlFree((xmlChar **)ielem->nsBindings);
23962 	ielem->nsBindings = NULL;
23963 	ielem->nbNsBindings = 0;
23964 	ielem->sizeNsBindings = 0;
23965     }
23966 }
23967 
23968 /**
23969  * xmlSchemaGetFreshElemInfo:
23970  * @vctxt: the schema validation context
23971  *
23972  * Creates/reuses and initializes the element info item for
23973  * the currect tree depth.
23974  *
23975  * Returns the element info item or NULL on API or internal errors.
23976  */
23977 static xmlSchemaNodeInfoPtr
23978 xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
23979 {
23980     xmlSchemaNodeInfoPtr info = NULL;
23981 
23982     if (vctxt->depth > vctxt->sizeElemInfos) {
23983 	VERROR_INT("xmlSchemaGetFreshElemInfo",
23984 	    "inconsistent depth encountered");
23985 	return (NULL);
23986     }
23987     if (vctxt->elemInfos == NULL) {
23988 	vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
23989 	    xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
23990 	if (vctxt->elemInfos == NULL) {
23991 	    xmlSchemaVErrMemory(vctxt,
23992 		"allocating the element info array", NULL);
23993 	    return (NULL);
23994 	}
23995 	memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
23996 	vctxt->sizeElemInfos = 10;
23997     } else if (vctxt->sizeElemInfos <= vctxt->depth) {
23998 	int i = vctxt->sizeElemInfos;
23999 
24000 	vctxt->sizeElemInfos *= 2;
24001 	vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24002 	    xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
24003 	    sizeof(xmlSchemaNodeInfoPtr));
24004 	if (vctxt->elemInfos == NULL) {
24005 	    xmlSchemaVErrMemory(vctxt,
24006 		"re-allocating the element info array", NULL);
24007 	    return (NULL);
24008 	}
24009 	/*
24010 	* We need the new memory to be NULLed.
24011 	* TODO: Use memset instead?
24012 	*/
24013 	for (; i < vctxt->sizeElemInfos; i++)
24014 	    vctxt->elemInfos[i] = NULL;
24015     } else
24016 	info = vctxt->elemInfos[vctxt->depth];
24017 
24018     if (info == NULL) {
24019 	info = (xmlSchemaNodeInfoPtr)
24020 	    xmlMalloc(sizeof(xmlSchemaNodeInfo));
24021 	if (info == NULL) {
24022 	    xmlSchemaVErrMemory(vctxt,
24023 		"allocating an element info", NULL);
24024 	    return (NULL);
24025 	}
24026 	vctxt->elemInfos[vctxt->depth] = info;
24027     } else {
24028 	if (info->localName != NULL) {
24029 	    VERROR_INT("xmlSchemaGetFreshElemInfo",
24030 		"elem info has not been cleared");
24031 	    return (NULL);
24032 	}
24033     }
24034     memset(info, 0, sizeof(xmlSchemaNodeInfo));
24035     info->nodeType = XML_ELEMENT_NODE;
24036     info->depth = vctxt->depth;
24037 
24038     return (info);
24039 }
24040 
24041 #define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
24042 #define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
24043 #define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
24044 
24045 static int
24046 xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
24047 			xmlNodePtr node,
24048 			xmlSchemaTypePtr type,
24049 			xmlSchemaValType valType,
24050 			const xmlChar * value,
24051 			xmlSchemaValPtr val,
24052 			unsigned long length,
24053 			int fireErrors)
24054 {
24055     int ret, error = 0;
24056 
24057     xmlSchemaTypePtr tmpType;
24058     xmlSchemaFacetLinkPtr facetLink;
24059     xmlSchemaFacetPtr facet;
24060     unsigned long len = 0;
24061     xmlSchemaWhitespaceValueType ws;
24062 
24063     /*
24064     * In Libxml2, derived built-in types have currently no explicit facets.
24065     */
24066     if (type->type == XML_SCHEMA_TYPE_BASIC)
24067 	return (0);
24068 
24069     /*
24070     * NOTE: Do not jump away, if the facetSet of the given type is
24071     * empty: until now, "pattern" and "enumeration" facets of the
24072     * *base types* need to be checked as well.
24073     */
24074     if (type->facetSet == NULL)
24075 	goto pattern_and_enum;
24076 
24077     if (! WXS_IS_ATOMIC(type)) {
24078 	if (WXS_IS_LIST(type))
24079 	    goto WXS_IS_LIST;
24080 	else
24081 	    goto pattern_and_enum;
24082     }
24083     /*
24084     * Whitespace handling is only of importance for string-based
24085     * types.
24086     */
24087     tmpType = xmlSchemaGetPrimitiveType(type);
24088     if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
24089 	WXS_IS_ANY_SIMPLE_TYPE(tmpType)) {
24090 	ws = xmlSchemaGetWhiteSpaceFacetValue(type);
24091     } else
24092 	ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
24093     /*
24094     * If the value was not computed (for string or
24095     * anySimpleType based types), then use the provided
24096     * type.
24097     */
24098     if (val == NULL)
24099 	valType = valType;
24100     else
24101 	valType = xmlSchemaGetValType(val);
24102 
24103     ret = 0;
24104     for (facetLink = type->facetSet; facetLink != NULL;
24105 	facetLink = facetLink->next) {
24106 	/*
24107 	* Skip the pattern "whiteSpace": it is used to
24108 	* format the character content beforehand.
24109 	*/
24110 	switch (facetLink->facet->type) {
24111 	    case XML_SCHEMA_FACET_WHITESPACE:
24112 	    case XML_SCHEMA_FACET_PATTERN:
24113 	    case XML_SCHEMA_FACET_ENUMERATION:
24114 		continue;
24115 	    case XML_SCHEMA_FACET_LENGTH:
24116 	    case XML_SCHEMA_FACET_MINLENGTH:
24117 	    case XML_SCHEMA_FACET_MAXLENGTH:
24118 		ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
24119 		    valType, value, val, &len, ws);
24120 		break;
24121 	    default:
24122 		ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
24123 		    valType, value, val, ws);
24124 		break;
24125 	}
24126 	if (ret < 0) {
24127 	    AERROR_INT("xmlSchemaValidateFacets",
24128 		"validating against a atomic type facet");
24129 	    return (-1);
24130 	} else if (ret > 0) {
24131 	    if (fireErrors)
24132 		xmlSchemaFacetErr(actxt, ret, node,
24133 		value, len, type, facetLink->facet, NULL, NULL, NULL);
24134 	    else
24135 		return (ret);
24136 	    if (error == 0)
24137 		error = ret;
24138 	}
24139 	ret = 0;
24140     }
24141 
24142 WXS_IS_LIST:
24143     if (! WXS_IS_LIST(type))
24144 	goto pattern_and_enum;
24145     /*
24146     * "length", "minLength" and "maxLength" of list types.
24147     */
24148     ret = 0;
24149     for (facetLink = type->facetSet; facetLink != NULL;
24150 	facetLink = facetLink->next) {
24151 
24152 	switch (facetLink->facet->type) {
24153 	    case XML_SCHEMA_FACET_LENGTH:
24154 	    case XML_SCHEMA_FACET_MINLENGTH:
24155 	    case XML_SCHEMA_FACET_MAXLENGTH:
24156 		ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
24157 		    value, length, NULL);
24158 		break;
24159 	    default:
24160 		continue;
24161 	}
24162 	if (ret < 0) {
24163 	    AERROR_INT("xmlSchemaValidateFacets",
24164 		"validating against a list type facet");
24165 	    return (-1);
24166 	} else if (ret > 0) {
24167 	    if (fireErrors)
24168 		xmlSchemaFacetErr(actxt, ret, node,
24169 		value, length, type, facetLink->facet, NULL, NULL, NULL);
24170 	    else
24171 		return (ret);
24172 	    if (error == 0)
24173 		error = ret;
24174 	}
24175 	ret = 0;
24176     }
24177 
24178 pattern_and_enum:
24179     if (error >= 0) {
24180 	int found = 0;
24181 	/*
24182 	* Process enumerations. Facet values are in the value space
24183 	* of the defining type's base type. This seems to be a bug in the
24184 	* XML Schema 1.0 spec. Use the whitespace type of the base type.
24185 	* Only the first set of enumerations in the ancestor-or-self axis
24186 	* is used for validation.
24187 	*/
24188 	ret = 0;
24189 	tmpType = type;
24190 	do {
24191 	    for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
24192 		if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
24193 		    continue;
24194 		found = 1;
24195 		ret = xmlSchemaAreValuesEqual(facet->val, val);
24196 		if (ret == 1)
24197 		    break;
24198 		else if (ret < 0) {
24199 		    AERROR_INT("xmlSchemaValidateFacets",
24200 			"validating against an enumeration facet");
24201 		    return (-1);
24202 		}
24203 	    }
24204 	    if (ret != 0)
24205 		break;
24206 	    /*
24207 	    * Break on the first set of enumerations. Any additional
24208 	    *  enumerations which might be existent on the ancestors
24209 	    *  of the current type are restricted by this set; thus
24210 	    *  *must* *not* be taken into account.
24211 	    */
24212 	    if (found)
24213 		break;
24214 	    tmpType = tmpType->baseType;
24215 	} while ((tmpType != NULL) &&
24216 	    (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24217 	if (found && (ret == 0)) {
24218 	    ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
24219 	    if (fireErrors) {
24220 		xmlSchemaFacetErr(actxt, ret, node,
24221 		    value, 0, type, NULL, NULL, NULL, NULL);
24222 	    } else
24223 		return (ret);
24224 	    if (error == 0)
24225 		error = ret;
24226 	}
24227     }
24228 
24229     if (error >= 0) {
24230 	int found;
24231 	/*
24232 	* Process patters. Pattern facets are ORed at type level
24233 	* and ANDed if derived. Walk the base type axis.
24234 	*/
24235 	tmpType = type;
24236 	facet = NULL;
24237 	do {
24238 	    found = 0;
24239 	    for (facetLink = tmpType->facetSet; facetLink != NULL;
24240 		facetLink = facetLink->next) {
24241 		if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
24242 		    continue;
24243 		found = 1;
24244 		/*
24245 		* NOTE that for patterns, @value needs to be the
24246 		* normalized vaule.
24247 		*/
24248 		ret = xmlRegexpExec(facetLink->facet->regexp, value);
24249 		if (ret == 1)
24250 		    break;
24251 		else if (ret < 0) {
24252 		    AERROR_INT("xmlSchemaValidateFacets",
24253 			"validating against a pattern facet");
24254 		    return (-1);
24255 		} else {
24256 		    /*
24257 		    * Save the last non-validating facet.
24258 		    */
24259 		    facet = facetLink->facet;
24260 		}
24261 	    }
24262 	    if (found && (ret != 1)) {
24263 		ret = XML_SCHEMAV_CVC_PATTERN_VALID;
24264 		if (fireErrors) {
24265 		    xmlSchemaFacetErr(actxt, ret, node,
24266 			value, 0, type, facet, NULL, NULL, NULL);
24267 		} else
24268 		    return (ret);
24269 		if (error == 0)
24270 		    error = ret;
24271 		break;
24272 	    }
24273 	    tmpType = tmpType->baseType;
24274 	} while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24275     }
24276 
24277     return (error);
24278 }
24279 
24280 static xmlChar *
24281 xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
24282 			const xmlChar *value)
24283 {
24284     switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
24285 	case XML_SCHEMA_WHITESPACE_COLLAPSE:
24286 	    return (xmlSchemaCollapseString(value));
24287 	case XML_SCHEMA_WHITESPACE_REPLACE:
24288 	    return (xmlSchemaWhiteSpaceReplace(value));
24289 	default:
24290 	    return (NULL);
24291     }
24292 }
24293 
24294 static int
24295 xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
24296 		       const xmlChar *value,
24297 		       xmlSchemaValPtr *val,
24298 		       int valNeeded)
24299 {
24300     int ret;
24301     const xmlChar *nsName;
24302     xmlChar *local, *prefix = NULL;
24303 
24304     ret = xmlValidateQName(value, 1);
24305     if (ret != 0) {
24306 	if (ret == -1) {
24307 	    VERROR_INT("xmlSchemaValidateQName",
24308 		"calling xmlValidateQName()");
24309 	    return (-1);
24310 	}
24311 	return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
24312     }
24313     /*
24314     * NOTE: xmlSplitQName2 will always return a duplicated
24315     * strings.
24316     */
24317     local = xmlSplitQName2(value, &prefix);
24318     if (local == NULL)
24319 	local = xmlStrdup(value);
24320     /*
24321     * OPTIMIZE TODO: Use flags for:
24322     *  - is there any namespace binding?
24323     *  - is there a default namespace?
24324     */
24325     nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24326 
24327     if (prefix != NULL) {
24328 	xmlFree(prefix);
24329 	/*
24330 	* A namespace must be found if the prefix is
24331 	* NOT NULL.
24332 	*/
24333 	if (nsName == NULL) {
24334 	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24335 	    xmlSchemaCustomErr(ACTXT_CAST vctxt, ret, NULL,
24336 		WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24337 		"The QName value '%s' has no "
24338 		"corresponding namespace declaration in "
24339 		"scope", value, NULL);
24340 	    if (local != NULL)
24341 		xmlFree(local);
24342 	    return (ret);
24343 	}
24344     }
24345     if (valNeeded && val) {
24346 	if (nsName != NULL)
24347 	    *val = xmlSchemaNewQNameValue(
24348 		BAD_CAST xmlStrdup(nsName), BAD_CAST local);
24349 	else
24350 	    *val = xmlSchemaNewQNameValue(NULL,
24351 		BAD_CAST local);
24352     } else
24353 	xmlFree(local);
24354     return (0);
24355 }
24356 
24357 /*
24358 * cvc-simple-type
24359 */
24360 static int
24361 xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
24362 			     xmlNodePtr node,
24363 			     xmlSchemaTypePtr type,
24364 			     const xmlChar *value,
24365 			     xmlSchemaValPtr *retVal,
24366 			     int fireErrors,
24367 			     int normalize,
24368 			     int isNormalized)
24369 {
24370     int ret = 0, valNeeded = (retVal) ? 1 : 0;
24371     xmlSchemaValPtr val = NULL;
24372     /* xmlSchemaWhitespaceValueType ws; */
24373     xmlChar *normValue = NULL;
24374 
24375 #define NORMALIZE(atype) \
24376     if ((! isNormalized) && \
24377     (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
24378 	normValue = xmlSchemaNormalizeValue(atype, value); \
24379 	if (normValue != NULL) \
24380 	    value = normValue; \
24381 	isNormalized = 1; \
24382     }
24383 
24384     if ((retVal != NULL) && (*retVal != NULL)) {
24385 	xmlSchemaFreeValue(*retVal);
24386 	*retVal = NULL;
24387     }
24388     /*
24389     * 3.14.4 Simple Type Definition Validation Rules
24390     * Validation Rule: String Valid
24391     */
24392     /*
24393     * 1 It is schema-valid with respect to that definition as defined
24394     * by Datatype Valid in [XML Schemas: Datatypes].
24395     */
24396     /*
24397     * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
24398     * the empty set, as defined in Type Derivation OK (Simple) (�3.14.6), then
24399     * the string must be a �declared entity name�.
24400     */
24401     /*
24402     * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
24403     * given the empty set, as defined in Type Derivation OK (Simple) (�3.14.6),
24404     * then every whitespace-delimited substring of the string must be a �declared
24405     * entity name�.
24406     */
24407     /*
24408     * 2.3 otherwise no further condition applies.
24409     */
24410     if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
24411 	valNeeded = 1;
24412     if (value == NULL)
24413 	value = BAD_CAST "";
24414     if (WXS_IS_ANY_SIMPLE_TYPE(type) || WXS_IS_ATOMIC(type)) {
24415 	xmlSchemaTypePtr biType; /* The built-in type. */
24416 	/*
24417 	* SPEC (1.2.1) "if {variety} is �atomic� then the string must �match�
24418 	* a literal in the �lexical space� of {base type definition}"
24419 	*/
24420 	/*
24421 	* Whitespace-normalize.
24422 	*/
24423 	NORMALIZE(type);
24424 	if (type->type != XML_SCHEMA_TYPE_BASIC) {
24425 	    /*
24426 	    * Get the built-in type.
24427 	    */
24428 	    biType = type->baseType;
24429 	    while ((biType != NULL) &&
24430 		(biType->type != XML_SCHEMA_TYPE_BASIC))
24431 		biType = biType->baseType;
24432 
24433 	    if (biType == NULL) {
24434 		AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24435 		    "could not get the built-in type");
24436 		goto internal_error;
24437 	    }
24438 	} else
24439 	    biType = type;
24440 	/*
24441 	* NOTATIONs need to be processed here, since they need
24442 	* to lookup in the hashtable of NOTATION declarations of the schema.
24443 	*/
24444 	if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
24445 	    switch (biType->builtInType) {
24446 		case XML_SCHEMAS_NOTATION:
24447 		    ret = xmlSchemaValidateNotation(
24448 			(xmlSchemaValidCtxtPtr) actxt,
24449 			((xmlSchemaValidCtxtPtr) actxt)->schema,
24450 			NULL, value, &val, valNeeded);
24451 		    break;
24452 		case XML_SCHEMAS_QNAME:
24453 		    ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
24454 			value, &val, valNeeded);
24455 		    break;
24456 		default:
24457 		    /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24458 		    if (valNeeded)
24459 			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24460 			    value, &val, NULL);
24461 		    else
24462 			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24463 			    value, NULL, NULL);
24464 		    break;
24465 	    }
24466 	} else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
24467 	    switch (biType->builtInType) {
24468 		case XML_SCHEMAS_NOTATION:
24469 		    ret = xmlSchemaValidateNotation(NULL,
24470 			((xmlSchemaParserCtxtPtr) actxt)->schema, node,
24471 			value, &val, valNeeded);
24472 		    break;
24473 		default:
24474 		    /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24475 		    if (valNeeded)
24476 			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24477 			    value, &val, node);
24478 		    else
24479 			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24480 			    value, NULL, node);
24481 		    break;
24482 	    }
24483 	} else {
24484 	    /*
24485 	    * Validation via a public API is not implemented yet.
24486 	    */
24487 	    TODO
24488 	    goto internal_error;
24489 	}
24490 	if (ret != 0) {
24491 	    if (ret < 0) {
24492 		AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24493 		    "validating against a built-in type");
24494 		goto internal_error;
24495 	    }
24496 	    if (WXS_IS_LIST(type))
24497 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24498 	    else
24499 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24500 	}
24501 	if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24502 	    /*
24503 	    * Check facets.
24504 	    */
24505 	    ret = xmlSchemaValidateFacets(actxt, node, type,
24506 		(xmlSchemaValType) biType->builtInType, value, val,
24507 		0, fireErrors);
24508 	    if (ret != 0) {
24509 		if (ret < 0) {
24510 		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24511 			"validating facets of atomic simple type");
24512 		    goto internal_error;
24513 		}
24514 		if (WXS_IS_LIST(type))
24515 		    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24516 		else
24517 		    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24518 	    }
24519 	}
24520 	if (fireErrors && (ret > 0))
24521 	    xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24522     } else if (WXS_IS_LIST(type)) {
24523 
24524 	xmlSchemaTypePtr itemType;
24525 	const xmlChar *cur, *end;
24526 	xmlChar *tmpValue = NULL;
24527 	unsigned long len = 0;
24528 	xmlSchemaValPtr prevVal = NULL, curVal = NULL;
24529 	/* 1.2.2 if {variety} is �list� then the string must be a sequence
24530 	* of white space separated tokens, each of which �match�es a literal
24531 	* in the �lexical space� of {item type definition}
24532 	*/
24533 	/*
24534 	* Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
24535 	* the list type has an enum or pattern facet.
24536 	*/
24537 	NORMALIZE(type);
24538 	/*
24539 	* VAL TODO: Optimize validation of empty values.
24540 	* VAL TODO: We do not have computed values for lists.
24541 	*/
24542 	itemType = WXS_LIST_ITEMTYPE(type);
24543 	cur = value;
24544 	do {
24545 	    while (IS_BLANK_CH(*cur))
24546 		cur++;
24547 	    end = cur;
24548 	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
24549 		end++;
24550 	    if (end == cur)
24551 		break;
24552 	    tmpValue = xmlStrndup(cur, end - cur);
24553 	    len++;
24554 
24555 	    if (valNeeded)
24556 		ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24557 		    tmpValue, &curVal, fireErrors, 0, 1);
24558 	    else
24559 		ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24560 		    tmpValue, NULL, fireErrors, 0, 1);
24561 	    FREE_AND_NULL(tmpValue);
24562 	    if (curVal != NULL) {
24563 		/*
24564 		* Add to list of computed values.
24565 		*/
24566 		if (val == NULL)
24567 		    val = curVal;
24568 		else
24569 		    xmlSchemaValueAppend(prevVal, curVal);
24570 		prevVal = curVal;
24571 		curVal = NULL;
24572 	    }
24573 	    if (ret != 0) {
24574 		if (ret < 0) {
24575 		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24576 			"validating an item of list simple type");
24577 		    goto internal_error;
24578 		}
24579 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24580 		break;
24581 	    }
24582 	    cur = end;
24583 	} while (*cur != 0);
24584 	FREE_AND_NULL(tmpValue);
24585 	if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24586 	    /*
24587 	    * Apply facets (pattern, enumeration).
24588 	    */
24589 	    ret = xmlSchemaValidateFacets(actxt, node, type,
24590 		XML_SCHEMAS_UNKNOWN, value, val,
24591 		len, fireErrors);
24592 	    if (ret != 0) {
24593 		if (ret < 0) {
24594 		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24595 			"validating facets of list simple type");
24596 		    goto internal_error;
24597 		}
24598 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24599 	    }
24600 	}
24601 	if (fireErrors && (ret > 0)) {
24602 	    /*
24603 	    * Report the normalized value.
24604 	    */
24605 	    normalize = 1;
24606 	    NORMALIZE(type);
24607 	    xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24608 	}
24609     } else if (WXS_IS_UNION(type)) {
24610 	xmlSchemaTypeLinkPtr memberLink;
24611 	/*
24612 	* TODO: For all datatypes �derived� by �union�  whiteSpace does
24613 	* not apply directly; however, the normalization behavior of �union�
24614 	* types is controlled by the value of whiteSpace on that one of the
24615 	* �memberTypes� against which the �union� is successfully validated.
24616 	*
24617 	* This means that the value is normalized by the first validating
24618 	* member type, then the facets of the union type are applied. This
24619 	* needs changing of the value!
24620 	*/
24621 
24622 	/*
24623 	* 1.2.3 if {variety} is �union� then the string must �match� a
24624 	* literal in the �lexical space� of at least one member of
24625 	* {member type definitions}
24626 	*/
24627 	memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
24628 	if (memberLink == NULL) {
24629 	    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24630 		"union simple type has no member types");
24631 	    goto internal_error;
24632 	}
24633 	/*
24634 	* Always normalize union type values, since we currently
24635 	* cannot store the whitespace information with the value
24636 	* itself; otherwise a later value-comparison would be
24637 	* not possible.
24638 	*/
24639 	while (memberLink != NULL) {
24640 	    if (valNeeded)
24641 		ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24642 		    memberLink->type, value, &val, 0, 1, 0);
24643 	    else
24644 		ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24645 		    memberLink->type, value, NULL, 0, 1, 0);
24646 	    if (ret <= 0)
24647 		break;
24648 	    memberLink = memberLink->next;
24649 	}
24650 	if (ret != 0) {
24651 	    if (ret < 0) {
24652 		AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24653 		    "validating members of union simple type");
24654 		goto internal_error;
24655 	    }
24656 	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24657 	}
24658 	/*
24659 	* Apply facets (pattern, enumeration).
24660 	*/
24661 	if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24662 	    /*
24663 	    * The normalization behavior of �union� types is controlled by
24664 	    * the value of whiteSpace on that one of the �memberTypes�
24665 	    * against which the �union� is successfully validated.
24666 	    */
24667 	    NORMALIZE(memberLink->type);
24668 	    ret = xmlSchemaValidateFacets(actxt, node, type,
24669 		XML_SCHEMAS_UNKNOWN, value, val,
24670 		0, fireErrors);
24671 	    if (ret != 0) {
24672 		if (ret < 0) {
24673 		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24674 			"validating facets of union simple type");
24675 		    goto internal_error;
24676 		}
24677 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24678 	    }
24679 	}
24680 	if (fireErrors && (ret > 0))
24681 	    xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24682     }
24683 
24684     if (normValue != NULL)
24685 	xmlFree(normValue);
24686     if (ret == 0) {
24687 	if (retVal != NULL)
24688 	    *retVal = val;
24689 	else if (val != NULL)
24690 	    xmlSchemaFreeValue(val);
24691     } else if (val != NULL)
24692 	xmlSchemaFreeValue(val);
24693     return (ret);
24694 internal_error:
24695     if (normValue != NULL)
24696 	xmlFree(normValue);
24697     if (val != NULL)
24698 	xmlSchemaFreeValue(val);
24699     return (-1);
24700 }
24701 
24702 static int
24703 xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
24704 			   const xmlChar *value,
24705 			   const xmlChar **nsName,
24706 			   const xmlChar **localName)
24707 {
24708     int ret = 0;
24709 
24710     if ((nsName == NULL) || (localName == NULL))
24711 	return (-1);
24712     *nsName = NULL;
24713     *localName = NULL;
24714 
24715     ret = xmlValidateQName(value, 1);
24716     if (ret == -1)
24717 	return (-1);
24718     if (ret > 0) {
24719 	xmlSchemaSimpleTypeErr(ACTXT_CAST vctxt,
24720 	    XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24721 	    value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
24722 	return (1);
24723     }
24724     {
24725 	xmlChar *local = NULL;
24726 	xmlChar *prefix;
24727 
24728 	/*
24729 	* NOTE: xmlSplitQName2 will return a duplicated
24730 	* string.
24731 	*/
24732 	local = xmlSplitQName2(value, &prefix);
24733 	if (local == NULL)
24734 	    *localName = xmlDictLookup(vctxt->dict, value, -1);
24735 	else {
24736 	    *localName = xmlDictLookup(vctxt->dict, local, -1);
24737 	    xmlFree(local);
24738 	}
24739 
24740 	*nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24741 
24742 	if (prefix != NULL) {
24743 	    xmlFree(prefix);
24744 	    /*
24745 	    * A namespace must be found if the prefix is NOT NULL.
24746 	    */
24747 	    if (*nsName == NULL) {
24748 		xmlSchemaCustomErr(ACTXT_CAST vctxt,
24749 		    XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24750 		    WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24751 		    "The QName value '%s' has no "
24752 		    "corresponding namespace declaration in scope",
24753 		    value, NULL);
24754 		return (2);
24755 	    }
24756 	}
24757     }
24758     return (0);
24759 }
24760 
24761 static int
24762 xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
24763 			xmlSchemaAttrInfoPtr iattr,
24764 			xmlSchemaTypePtr *localType,
24765 			xmlSchemaElementPtr elemDecl)
24766 {
24767     int ret = 0;
24768     /*
24769     * cvc-elt (3.3.4) : (4)
24770     * AND
24771     * Schema-Validity Assessment (Element) (cvc-assess-elt)
24772     *   (1.2.1.2.1) - (1.2.1.2.4)
24773     * Handle 'xsi:type'.
24774     */
24775     if (localType == NULL)
24776 	return (-1);
24777     *localType = NULL;
24778     if (iattr == NULL)
24779 	return (0);
24780     else {
24781 	const xmlChar *nsName = NULL, *local = NULL;
24782 	/*
24783 	* TODO: We should report a *warning* that the type was overriden
24784 	* by the instance.
24785 	*/
24786 	ACTIVATE_ATTRIBUTE(iattr);
24787 	/*
24788 	* (cvc-elt) (3.3.4) : (4.1)
24789 	* (cvc-assess-elt) (1.2.1.2.2)
24790 	*/
24791 	ret = xmlSchemaVExpandQName(vctxt, iattr->value,
24792 	    &nsName, &local);
24793 	if (ret != 0) {
24794 	    if (ret < 0) {
24795 		VERROR_INT("xmlSchemaValidateElementByDeclaration",
24796 		    "calling xmlSchemaQNameExpand() to validate the "
24797 		    "attribute 'xsi:type'");
24798 		goto internal_error;
24799 	    }
24800 	    goto exit;
24801 	}
24802 	/*
24803 	* (cvc-elt) (3.3.4) : (4.2)
24804 	* (cvc-assess-elt) (1.2.1.2.3)
24805 	*/
24806 	*localType = xmlSchemaGetType(vctxt->schema, local, nsName);
24807 	if (*localType == NULL) {
24808 	    xmlChar *str = NULL;
24809 
24810 	    xmlSchemaCustomErr(ACTXT_CAST vctxt,
24811 		XML_SCHEMAV_CVC_ELT_4_2, NULL,
24812 		WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24813 		"The QName value '%s' of the xsi:type attribute does not "
24814 		"resolve to a type definition",
24815 		xmlSchemaFormatQName(&str, nsName, local), NULL);
24816 	    FREE_AND_NULL(str);
24817 	    ret = vctxt->err;
24818 	    goto exit;
24819 	}
24820 	if (elemDecl != NULL) {
24821 	    int set = 0;
24822 
24823 	    /*
24824 	    * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
24825 	    * "The �local type definition� must be validly
24826 	    * derived from the {type definition} given the union of
24827 	    * the {disallowed substitutions} and the {type definition}'s
24828 	    * {prohibited substitutions}, as defined in
24829 	    * Type Derivation OK (Complex) (�3.4.6)
24830 	    * (if it is a complex type definition),
24831 	    * or given {disallowed substitutions} as defined in Type
24832 	    * Derivation OK (Simple) (�3.14.6) (if it is a simple type
24833 	    * definition)."
24834 	    *
24835 	    * {disallowed substitutions}: the "block" on the element decl.
24836 	    * {prohibited substitutions}: the "block" on the type def.
24837 	    */
24838 	    /*
24839 	    * OPTIMIZE TODO: We could map types already evaluated
24840 	    * to be validly derived from other types to avoid checking
24841 	    * this over and over for the same types.
24842 	    */
24843 	    if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
24844 		(elemDecl->subtypes->flags &
24845 		    XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
24846 		set |= SUBSET_EXTENSION;
24847 
24848 	    if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
24849 		(elemDecl->subtypes->flags &
24850 		    XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
24851 		set |= SUBSET_RESTRICTION;
24852 
24853 	    /*
24854 	    * REMOVED and CHANGED since this produced a parser context
24855 	    * which adds to the string dict of the schema. So this would
24856 	    * change the schema and we don't want this. We don't need
24857 	    * the parser context anymore.
24858 	    *
24859 	    * if ((vctxt->pctxt == NULL) &&
24860 	    *	(xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
24861 	    *	    return (-1);
24862 	    */
24863 
24864 	    if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST vctxt, *localType,
24865 		elemDecl->subtypes, set) != 0) {
24866 		xmlChar *str = NULL;
24867 
24868 		xmlSchemaCustomErr(ACTXT_CAST vctxt,
24869 		    XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
24870 		    "The type definition '%s', specified by xsi:type, is "
24871 		    "blocked or not validly derived from the type definition "
24872 		    "of the element declaration",
24873 		    xmlSchemaFormatQName(&str,
24874 			(*localType)->targetNamespace,
24875 			(*localType)->name),
24876 		    NULL);
24877 		FREE_AND_NULL(str);
24878 		ret = vctxt->err;
24879 		*localType = NULL;
24880 	    }
24881 	}
24882     }
24883 exit:
24884     ACTIVATE_ELEM;
24885     return (ret);
24886 internal_error:
24887     ACTIVATE_ELEM;
24888     return (-1);
24889 }
24890 
24891 static int
24892 xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
24893 {
24894     xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
24895     xmlSchemaTypePtr actualType;
24896 
24897     /*
24898     * cvc-elt (3.3.4) : 1
24899     */
24900     if (elemDecl == NULL) {
24901 	VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
24902 	    "No matching declaration available");
24903         return (vctxt->err);
24904     }
24905     actualType = WXS_ELEM_TYPEDEF(elemDecl);
24906     /*
24907     * cvc-elt (3.3.4) : 2
24908     */
24909     if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
24910 	VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
24911 	    "The element declaration is abstract");
24912         return (vctxt->err);
24913     }
24914     if (actualType == NULL) {
24915     	VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
24916     	    "The type definition is absent");
24917     	return (XML_SCHEMAV_CVC_TYPE_1);
24918     }
24919     if (vctxt->nbAttrInfos != 0) {
24920 	int ret;
24921 	xmlSchemaAttrInfoPtr iattr;
24922 	/*
24923 	* cvc-elt (3.3.4) : 3
24924 	* Handle 'xsi:nil'.
24925 	*/
24926 	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
24927 	    XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
24928 	if (iattr) {
24929 	    ACTIVATE_ATTRIBUTE(iattr);
24930 	    /*
24931 	    * Validate the value.
24932 	    */
24933 	    ret = xmlSchemaVCheckCVCSimpleType(
24934 		ACTXT_CAST vctxt, NULL,
24935 		xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
24936 		iattr->value, &(iattr->val), 1, 0, 0);
24937 	    ACTIVATE_ELEM;
24938 	    if (ret < 0) {
24939 		VERROR_INT("xmlSchemaValidateElemDecl",
24940 		    "calling xmlSchemaVCheckCVCSimpleType() to "
24941 		    "validate the attribute 'xsi:nil'");
24942 		return (-1);
24943 	    }
24944 	    if (ret == 0) {
24945 		if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
24946 		    /*
24947 		    * cvc-elt (3.3.4) : 3.1
24948 		    */
24949 		    VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
24950 			"The element is not 'nillable'");
24951 		    /* Does not return an error on purpose. */
24952 		} else {
24953 		    if (xmlSchemaValueGetAsBoolean(iattr->val)) {
24954 			/*
24955 			* cvc-elt (3.3.4) : 3.2.2
24956 			*/
24957 			if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
24958 			    (elemDecl->value != NULL)) {
24959 			    VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
24960 				"The element cannot be 'nilled' because "
24961 				"there is a fixed value constraint defined "
24962 				"for it");
24963 			     /* Does not return an error on purpose. */
24964 			} else
24965 			    vctxt->inode->flags |=
24966 				XML_SCHEMA_ELEM_INFO_NILLED;
24967 		    }
24968 		}
24969 	    }
24970 	}
24971 	/*
24972 	* cvc-elt (3.3.4) : 4
24973 	* Handle 'xsi:type'.
24974 	*/
24975 	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
24976 	    XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
24977 	if (iattr) {
24978 	    xmlSchemaTypePtr localType = NULL;
24979 
24980 	    ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
24981 		elemDecl);
24982 	    if (ret != 0) {
24983 		if (ret == -1) {
24984 		    VERROR_INT("xmlSchemaValidateElemDecl",
24985 			"calling xmlSchemaProcessXSIType() to "
24986 			"process the attribute 'xsi:type'");
24987 		    return (-1);
24988 		}
24989 		/* Does not return an error on purpose. */
24990 	    }
24991 	    if (localType != NULL) {
24992 		vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
24993 		actualType = localType;
24994 	    }
24995 	}
24996     }
24997     /*
24998     * IDC: Register identity-constraint XPath matchers.
24999     */
25000     if ((elemDecl->idcs != NULL) &&
25001 	(xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
25002 	    return (-1);
25003     /*
25004     * No actual type definition.
25005     */
25006     if (actualType == NULL) {
25007     	VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
25008     	    "The type definition is absent");
25009     	return (XML_SCHEMAV_CVC_TYPE_1);
25010     }
25011     /*
25012     * Remember the actual type definition.
25013     */
25014     vctxt->inode->typeDef = actualType;
25015 
25016     return (0);
25017 }
25018 
25019 static int
25020 xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
25021 {
25022     xmlSchemaAttrInfoPtr iattr;
25023     int ret = 0, i;
25024 
25025     /*
25026     * SPEC cvc-type (3.1.1)
25027     * "The attributes of must be empty, excepting those whose namespace
25028     * name is identical to http://www.w3.org/2001/XMLSchema-instance and
25029     * whose local name is one of type, nil, schemaLocation or
25030     * noNamespaceSchemaLocation."
25031     */
25032     if (vctxt->nbAttrInfos == 0)
25033 	return (0);
25034     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25035 	iattr = vctxt->attrInfos[i];
25036 	if (! iattr->metaType) {
25037 	    ACTIVATE_ATTRIBUTE(iattr)
25038 	    xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25039 		XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
25040 	    ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
25041         }
25042     }
25043     ACTIVATE_ELEM
25044     return (ret);
25045 }
25046 
25047 /*
25048 * Cleanup currently used attribute infos.
25049 */
25050 static void
25051 xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
25052 {
25053     int i;
25054     xmlSchemaAttrInfoPtr attr;
25055 
25056     if (vctxt->nbAttrInfos == 0)
25057 	return;
25058     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25059 	attr = vctxt->attrInfos[i];
25060 	if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
25061 	    if (attr->localName != NULL)
25062 		xmlFree((xmlChar *) attr->localName);
25063 	    if (attr->nsName != NULL)
25064 		xmlFree((xmlChar *) attr->nsName);
25065 	}
25066 	if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
25067 	    if (attr->value != NULL)
25068 		xmlFree((xmlChar *) attr->value);
25069 	}
25070 	if (attr->val != NULL) {
25071 	    xmlSchemaFreeValue(attr->val);
25072 	    attr->val = NULL;
25073 	}
25074 	memset(attr, 0, sizeof(xmlSchemaAttrInfo));
25075     }
25076     vctxt->nbAttrInfos = 0;
25077 }
25078 
25079 /*
25080 * 3.4.4 Complex Type Definition Validation Rules
25081 *   Element Locally Valid (Complex Type) (cvc-complex-type)
25082 * 3.2.4 Attribute Declaration Validation Rules
25083 *   Validation Rule: Attribute Locally Valid (cvc-attribute)
25084 *   Attribute Locally Valid (Use) (cvc-au)
25085 *
25086 * Only "assessed" attribute information items will be visible to
25087 * IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
25088 */
25089 static int
25090 xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
25091 {
25092     xmlSchemaTypePtr type = vctxt->inode->typeDef;
25093     xmlSchemaItemListPtr attrUseList;
25094     xmlSchemaAttributeUsePtr attrUse = NULL;
25095     xmlSchemaAttributePtr attrDecl = NULL;
25096     xmlSchemaAttrInfoPtr iattr, tmpiattr;
25097     int i, j, found, nbAttrs, nbUses;
25098     int xpathRes = 0, res, wildIDs = 0, fixed;
25099     xmlNodePtr defAttrOwnerElem = NULL;
25100 
25101     /*
25102     * SPEC (cvc-attribute)
25103     * (1) "The declaration must not be �absent� (see Missing
25104     * Sub-components (�5.3) for how this can fail to be
25105     * the case)."
25106     * (2) "Its {type definition} must not be absent."
25107     *
25108     * NOTE (1) + (2): This is not handled here, since we currently do not
25109     * allow validation against schemas which have missing sub-components.
25110     *
25111     * SPEC (cvc-complex-type)
25112     * (3) "For each attribute information item in the element information
25113     * item's [attributes] excepting those whose [namespace name] is
25114     * identical to http://www.w3.org/2001/XMLSchema-instance and whose
25115     * [local name] is one of type, nil, schemaLocation or
25116     * noNamespaceSchemaLocation, the appropriate case among the following
25117     * must be true:
25118     *
25119     */
25120     attrUseList = (xmlSchemaItemListPtr) type->attrUses;
25121     /*
25122     * @nbAttrs is the number of attributes present in the instance.
25123     */
25124     nbAttrs = vctxt->nbAttrInfos;
25125     if (attrUseList != NULL)
25126 	nbUses = attrUseList->nbItems;
25127     else
25128 	nbUses = 0;
25129     for (i = 0; i < nbUses; i++) {
25130         found = 0;
25131 	attrUse = attrUseList->items[i];
25132 	attrDecl = WXS_ATTRUSE_DECL(attrUse);
25133         for (j = 0; j < nbAttrs; j++) {
25134 	    iattr = vctxt->attrInfos[j];
25135 	    /*
25136 	    * SPEC (cvc-complex-type) (3)
25137 	    * Skip meta attributes.
25138 	    */
25139 	    if (iattr->metaType)
25140 		continue;
25141 	    if (iattr->localName[0] != attrDecl->name[0])
25142 		continue;
25143 	    if (!xmlStrEqual(iattr->localName, attrDecl->name))
25144 		continue;
25145 	    if (!xmlStrEqual(iattr->nsName, attrDecl->targetNamespace))
25146 		continue;
25147 	    found = 1;
25148 	    /*
25149 	    * SPEC (cvc-complex-type)
25150 	    * (3.1) "If there is among the {attribute uses} an attribute
25151 	    * use with an {attribute declaration} whose {name} matches
25152 	    * the attribute information item's [local name] and whose
25153 	    * {target namespace} is identical to the attribute information
25154 	    * item's [namespace name] (where an �absent� {target namespace}
25155 	    * is taken to be identical to a [namespace name] with no value),
25156 	    * then the attribute information must be �valid� with respect
25157 	    * to that attribute use as per Attribute Locally Valid (Use)
25158 	    * (�3.5.4). In this case the {attribute declaration} of that
25159 	    * attribute use is the �context-determined declaration� for the
25160 	    * attribute information item with respect to Schema-Validity
25161 	    * Assessment (Attribute) (�3.2.4) and
25162 	    * Assessment Outcome (Attribute) (�3.2.5).
25163 	    */
25164 	    iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25165 	    iattr->use = attrUse;
25166 	    /*
25167 	    * Context-determined declaration.
25168 	    */
25169 	    iattr->decl = attrDecl;
25170 	    iattr->typeDef = attrDecl->subtypes;
25171 	    break;
25172 	}
25173 
25174 	if (found)
25175 	    continue;
25176 
25177 	if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
25178 	    /*
25179 	    * Handle non-existent, required attributes.
25180 	    *
25181 	    * SPEC (cvc-complex-type)
25182 	    * (4) "The {attribute declaration} of each attribute use in
25183 	    * the {attribute uses} whose {required} is true matches one
25184 	    * of the attribute information items in the element information
25185 	    * item's [attributes] as per clause 3.1 above."
25186 	    */
25187 	    tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25188 	    if (tmpiattr == NULL) {
25189 		VERROR_INT(
25190 		    "xmlSchemaVAttributesComplex",
25191 		    "calling xmlSchemaGetFreshAttrInfo()");
25192 		return (-1);
25193 	    }
25194 	    tmpiattr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
25195 	    tmpiattr->use = attrUse;
25196 	    tmpiattr->decl = attrDecl;
25197 	} else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
25198 	    ((attrUse->defValue != NULL) ||
25199 	     (attrDecl->defValue != NULL))) {
25200 	    /*
25201 	    * Handle non-existent, optional, default/fixed attributes.
25202 	    */
25203 	    tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25204 	    if (tmpiattr == NULL) {
25205 		VERROR_INT(
25206 		    "xmlSchemaVAttributesComplex",
25207 		    "calling xmlSchemaGetFreshAttrInfo()");
25208 		return (-1);
25209 	    }
25210 	    tmpiattr->state = XML_SCHEMAS_ATTR_DEFAULT;
25211 	    tmpiattr->use = attrUse;
25212 	    tmpiattr->decl = attrDecl;
25213 	    tmpiattr->typeDef = attrDecl->subtypes;
25214 	    tmpiattr->localName = attrDecl->name;
25215 	    tmpiattr->nsName = attrDecl->targetNamespace;
25216 	}
25217     }
25218 
25219     if (vctxt->nbAttrInfos == 0)
25220 	return (0);
25221     nbUses = vctxt->nbAttrInfos;
25222     /*
25223     * Validate against the wildcard.
25224     */
25225     if (type->attributeWildcard != NULL) {
25226 	/*
25227 	* SPEC (cvc-complex-type)
25228 	* (3.2.1) "There must be an {attribute wildcard}."
25229 	*/
25230 	for (i = 0; i < nbAttrs; i++) {
25231 	    iattr = vctxt->attrInfos[i];
25232 	    /*
25233 	    * SPEC (cvc-complex-type) (3)
25234 	    * Skip meta attributes.
25235 	    */
25236 	    if (iattr->state != XML_SCHEMAS_ATTR_UNKNOWN)
25237 		continue;
25238 	    /*
25239 	    * SPEC (cvc-complex-type)
25240 	    * (3.2.2) "The attribute information item must be �valid� with
25241 	    * respect to it as defined in Item Valid (Wildcard) (�3.10.4)."
25242 	    *
25243 	    * SPEC Item Valid (Wildcard) (cvc-wildcard)
25244 	    * "... its [namespace name] must be �valid� with respect to
25245 	    * the wildcard constraint, as defined in Wildcard allows
25246 	    * Namespace Name (�3.10.4)."
25247 	    */
25248 	    if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
25249 		    iattr->nsName) == 0) {
25250 		/*
25251 		* Handle processContents.
25252 		*
25253 		* SPEC (cvc-wildcard):
25254 		* processContents | context-determined declaration:
25255 		* "strict"          "mustFind"
25256 		* "lax"             "none"
25257 		* "skip"            "skip"
25258 		*/
25259 		if (type->attributeWildcard->processContents ==
25260 		    XML_SCHEMAS_ANY_SKIP) {
25261 		     /*
25262 		    * context-determined declaration = "skip"
25263 		    *
25264 		    * SPEC PSVI Assessment Outcome (Attribute)
25265 		    * [validity] = "notKnown"
25266 		    * [validation attempted] = "none"
25267 		    */
25268 		    iattr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
25269 		    continue;
25270 		}
25271 		/*
25272 		* Find an attribute declaration.
25273 		*/
25274 		iattr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
25275 		    iattr->localName, iattr->nsName);
25276 		if (iattr->decl != NULL) {
25277 		    iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25278 		    /*
25279 		    * SPEC (cvc-complex-type)
25280 		    * (5) "Let [Definition:]  the wild IDs be the set of
25281 		    * all attribute information item to which clause 3.2
25282 		    * applied and whose �validation� resulted in a
25283 		    * �context-determined declaration� of mustFind or no
25284 		    * �context-determined declaration� at all, and whose
25285 		    * [local name] and [namespace name] resolve (as
25286 		    * defined by QName resolution (Instance) (�3.15.4)) to
25287 		    * an attribute declaration whose {type definition} is
25288 		    * or is derived from ID. Then all of the following
25289 		    * must be true:"
25290 		    */
25291 		    iattr->typeDef = WXS_ATTR_TYPEDEF(iattr->decl);
25292 		    if (xmlSchemaIsDerivedFromBuiltInType(
25293 			iattr->typeDef, XML_SCHEMAS_ID)) {
25294 			/*
25295 			* SPEC (5.1) "There must be no more than one
25296 			* item in �wild IDs�."
25297 			*/
25298 			if (wildIDs != 0) {
25299 			    /* VAL TODO */
25300 			    iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
25301 			    TODO
25302 			    continue;
25303 			}
25304 			wildIDs++;
25305 			/*
25306 			* SPEC (cvc-complex-type)
25307 			* (5.2) "If �wild IDs� is non-empty, there must not
25308 			* be any attribute uses among the {attribute uses}
25309 			* whose {attribute declaration}'s {type definition}
25310 			* is or is derived from ID."
25311 			*/
25312 			for (j = 0; j < attrUseList->nbItems; j++) {
25313 			    if (xmlSchemaIsDerivedFromBuiltInType(
25314 				WXS_ATTRUSE_TYPEDEF(attrUseList->items[j]),
25315 				XML_SCHEMAS_ID)) {
25316 				/* URGENT VAL TODO: implement */
25317 				iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
25318 				TODO
25319 				break;
25320 			    }
25321 			}
25322 		    }
25323 		} else if (type->attributeWildcard->processContents ==
25324 		    XML_SCHEMAS_ANY_LAX) {
25325 		    iattr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
25326 		    /*
25327 		    * SPEC PSVI Assessment Outcome (Attribute)
25328 		    * [validity] = "notKnown"
25329 		    * [validation attempted] = "none"
25330 		    */
25331 		} else {
25332 		    iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
25333 		}
25334 	    }
25335 	}
25336     }
25337 
25338     if (vctxt->nbAttrInfos == 0)
25339 	return (0);
25340 
25341     /*
25342     * Get the owner element; needed for creation of default attributes.
25343     * This fixes bug #341337, reported by David Grohmann.
25344     */
25345     if (vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
25346 	xmlSchemaNodeInfoPtr ielem = vctxt->elemInfos[vctxt->depth];
25347 	if (ielem && ielem->node && ielem->node->doc)
25348 	    defAttrOwnerElem = ielem->node;
25349     }
25350     /*
25351     * Validate values, create default attributes, evaluate IDCs.
25352     */
25353     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25354 	iattr = vctxt->attrInfos[i];
25355 	/*
25356 	* VAL TODO: Note that we won't try to resolve IDCs to
25357 	* "lax" and "skip" validated attributes. Check what to
25358 	* do in this case.
25359 	*/
25360 	if ((iattr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
25361 	    (iattr->state != XML_SCHEMAS_ATTR_DEFAULT))
25362 	    continue;
25363 	/*
25364 	* VAL TODO: What to do if the type definition is missing?
25365 	*/
25366 	if (iattr->typeDef == NULL) {
25367 	    iattr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
25368 	    continue;
25369 	}
25370 
25371 	ACTIVATE_ATTRIBUTE(iattr);
25372 	fixed = 0;
25373 	xpathRes = 0;
25374 
25375 	if (vctxt->xpathStates != NULL) {
25376 	    /*
25377 	    * Evaluate IDCs.
25378 	    */
25379 	    xpathRes = xmlSchemaXPathEvaluate(vctxt,
25380 		XML_ATTRIBUTE_NODE);
25381 	    if (xpathRes == -1) {
25382 		VERROR_INT("xmlSchemaVAttributesComplex",
25383 		    "calling xmlSchemaXPathEvaluate()");
25384 		goto internal_error;
25385 	    }
25386 	}
25387 
25388 	if (iattr->state == XML_SCHEMAS_ATTR_DEFAULT) {
25389 	    /*
25390 	    * Default/fixed attributes.
25391 	    * We need the value only if we need to resolve IDCs or
25392 	    * will create default attributes.
25393 	    */
25394 	    if ((xpathRes) || (defAttrOwnerElem)) {
25395 		if (iattr->use->defValue != NULL) {
25396 		    iattr->value = (xmlChar *) iattr->use->defValue;
25397 		    iattr->val = iattr->use->defVal;
25398 		} else {
25399 		    iattr->value = (xmlChar *) iattr->decl->defValue;
25400 		    iattr->val = iattr->decl->defVal;
25401 		}
25402 		/*
25403 		* IDCs will consume the precomputed default value,
25404 		* so we need to clone it.
25405 		*/
25406 		if (iattr->val == NULL) {
25407 		    VERROR_INT("xmlSchemaVAttributesComplex",
25408 			"default/fixed value on an attribute use was "
25409 			"not precomputed");
25410 		    goto internal_error;
25411 		}
25412 		iattr->val = xmlSchemaCopyValue(iattr->val);
25413 		if (iattr->val == NULL) {
25414 		    VERROR_INT("xmlSchemaVAttributesComplex",
25415 			"calling xmlSchemaCopyValue()");
25416 		    goto internal_error;
25417 		}
25418 	    }
25419 	    /*
25420 	    * PSVI: Add the default attribute to the current element.
25421 	    * VAL TODO: Should we use the *normalized* value? This currently
25422 	    *   uses the *initial* value.
25423 	    */
25424 
25425 	    if (defAttrOwnerElem) {
25426 		xmlChar *normValue;
25427 		const xmlChar *value;
25428 
25429 		value = iattr->value;
25430 		/*
25431 		* Normalize the value.
25432 		*/
25433 		normValue = xmlSchemaNormalizeValue(iattr->typeDef,
25434 		    iattr->value);
25435 		if (normValue != NULL)
25436 		    value = BAD_CAST normValue;
25437 
25438 		if (iattr->nsName == NULL) {
25439 		    if (xmlNewProp(defAttrOwnerElem,
25440 			iattr->localName, value) == NULL) {
25441 			VERROR_INT("xmlSchemaVAttributesComplex",
25442 			    "callling xmlNewProp()");
25443 			if (normValue != NULL)
25444 			    xmlFree(normValue);
25445 			goto internal_error;
25446 		    }
25447 		} else {
25448 		    xmlNsPtr ns;
25449 
25450 		    ns = xmlSearchNsByHref(defAttrOwnerElem->doc,
25451 			defAttrOwnerElem, iattr->nsName);
25452 		    if (ns == NULL) {
25453 			xmlChar prefix[12];
25454 			int counter = 0;
25455 
25456 			/*
25457 			* Create a namespace declaration on the validation
25458 			* root node if no namespace declaration is in scope.
25459 			*/
25460 			do {
25461 			    snprintf((char *) prefix, 12, "p%d", counter++);
25462 			    ns = xmlSearchNs(defAttrOwnerElem->doc,
25463 				defAttrOwnerElem, BAD_CAST prefix);
25464 			    if (counter > 1000) {
25465 				VERROR_INT(
25466 				    "xmlSchemaVAttributesComplex",
25467 				    "could not compute a ns prefix for a "
25468 				    "default/fixed attribute");
25469 				if (normValue != NULL)
25470 				    xmlFree(normValue);
25471 				goto internal_error;
25472 			    }
25473 			} while (ns != NULL);
25474 			ns = xmlNewNs(vctxt->validationRoot,
25475 			    iattr->nsName, BAD_CAST prefix);
25476 		    }
25477 		    /*
25478 		    * TODO:
25479 		    * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0406.html
25480 		    * If we have QNames: do we need to ensure there's a
25481 		    * prefix defined for the QName?
25482 		    */
25483 		    xmlNewNsProp(defAttrOwnerElem, ns, iattr->localName, value);
25484 		}
25485 		if (normValue != NULL)
25486 		    xmlFree(normValue);
25487 	    }
25488 	    /*
25489 	    * Go directly to IDC evaluation.
25490 	    */
25491 	    goto eval_idcs;
25492 	}
25493 	/*
25494 	* Validate the value.
25495 	*/
25496 	if (vctxt->value != NULL) {
25497 	    /*
25498 	    * Free last computed value; just for safety reasons.
25499 	    */
25500 	    xmlSchemaFreeValue(vctxt->value);
25501 	    vctxt->value = NULL;
25502 	}
25503 	/*
25504 	* Note that the attribute *use* can be unavailable, if
25505 	* the attribute was a wild attribute.
25506 	*/
25507 	if ((iattr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
25508 	    ((iattr->use != NULL) &&
25509 	     (iattr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
25510 	    fixed = 1;
25511 	else
25512 	    fixed = 0;
25513 	/*
25514 	* SPEC (cvc-attribute)
25515 	* (3) "The item's �normalized value� must be locally �valid�
25516 	* with respect to that {type definition} as per
25517 	* String Valid (�3.14.4)."
25518 	*
25519 	* VAL TODO: Do we already have the
25520 	* "normalized attribute value" here?
25521 	*/
25522 	if (xpathRes || fixed) {
25523 	    iattr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
25524 	    /*
25525 	    * Request a computed value.
25526 	    */
25527 	    res = xmlSchemaVCheckCVCSimpleType(
25528 		ACTXT_CAST vctxt,
25529 		iattr->node, iattr->typeDef, iattr->value, &(iattr->val),
25530 		1, 1, 0);
25531 	} else {
25532 	    res = xmlSchemaVCheckCVCSimpleType(
25533 		ACTXT_CAST vctxt,
25534 		iattr->node, iattr->typeDef, iattr->value, NULL,
25535 		1, 0, 0);
25536 	}
25537 
25538 	if (res != 0) {
25539 	    if (res == -1) {
25540 		VERROR_INT("xmlSchemaVAttributesComplex",
25541 		    "calling xmlSchemaStreamValidateSimpleTypeValue()");
25542 		goto internal_error;
25543 	    }
25544 	    iattr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
25545 	    /*
25546 	    * SPEC PSVI Assessment Outcome (Attribute)
25547 	    * [validity] = "invalid"
25548 	    */
25549 	    goto eval_idcs;
25550 	}
25551 
25552 	if (fixed) {
25553 	    /*
25554 	    * SPEC Attribute Locally Valid (Use) (cvc-au)
25555 	    * "For an attribute information item to be�valid�
25556 	    * with respect to an attribute use its *normalized*
25557 	    * value� must match the *canonical* lexical
25558 	    * representation of the attribute use's {value
25559 	    * constraint}value, if it is present and fixed."
25560 	    *
25561 	    * VAL TODO: The requirement for the *canonical* value
25562 	    * will be removed in XML Schema 1.1.
25563 	    */
25564 	    /*
25565 	    * SPEC Attribute Locally Valid (cvc-attribute)
25566 	    * (4) "The item's *actual* value� must match the *value* of
25567 	    * the {value constraint}, if it is present and fixed."
25568 	    */
25569 	    if (iattr->val == NULL) {
25570 		/* VAL TODO: A value was not precomputed. */
25571 		TODO
25572 		goto eval_idcs;
25573 	    }
25574 	    if ((iattr->use != NULL) &&
25575 		(iattr->use->defValue != NULL)) {
25576 		if (iattr->use->defVal == NULL) {
25577 		    /* VAL TODO: A default value was not precomputed. */
25578 		    TODO
25579 		    goto eval_idcs;
25580 		}
25581 		iattr->vcValue = iattr->use->defValue;
25582 		/*
25583 		if (xmlSchemaCompareValuesWhtsp(attr->val,
25584 		    (xmlSchemaWhitespaceValueType) ws,
25585 		    attr->use->defVal,
25586 		    (xmlSchemaWhitespaceValueType) ws) != 0) {
25587 		*/
25588 		if (! xmlSchemaAreValuesEqual(iattr->val, iattr->use->defVal))
25589 		    iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25590 	    } else {
25591 		if (iattr->decl->defVal == NULL) {
25592 		    /* VAL TODO: A default value was not precomputed. */
25593 		    TODO
25594 		    goto eval_idcs;
25595 		}
25596 		iattr->vcValue = iattr->decl->defValue;
25597 		/*
25598 		if (xmlSchemaCompareValuesWhtsp(attr->val,
25599 		    (xmlSchemaWhitespaceValueType) ws,
25600 		    attrDecl->defVal,
25601 		    (xmlSchemaWhitespaceValueType) ws) != 0) {
25602 		*/
25603 		if (! xmlSchemaAreValuesEqual(iattr->val, iattr->decl->defVal))
25604 		    iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25605 	    }
25606 	    /*
25607 	    * [validity] = "valid"
25608 	    */
25609 	}
25610 eval_idcs:
25611 	/*
25612 	* Evaluate IDCs.
25613 	*/
25614 	if (xpathRes) {
25615 	    if (xmlSchemaXPathProcessHistory(vctxt,
25616 		vctxt->depth +1) == -1) {
25617 		VERROR_INT("xmlSchemaVAttributesComplex",
25618 		    "calling xmlSchemaXPathEvaluate()");
25619 		goto internal_error;
25620 	    }
25621 	} else if (vctxt->xpathStates != NULL)
25622 	    xmlSchemaXPathPop(vctxt);
25623     }
25624 
25625     /*
25626     * Report errors.
25627     */
25628     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25629 	iattr = vctxt->attrInfos[i];
25630 	if ((iattr->state == XML_SCHEMAS_ATTR_META) ||
25631 	    (iattr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
25632 	    (iattr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
25633 	    (iattr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
25634 	    continue;
25635 	ACTIVATE_ATTRIBUTE(iattr);
25636 	switch (iattr->state) {
25637 	    case XML_SCHEMAS_ATTR_ERR_MISSING: {
25638 		    xmlChar *str = NULL;
25639 		    ACTIVATE_ELEM;
25640 		    xmlSchemaCustomErr(ACTXT_CAST vctxt,
25641 			XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
25642 			"The attribute '%s' is required but missing",
25643 			xmlSchemaFormatQName(&str,
25644 			    iattr->decl->targetNamespace,
25645 			    iattr->decl->name),
25646 			NULL);
25647 		    FREE_AND_NULL(str)
25648 		    break;
25649 		}
25650 	    case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
25651 		VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
25652 		    "The type definition is absent");
25653 		break;
25654 	    case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
25655 		xmlSchemaCustomErr(ACTXT_CAST vctxt,
25656 		    XML_SCHEMAV_CVC_AU, NULL, NULL,
25657 		    "The value '%s' does not match the fixed "
25658 		    "value constraint '%s'",
25659 		    iattr->value, iattr->vcValue);
25660 		break;
25661 	    case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
25662 		VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
25663 		    "No matching global attribute declaration available, but "
25664 		    "demanded by the strict wildcard");
25665 		break;
25666 	    case XML_SCHEMAS_ATTR_UNKNOWN:
25667 		if (iattr->metaType)
25668 		    break;
25669 		/*
25670 		* MAYBE VAL TODO: One might report different error messages
25671 		* for the following errors.
25672 		*/
25673 		if (type->attributeWildcard == NULL) {
25674 		    xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25675 			XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, iattr, NULL);
25676 		} else {
25677 		    xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25678 			XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, iattr, NULL);
25679 		}
25680 		break;
25681 	    default:
25682 		break;
25683 	}
25684     }
25685 
25686     ACTIVATE_ELEM;
25687     return (0);
25688 internal_error:
25689     ACTIVATE_ELEM;
25690     return (-1);
25691 }
25692 
25693 static int
25694 xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
25695 			      int *skip)
25696 {
25697     xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
25698     /*
25699     * The namespace of the element was already identified to be
25700     * matching the wildcard.
25701     */
25702     if ((skip == NULL) || (wild == NULL) ||
25703 	(wild->type != XML_SCHEMA_TYPE_ANY)) {
25704 	VERROR_INT("xmlSchemaValidateElemWildcard",
25705 	    "bad arguments");
25706 	return (-1);
25707     }
25708     *skip = 0;
25709     if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
25710 	/*
25711 	* URGENT VAL TODO: Either we need to position the stream to the
25712 	* next sibling, or walk the whole subtree.
25713 	*/
25714 	*skip = 1;
25715 	return (0);
25716     }
25717     {
25718 	xmlSchemaElementPtr decl = NULL;
25719 
25720 	decl = xmlSchemaGetElem(vctxt->schema,
25721 	    vctxt->inode->localName, vctxt->inode->nsName);
25722 	if (decl != NULL) {
25723 	    vctxt->inode->decl = decl;
25724 	    return (0);
25725 	}
25726     }
25727     if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
25728 	/* VAL TODO: Change to proper error code. */
25729 	VERROR(XML_SCHEMAV_CVC_ELT_1, NULL, /* WXS_BASIC_CAST wild */
25730 	    "No matching global element declaration available, but "
25731 	    "demanded by the strict wildcard");
25732 	return (vctxt->err);
25733     }
25734     if (vctxt->nbAttrInfos != 0) {
25735 	xmlSchemaAttrInfoPtr iattr;
25736 	/*
25737 	* SPEC Validation Rule: Schema-Validity Assessment (Element)
25738 	* (1.2.1.2.1) - (1.2.1.2.3 )
25739 	*
25740 	* Use the xsi:type attribute for the type definition.
25741 	*/
25742 	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25743 	    XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25744 	if (iattr != NULL) {
25745 	    if (xmlSchemaProcessXSIType(vctxt, iattr,
25746 		&(vctxt->inode->typeDef), NULL) == -1) {
25747 		VERROR_INT("xmlSchemaValidateElemWildcard",
25748 		    "calling xmlSchemaProcessXSIType() to "
25749 		    "process the attribute 'xsi:nil'");
25750 		return (-1);
25751 	    }
25752 	    /*
25753 	    * Don't return an error on purpose.
25754 	    */
25755 	    return (0);
25756 	}
25757     }
25758     /*
25759     * SPEC Validation Rule: Schema-Validity Assessment (Element)
25760     *
25761     * Fallback to "anyType".
25762     */
25763     vctxt->inode->typeDef =
25764 	xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
25765     return (0);
25766 }
25767 
25768 /*
25769 * xmlSchemaCheckCOSValidDefault:
25770 *
25771 * This will be called if: not nilled, no content and a default/fixed
25772 * value is provided.
25773 */
25774 
25775 static int
25776 xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
25777 			      const xmlChar *value,
25778 			      xmlSchemaValPtr *val)
25779 {
25780     int ret = 0;
25781     xmlSchemaNodeInfoPtr inode = vctxt->inode;
25782 
25783     /*
25784     * cos-valid-default:
25785     * Schema Component Constraint: Element Default Valid (Immediate)
25786     * For a string to be a valid default with respect to a type
25787     * definition the appropriate case among the following must be true:
25788     */
25789     if WXS_IS_COMPLEX(inode->typeDef) {
25790 	/*
25791 	* Complex type.
25792 	*
25793 	* SPEC (2.1) "its {content type} must be a simple type definition
25794 	* or mixed."
25795 	* SPEC (2.2.2) "If the {content type} is mixed, then the {content
25796 	* type}'s particle must be �emptiable� as defined by
25797 	* Particle Emptiable (�3.9.6)."
25798 	*/
25799 	if ((! WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) &&
25800 	    ((! WXS_HAS_MIXED_CONTENT(inode->typeDef)) ||
25801 	     (! WXS_EMPTIABLE(inode->typeDef)))) {
25802 	    ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
25803 	    /* NOTE that this covers (2.2.2) as well. */
25804 	    VERROR(ret, NULL,
25805 		"For a string to be a valid default, the type definition "
25806 		"must be a simple type or a complex type with simple content "
25807 		"or mixed content and a particle emptiable");
25808 	    return(ret);
25809 	}
25810     }
25811     /*
25812     * 1 If the type definition is a simple type definition, then the string
25813     * must be �valid� with respect to that definition as defined by String
25814     * Valid (�3.14.4).
25815     *
25816     * AND
25817     *
25818     * 2.2.1 If the {content type} is a simple type definition, then the
25819     * string must be �valid� with respect to that simple type definition
25820     * as defined by String Valid (�3.14.4).
25821     */
25822     if (WXS_IS_SIMPLE(inode->typeDef)) {
25823 
25824 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
25825 	    NULL, inode->typeDef, value, val, 1, 1, 0);
25826 
25827     } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
25828 
25829 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
25830 	    NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
25831     }
25832     if (ret < 0) {
25833 	VERROR_INT("xmlSchemaCheckCOSValidDefault",
25834 	    "calling xmlSchemaVCheckCVCSimpleType()");
25835     }
25836     return (ret);
25837 }
25838 
25839 static void
25840 xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
25841 			       const xmlChar * name ATTRIBUTE_UNUSED,
25842 			       xmlSchemaElementPtr item,
25843 			       xmlSchemaNodeInfoPtr inode)
25844 {
25845     inode->decl = item;
25846 #ifdef DEBUG_CONTENT
25847     {
25848 	xmlChar *str = NULL;
25849 
25850 	if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
25851 	    xmlGenericError(xmlGenericErrorContext,
25852 		"AUTOMATON callback for '%s' [declaration]\n",
25853 		xmlSchemaFormatQName(&str,
25854 		inode->localName, inode->nsName));
25855 	} else {
25856 	    xmlGenericError(xmlGenericErrorContext,
25857 		    "AUTOMATON callback for '%s' [wildcard]\n",
25858 		    xmlSchemaFormatQName(&str,
25859 		    inode->localName, inode->nsName));
25860 
25861 	}
25862 	FREE_AND_NULL(str)
25863     }
25864 #endif
25865 }
25866 
25867 static int
25868 xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
25869 {
25870     vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
25871     if (vctxt->inode == NULL) {
25872 	VERROR_INT("xmlSchemaValidatorPushElem",
25873 	    "calling xmlSchemaGetFreshElemInfo()");
25874 	return (-1);
25875     }
25876     vctxt->nbAttrInfos = 0;
25877     return (0);
25878 }
25879 
25880 static int
25881 xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
25882 			     xmlSchemaNodeInfoPtr inode,
25883 			     xmlSchemaTypePtr type,
25884 			     const xmlChar *value)
25885 {
25886     if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
25887 	return (xmlSchemaVCheckCVCSimpleType(
25888 	    ACTXT_CAST vctxt, NULL,
25889 	    type, value, &(inode->val), 1, 1, 0));
25890     else
25891 	return (xmlSchemaVCheckCVCSimpleType(
25892 	    ACTXT_CAST vctxt, NULL,
25893 	    type, value, NULL, 1, 0, 0));
25894 }
25895 
25896 
25897 
25898 /*
25899 * Process END of element.
25900 */
25901 static int
25902 xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
25903 {
25904     int ret = 0;
25905     xmlSchemaNodeInfoPtr inode = vctxt->inode;
25906 
25907     if (vctxt->nbAttrInfos != 0)
25908 	xmlSchemaClearAttrInfos(vctxt);
25909     if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
25910 	/*
25911 	* This element was not expected;
25912 	* we will not validate child elements of broken parents.
25913 	* Skip validation of all content of the parent.
25914 	*/
25915 	vctxt->skipDepth = vctxt->depth -1;
25916 	goto end_elem;
25917     }
25918     if ((inode->typeDef == NULL) ||
25919 	(inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
25920 	/*
25921 	* 1. the type definition might be missing if the element was
25922 	*    error prone
25923 	* 2. it might be abstract.
25924 	*/
25925 	goto end_elem;
25926     }
25927     /*
25928     * Check the content model.
25929     */
25930     if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
25931 	(inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
25932 
25933 	/*
25934 	* Workaround for "anyType".
25935 	*/
25936 	if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
25937 	    goto character_content;
25938 
25939 	if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
25940 	    xmlChar *values[10];
25941 	    int terminal, nbval = 10, nbneg;
25942 
25943 	    if (inode->regexCtxt == NULL) {
25944 		/*
25945 		* Create the regex context.
25946 		*/
25947 		inode->regexCtxt =
25948 		    xmlRegNewExecCtxt(inode->typeDef->contModel,
25949 		    (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
25950 		    vctxt);
25951 		if (inode->regexCtxt == NULL) {
25952 		    VERROR_INT("xmlSchemaValidatorPopElem",
25953 			"failed to create a regex context");
25954 		    goto internal_error;
25955 		}
25956 #ifdef DEBUG_AUTOMATA
25957 		xmlGenericError(xmlGenericErrorContext,
25958 		    "AUTOMATON create on '%s'\n", inode->localName);
25959 #endif
25960 	    }
25961 	    /*
25962 	    * Get hold of the still expected content, since a further
25963 	    * call to xmlRegExecPushString() will loose this information.
25964 	    */
25965 	    xmlRegExecNextValues(inode->regexCtxt,
25966 		&nbval, &nbneg, &values[0], &terminal);
25967 	    ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
25968 	    if ((ret<0) || ((ret==0) && (!INODE_NILLED(inode)))) {
25969 		/*
25970 		* Still missing something.
25971 		*/
25972 		ret = 1;
25973 		inode->flags |=
25974 		    XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
25975 		xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
25976 		    XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
25977 		    "Missing child element(s)",
25978 		    nbval, nbneg, values);
25979 #ifdef DEBUG_AUTOMATA
25980 		xmlGenericError(xmlGenericErrorContext,
25981 		    "AUTOMATON missing ERROR on '%s'\n",
25982 		    inode->localName);
25983 #endif
25984 	    } else {
25985 		/*
25986 		* Content model is satisfied.
25987 		*/
25988 		ret = 0;
25989 #ifdef DEBUG_AUTOMATA
25990 		xmlGenericError(xmlGenericErrorContext,
25991 		    "AUTOMATON succeeded on '%s'\n",
25992 		    inode->localName);
25993 #endif
25994 	    }
25995 
25996 	}
25997     }
25998     if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
25999 	goto end_elem;
26000 
26001 character_content:
26002 
26003     if (vctxt->value != NULL) {
26004 	xmlSchemaFreeValue(vctxt->value);
26005 	vctxt->value = NULL;
26006     }
26007     /*
26008     * Check character content.
26009     */
26010     if (inode->decl == NULL) {
26011 	/*
26012 	* Speedup if no declaration exists.
26013 	*/
26014 	if (WXS_IS_SIMPLE(inode->typeDef)) {
26015 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26016 		inode, inode->typeDef, inode->value);
26017 	} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26018 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26019 		inode, inode->typeDef->contentTypeDef,
26020 		inode->value);
26021 	}
26022 	if (ret < 0) {
26023 	    VERROR_INT("xmlSchemaValidatorPopElem",
26024 		"calling xmlSchemaVCheckCVCSimpleType()");
26025 	    goto internal_error;
26026 	}
26027 	goto end_elem;
26028     }
26029     /*
26030     * cvc-elt (3.3.4) : 5
26031     * The appropriate case among the following must be true:
26032     */
26033     /*
26034     * cvc-elt (3.3.4) : 5.1
26035     * If the declaration has a {value constraint},
26036     * the item has neither element nor character [children] and
26037     * clause 3.2 has not applied, then all of the following must be true:
26038     */
26039     if ((inode->decl->value != NULL) &&
26040 	(inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
26041 	(! INODE_NILLED(inode))) {
26042 	/*
26043 	* cvc-elt (3.3.4) : 5.1.1
26044 	* If the �actual type definition� is a �local type definition�
26045 	* then the canonical lexical representation of the {value constraint}
26046 	* value must be a valid default for the �actual type definition� as
26047 	* defined in Element Default Valid (Immediate) (�3.3.6).
26048 	*/
26049 	/*
26050 	* NOTE: 'local' above means types acquired by xsi:type.
26051 	* NOTE: Although the *canonical* value is stated, it is not
26052 	* relevant if canonical or not. Additionally XML Schema 1.1
26053 	* will removed this requirement as well.
26054 	*/
26055 	if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
26056 
26057 	    ret = xmlSchemaCheckCOSValidDefault(vctxt,
26058 		inode->decl->value, &(inode->val));
26059 	    if (ret != 0) {
26060 		if (ret < 0) {
26061 		    VERROR_INT("xmlSchemaValidatorPopElem",
26062 			"calling xmlSchemaCheckCOSValidDefault()");
26063 		    goto internal_error;
26064 		}
26065 		goto end_elem;
26066 	    }
26067 	    /*
26068 	    * Stop here, to avoid redundant validation of the value
26069 	    * (see following).
26070 	    */
26071 	    goto default_psvi;
26072 	}
26073 	/*
26074 	* cvc-elt (3.3.4) : 5.1.2
26075 	* The element information item with the canonical lexical
26076 	* representation of the {value constraint} value used as its
26077 	* �normalized value� must be �valid� with respect to the
26078 	* �actual type definition� as defined by Element Locally Valid (Type)
26079 	* (�3.3.4).
26080 	*/
26081 	if (WXS_IS_SIMPLE(inode->typeDef)) {
26082 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26083 		inode, inode->typeDef, inode->decl->value);
26084 	} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26085 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26086 		inode, inode->typeDef->contentTypeDef,
26087 		inode->decl->value);
26088 	}
26089 	if (ret != 0) {
26090 	    if (ret < 0) {
26091 		VERROR_INT("xmlSchemaValidatorPopElem",
26092 		    "calling xmlSchemaVCheckCVCSimpleType()");
26093 		goto internal_error;
26094 	    }
26095 	    goto end_elem;
26096 	}
26097 
26098 default_psvi:
26099 	/*
26100 	* PSVI: Create a text node on the instance element.
26101 	*/
26102 	if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
26103 	    (inode->node != NULL)) {
26104 	    xmlNodePtr textChild;
26105 	    xmlChar *normValue;
26106 	    /*
26107 	    * VAL TODO: Normalize the value.
26108 	    */
26109 	    normValue = xmlSchemaNormalizeValue(inode->typeDef,
26110 		inode->decl->value);
26111 	    if (normValue != NULL) {
26112 		textChild = xmlNewText(BAD_CAST normValue);
26113 		xmlFree(normValue);
26114 	    } else
26115 		textChild = xmlNewText(inode->decl->value);
26116 	    if (textChild == NULL) {
26117 		VERROR_INT("xmlSchemaValidatorPopElem",
26118 		    "calling xmlNewText()");
26119 		goto internal_error;
26120 	    } else
26121 		xmlAddChild(inode->node, textChild);
26122 	}
26123 
26124     } else if (! INODE_NILLED(inode)) {
26125 	/*
26126 	* 5.2.1 The element information item must be �valid� with respect
26127 	* to the �actual type definition� as defined by Element Locally
26128 	* Valid (Type) (�3.3.4).
26129 	*/
26130 	if (WXS_IS_SIMPLE(inode->typeDef)) {
26131 	     /*
26132 	    * SPEC (cvc-type) (3.1)
26133 	    * "If the type definition is a simple type definition, ..."
26134 	    * (3.1.3) "If clause 3.2 of Element Locally Valid
26135 	    * (Element) (�3.3.4) did not apply, then the �normalized value�
26136 	    * must be �valid� with respect to the type definition as defined
26137 	    * by String Valid (�3.14.4).
26138 	    */
26139 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26140 		    inode, inode->typeDef, inode->value);
26141 	} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26142 	    /*
26143 	    * SPEC (cvc-type) (3.2) "If the type definition is a complex type
26144 	    * definition, then the element information item must be
26145 	    * �valid� with respect to the type definition as per
26146 	    * Element Locally Valid (Complex Type) (�3.4.4);"
26147 	    *
26148 	    * SPEC (cvc-complex-type) (2.2)
26149 	    * "If the {content type} is a simple type definition, ...
26150 	    * the �normalized value� of the element information item is
26151 	    * �valid� with respect to that simple type definition as
26152 	    * defined by String Valid (�3.14.4)."
26153 	    */
26154 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26155 		inode, inode->typeDef->contentTypeDef, inode->value);
26156 	}
26157 	if (ret != 0) {
26158 	    if (ret < 0) {
26159 		VERROR_INT("xmlSchemaValidatorPopElem",
26160 		    "calling xmlSchemaVCheckCVCSimpleType()");
26161 		goto internal_error;
26162 	    }
26163 	    goto end_elem;
26164 	}
26165 	/*
26166 	* 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
26167 	* not applied, all of the following must be true:
26168 	*/
26169 	if ((inode->decl->value != NULL) &&
26170 	    (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
26171 
26172 	    /*
26173 	    * TODO: We will need a computed value, when comparison is
26174 	    * done on computed values.
26175 	    */
26176 	    /*
26177 	    * 5.2.2.1 The element information item must have no element
26178 	    * information item [children].
26179 	    */
26180 	    if (inode->flags &
26181 		    XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
26182 		ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
26183 		VERROR(ret, NULL,
26184 		    "The content must not containt element nodes since "
26185 		    "there is a fixed value constraint");
26186 		goto end_elem;
26187 	    } else {
26188 		/*
26189 		* 5.2.2.2 The appropriate case among the following must
26190 		* be true:
26191 		*/
26192 		if (WXS_HAS_MIXED_CONTENT(inode->typeDef)) {
26193 		    /*
26194 		    * 5.2.2.2.1 If the {content type} of the �actual type
26195 		    * definition� is mixed, then the *initial value* of the
26196 		    * item must match the canonical lexical representation
26197 		    * of the {value constraint} value.
26198 		    *
26199 		    * ... the *initial value* of an element information
26200 		    * item is the string composed of, in order, the
26201 		    * [character code] of each character information item in
26202 		    * the [children] of that element information item.
26203 		    */
26204 		    if (! xmlStrEqual(inode->value, inode->decl->value)){
26205 			/*
26206 			* VAL TODO: Report invalid & expected values as well.
26207 			* VAL TODO: Implement the canonical stuff.
26208 			*/
26209 			ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
26210 			xmlSchemaCustomErr(ACTXT_CAST vctxt,
26211 			    ret, NULL, NULL,
26212 			    "The initial value '%s' does not match the fixed "
26213 			    "value constraint '%s'",
26214 			    inode->value, inode->decl->value);
26215 			goto end_elem;
26216 		    }
26217 		} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26218 		    /*
26219 		    * 5.2.2.2.2 If the {content type} of the �actual type
26220 		    * definition� is a simple type definition, then the
26221 		    * *actual value* of the item must match the canonical
26222 		    * lexical representation of the {value constraint} value.
26223 		    */
26224 		    /*
26225 		    * VAL TODO: *actual value* is the normalized value, impl.
26226 		    *           this.
26227 		    * VAL TODO: Report invalid & expected values as well.
26228 		    * VAL TODO: Implement a comparison with the computed values.
26229 		    */
26230 		    if (! xmlStrEqual(inode->value,
26231 			    inode->decl->value)) {
26232 			ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
26233 			xmlSchemaCustomErr(ACTXT_CAST vctxt,
26234 			    ret, NULL, NULL,
26235 			    "The actual value '%s' does not match the fixed "
26236 			    "value constraint '%s'",
26237 			    inode->value,
26238 			    inode->decl->value);
26239 			goto end_elem;
26240 		    }
26241 		}
26242 	    }
26243 	}
26244     }
26245 
26246 end_elem:
26247     if (vctxt->depth < 0) {
26248 	/* TODO: raise error? */
26249 	return (0);
26250     }
26251     if (vctxt->depth == vctxt->skipDepth)
26252 	vctxt->skipDepth = -1;
26253     /*
26254     * Evaluate the history of XPath state objects.
26255     */
26256     if (inode->appliedXPath &&
26257 	(xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1))
26258 	goto internal_error;
26259     /*
26260     * MAYBE TODO:
26261     * SPEC (6) "The element information item must be �valid� with
26262     * respect to each of the {identity-constraint definitions} as per
26263     * Identity-constraint Satisfied (�3.11.4)."
26264     */
26265     /*
26266     * PSVI TODO: If we expose IDC node-tables via PSVI then the tables
26267     *   need to be built in any case.
26268     *   We will currently build IDC node-tables and bubble them only if
26269     *   keyrefs do exist.
26270     */
26271 
26272     /*
26273     * Add the current IDC target-nodes to the IDC node-tables.
26274     */
26275     if ((inode->idcMatchers != NULL) &&
26276 	(vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26277     {
26278 	if (xmlSchemaIDCFillNodeTables(vctxt, inode) == -1)
26279 	    goto internal_error;
26280     }
26281     /*
26282     * Validate IDC keyrefs.
26283     */
26284     if (vctxt->inode->hasKeyrefs)
26285 	if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
26286 	    goto internal_error;
26287     /*
26288     * Merge/free the IDC table.
26289     */
26290     if (inode->idcTable != NULL) {
26291 #ifdef DEBUG_IDC_NODE_TABLE
26292 	xmlSchemaDebugDumpIDCTable(stdout,
26293 	    inode->nsName,
26294 	    inode->localName,
26295 	    inode->idcTable);
26296 #endif
26297 	if ((vctxt->depth > 0) &&
26298 	    (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26299 	{
26300 	    /*
26301 	    * Merge the IDC node table with the table of the parent node.
26302 	    */
26303 	    if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
26304 		goto internal_error;
26305 	}
26306     }
26307     /*
26308     * Clear the current ielem.
26309     * VAL TODO: Don't free the PSVI IDC tables if they are
26310     * requested for the PSVI.
26311     */
26312     xmlSchemaClearElemInfo(vctxt, inode);
26313     /*
26314     * Skip further processing if we are on the validation root.
26315     */
26316     if (vctxt->depth == 0) {
26317 	vctxt->depth--;
26318 	vctxt->inode = NULL;
26319 	return (0);
26320     }
26321     /*
26322     * Reset the keyrefDepth if needed.
26323     */
26324     if (vctxt->aidcs != NULL) {
26325 	xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
26326 	do {
26327 	    if (aidc->keyrefDepth == vctxt->depth) {
26328 		/*
26329 		* A 'keyrefDepth' of a key/unique IDC matches the current
26330 		* depth, this means that we are leaving the scope of the
26331 		* top-most keyref IDC which refers to this IDC.
26332 		*/
26333 		aidc->keyrefDepth = -1;
26334 	    }
26335 	    aidc = aidc->next;
26336 	} while (aidc != NULL);
26337     }
26338     vctxt->depth--;
26339     vctxt->inode = vctxt->elemInfos[vctxt->depth];
26340     /*
26341     * VAL TODO: 7 If the element information item is the �validation root�, it must be
26342     * �valid� per Validation Root Valid (ID/IDREF) (�3.3.4).
26343     */
26344     return (ret);
26345 
26346 internal_error:
26347     vctxt->err = -1;
26348     return (-1);
26349 }
26350 
26351 /*
26352 * 3.4.4 Complex Type Definition Validation Rules
26353 * Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
26354 */
26355 static int
26356 xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
26357 {
26358     xmlSchemaNodeInfoPtr pielem;
26359     xmlSchemaTypePtr ptype;
26360     int ret = 0;
26361 
26362     if (vctxt->depth <= 0) {
26363 	VERROR_INT("xmlSchemaValidateChildElem",
26364 	    "not intended for the validation root");
26365 	return (-1);
26366     }
26367     pielem = vctxt->elemInfos[vctxt->depth -1];
26368     if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26369 	pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26370     /*
26371     * Handle 'nilled' elements.
26372     */
26373     if (INODE_NILLED(pielem)) {
26374 	/*
26375 	* SPEC (cvc-elt) (3.3.4) : (3.2.1)
26376 	*/
26377 	ACTIVATE_PARENT_ELEM;
26378 	ret = XML_SCHEMAV_CVC_ELT_3_2_1;
26379 	VERROR(ret, NULL,
26380 	    "Neither character nor element content is allowed, "
26381 	    "because the element was 'nilled'");
26382 	ACTIVATE_ELEM;
26383 	goto unexpected_elem;
26384     }
26385 
26386     ptype = pielem->typeDef;
26387 
26388     if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
26389 	/*
26390 	* Workaround for "anyType": we have currently no content model
26391 	* assigned for "anyType", so handle it explicitely.
26392 	* "anyType" has an unbounded, lax "any" wildcard.
26393 	*/
26394 	vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26395 	    vctxt->inode->localName,
26396 	    vctxt->inode->nsName);
26397 
26398 	if (vctxt->inode->decl == NULL) {
26399 	    xmlSchemaAttrInfoPtr iattr;
26400 	    /*
26401 	    * Process "xsi:type".
26402 	    * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
26403 	    */
26404 	    iattr = xmlSchemaGetMetaAttrInfo(vctxt,
26405 		XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
26406 	    if (iattr != NULL) {
26407 		ret = xmlSchemaProcessXSIType(vctxt, iattr,
26408 		    &(vctxt->inode->typeDef), NULL);
26409 		if (ret != 0) {
26410 		    if (ret == -1) {
26411 			VERROR_INT("xmlSchemaValidateChildElem",
26412 			    "calling xmlSchemaProcessXSIType() to "
26413 			    "process the attribute 'xsi:nil'");
26414 			return (-1);
26415 		    }
26416 		    return (ret);
26417 		}
26418 	    } else {
26419 		 /*
26420 		 * Fallback to "anyType".
26421 		 *
26422 		 * SPEC (cvc-assess-elt)
26423 		 * "If the item cannot be �strictly assessed�, [...]
26424 		 * an element information item's schema validity may be laxly
26425 		 * assessed if its �context-determined declaration� is not
26426 		 * skip by �validating� with respect to the �ur-type
26427 		 * definition� as per Element Locally Valid (Type) (�3.3.4)."
26428 		*/
26429 		vctxt->inode->typeDef =
26430 		    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
26431 	    }
26432 	}
26433 	return (0);
26434     }
26435 
26436     switch (ptype->contentType) {
26437 	case XML_SCHEMA_CONTENT_EMPTY:
26438 	    /*
26439 	    * SPEC (2.1) "If the {content type} is empty, then the
26440 	    * element information item has no character or element
26441 	    * information item [children]."
26442 	    */
26443 	    ACTIVATE_PARENT_ELEM
26444 	    ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
26445 	    VERROR(ret, NULL,
26446 		"Element content is not allowed, "
26447 		"because the content type is empty");
26448 	    ACTIVATE_ELEM
26449 	    goto unexpected_elem;
26450 	    break;
26451 
26452 	case XML_SCHEMA_CONTENT_MIXED:
26453         case XML_SCHEMA_CONTENT_ELEMENTS: {
26454 	    xmlRegExecCtxtPtr regexCtxt;
26455 	    xmlChar *values[10];
26456 	    int terminal, nbval = 10, nbneg;
26457 
26458 	    /* VAL TODO: Optimized "anyType" validation.*/
26459 
26460 	    if (ptype->contModel == NULL) {
26461 		VERROR_INT("xmlSchemaValidateChildElem",
26462 		    "type has elem content but no content model");
26463 		return (-1);
26464 	    }
26465 	    /*
26466 	    * Safety belf for evaluation if the cont. model was already
26467 	    * examined to be invalid.
26468 	    */
26469 	    if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
26470 		VERROR_INT("xmlSchemaValidateChildElem",
26471 		    "validating elem, but elem content is already invalid");
26472 		return (-1);
26473 	    }
26474 
26475 	    regexCtxt = pielem->regexCtxt;
26476 	    if (regexCtxt == NULL) {
26477 		/*
26478 		* Create the regex context.
26479 		*/
26480 		regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
26481 		    (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
26482 		    vctxt);
26483 		if (regexCtxt == NULL) {
26484 		    VERROR_INT("xmlSchemaValidateChildElem",
26485 			"failed to create a regex context");
26486 		    return (-1);
26487 		}
26488 		pielem->regexCtxt = regexCtxt;
26489 #ifdef DEBUG_AUTOMATA
26490 		xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
26491 		    pielem->localName);
26492 #endif
26493 	    }
26494 
26495 	    /*
26496 	    * SPEC (2.4) "If the {content type} is element-only or mixed,
26497 	    * then the sequence of the element information item's
26498 	    * element information item [children], if any, taken in
26499 	    * order, is �valid� with respect to the {content type}'s
26500 	    * particle, as defined in Element Sequence Locally Valid
26501 	    * (Particle) (�3.9.4)."
26502 	    */
26503 	    ret = xmlRegExecPushString2(regexCtxt,
26504 		vctxt->inode->localName,
26505 		vctxt->inode->nsName,
26506 		vctxt->inode);
26507 #ifdef DEBUG_AUTOMATA
26508 	    if (ret < 0)
26509 		xmlGenericError(xmlGenericErrorContext,
26510 		"AUTOMATON push ERROR for '%s' on '%s'\n",
26511 		vctxt->inode->localName, pielem->localName);
26512 	    else
26513 		xmlGenericError(xmlGenericErrorContext,
26514 		"AUTOMATON push OK for '%s' on '%s'\n",
26515 		vctxt->inode->localName, pielem->localName);
26516 #endif
26517 	    if (vctxt->err == XML_SCHEMAV_INTERNAL) {
26518 		VERROR_INT("xmlSchemaValidateChildElem",
26519 		    "calling xmlRegExecPushString2()");
26520 		return (-1);
26521 	    }
26522 	    if (ret < 0) {
26523 		xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
26524 		    &values[0], &terminal);
26525 		xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26526 		    XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
26527 		    "This element is not expected",
26528 		    nbval, nbneg, values);
26529 		ret = vctxt->err;
26530 		goto unexpected_elem;
26531 	    } else
26532 		ret = 0;
26533 	}
26534 	    break;
26535 	case XML_SCHEMA_CONTENT_SIMPLE:
26536 	case XML_SCHEMA_CONTENT_BASIC:
26537 	    ACTIVATE_PARENT_ELEM
26538 	    if (WXS_IS_COMPLEX(ptype)) {
26539 		/*
26540 		* SPEC (cvc-complex-type) (2.2)
26541 		* "If the {content type} is a simple type definition, then
26542 		* the element information item has no element information
26543 		* item [children], ..."
26544 		*/
26545 		ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
26546 		VERROR(ret, NULL, "Element content is not allowed, "
26547 		    "because the content type is a simple type definition");
26548 	    } else {
26549 		/*
26550 		* SPEC (cvc-type) (3.1.2) "The element information item must
26551 		* have no element information item [children]."
26552 		*/
26553 		ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
26554 		VERROR(ret, NULL, "Element content is not allowed, "
26555 		    "because the type definition is simple");
26556 	    }
26557 	    ACTIVATE_ELEM
26558 	    ret = vctxt->err;
26559 	    goto unexpected_elem;
26560 	    break;
26561 
26562 	default:
26563 	    break;
26564     }
26565     return (ret);
26566 unexpected_elem:
26567     /*
26568     * Pop this element and set the skipDepth to skip
26569     * all further content of the parent element.
26570     */
26571     vctxt->skipDepth = vctxt->depth;
26572     vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
26573     pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26574     return (ret);
26575 }
26576 
26577 #define XML_SCHEMA_PUSH_TEXT_PERSIST 1
26578 #define XML_SCHEMA_PUSH_TEXT_CREATED 2
26579 #define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
26580 
26581 static int
26582 xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
26583 		  int nodeType, const xmlChar *value, int len,
26584 		  int mode, int *consumed)
26585 {
26586     /*
26587     * Unfortunately we have to duplicate the text sometimes.
26588     * OPTIMIZE: Maybe we could skip it, if:
26589     *   1. content type is simple
26590     *   2. whitespace is "collapse"
26591     *   3. it consists of whitespace only
26592     *
26593     * Process character content.
26594     */
26595     if (consumed != NULL)
26596 	*consumed = 0;
26597     if (INODE_NILLED(vctxt->inode)) {
26598 	/*
26599 	* SPEC cvc-elt (3.3.4 - 3.2.1)
26600 	* "The element information item must have no character or
26601 	* element information item [children]."
26602 	*/
26603 	VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
26604 	    "Neither character nor element content is allowed "
26605 	    "because the element is 'nilled'");
26606 	return (vctxt->err);
26607     }
26608     /*
26609     * SPEC (2.1) "If the {content type} is empty, then the
26610     * element information item has no character or element
26611     * information item [children]."
26612     */
26613     if (vctxt->inode->typeDef->contentType ==
26614 	    XML_SCHEMA_CONTENT_EMPTY) {
26615 	VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
26616 	    "Character content is not allowed, "
26617 	    "because the content type is empty");
26618 	return (vctxt->err);
26619     }
26620 
26621     if (vctxt->inode->typeDef->contentType ==
26622 	    XML_SCHEMA_CONTENT_ELEMENTS) {
26623 	if ((nodeType != XML_TEXT_NODE) ||
26624 	    (! xmlSchemaIsBlank((xmlChar *) value, len))) {
26625 	    /*
26626 	    * SPEC cvc-complex-type (2.3)
26627 	    * "If the {content type} is element-only, then the
26628 	    * element information item has no character information
26629 	    * item [children] other than those whose [character
26630 	    * code] is defined as a white space in [XML 1.0 (Second
26631 	    * Edition)]."
26632 	    */
26633 	    VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
26634 		"Character content other than whitespace is not allowed "
26635 		"because the content type is 'element-only'");
26636 	    return (vctxt->err);
26637 	}
26638 	return (0);
26639     }
26640 
26641     if ((value == NULL) || (value[0] == 0))
26642 	return (0);
26643     /*
26644     * Save the value.
26645     * NOTE that even if the content type is *mixed*, we need the
26646     * *initial value* for default/fixed value constraints.
26647     */
26648     if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
26649 	((vctxt->inode->decl == NULL) ||
26650 	(vctxt->inode->decl->value == NULL)))
26651 	return (0);
26652 
26653     if (vctxt->inode->value == NULL) {
26654 	/*
26655 	* Set the value.
26656 	*/
26657 	switch (mode) {
26658 	    case XML_SCHEMA_PUSH_TEXT_PERSIST:
26659 		/*
26660 		* When working on a tree.
26661 		*/
26662 		vctxt->inode->value = value;
26663 		break;
26664 	    case XML_SCHEMA_PUSH_TEXT_CREATED:
26665 		/*
26666 		* When working with the reader.
26667 		* The value will be freed by the element info.
26668 		*/
26669 		vctxt->inode->value = value;
26670 		if (consumed != NULL)
26671 		    *consumed = 1;
26672 		vctxt->inode->flags |=
26673 		    XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26674 		break;
26675 	    case XML_SCHEMA_PUSH_TEXT_VOLATILE:
26676 		/*
26677 		* When working with SAX.
26678 		* The value will be freed by the element info.
26679 		*/
26680 		if (len != -1)
26681 		    vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
26682 		else
26683 		    vctxt->inode->value = BAD_CAST xmlStrdup(value);
26684 		vctxt->inode->flags |=
26685 		    XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26686 		break;
26687 	    default:
26688 		break;
26689 	}
26690     } else {
26691 	if (len < 0)
26692 	    len = xmlStrlen(value);
26693 	/*
26694 	* Concat the value.
26695 	*/
26696 	if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
26697 	    vctxt->inode->value = BAD_CAST xmlStrncat(
26698 		(xmlChar *) vctxt->inode->value, value, len);
26699 	} else {
26700 	    vctxt->inode->value =
26701 		BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
26702 	    vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26703 	}
26704     }
26705 
26706     return (0);
26707 }
26708 
26709 static int
26710 xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
26711 {
26712     int ret = 0;
26713 
26714     if ((vctxt->skipDepth != -1) &&
26715 	(vctxt->depth >= vctxt->skipDepth)) {
26716 	VERROR_INT("xmlSchemaValidateElem",
26717 	    "in skip-state");
26718 	goto internal_error;
26719     }
26720     if (vctxt->xsiAssemble) {
26721 	/*
26722 	* We will stop validation if there was an error during
26723 	* dynamic schema construction.
26724 	* Note that we simply set @skipDepth to 0, this could
26725 	* mean that a streaming document via SAX would be
26726 	* still read to the end but it won't be validated any more.
26727 	* TODO: If we are sure how to stop the validation at once
26728 	*   for all input scenarios, then this should be changed to
26729 	*   instantly stop the validation.
26730 	*/
26731 	ret = xmlSchemaAssembleByXSI(vctxt);
26732 	if (ret != 0) {
26733 	    if (ret == -1)
26734 		goto internal_error;
26735 	    vctxt->skipDepth = 0;
26736 	    return(ret);
26737 	}
26738     }
26739     if (vctxt->depth > 0) {
26740 	/*
26741 	* Validate this element against the content model
26742 	* of the parent.
26743 	*/
26744 	ret = xmlSchemaValidateChildElem(vctxt);
26745 	if (ret != 0) {
26746 	    if (ret < 0) {
26747 		VERROR_INT("xmlSchemaValidateElem",
26748 		    "calling xmlSchemaStreamValidateChildElement()");
26749 		goto internal_error;
26750 	    }
26751 	    goto exit;
26752 	}
26753 	if (vctxt->depth == vctxt->skipDepth)
26754 	    goto exit;
26755 	if ((vctxt->inode->decl == NULL) &&
26756 	    (vctxt->inode->typeDef == NULL)) {
26757 	    VERROR_INT("xmlSchemaValidateElem",
26758 		"the child element was valid but neither the "
26759 		"declaration nor the type was set");
26760 	    goto internal_error;
26761 	}
26762     } else {
26763 	/*
26764 	* Get the declaration of the validation root.
26765 	*/
26766 	vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26767 	    vctxt->inode->localName,
26768 	    vctxt->inode->nsName);
26769 	if (vctxt->inode->decl == NULL) {
26770 	    ret = XML_SCHEMAV_CVC_ELT_1;
26771 	    VERROR(ret, NULL,
26772 		"No matching global declaration available "
26773 		"for the validation root");
26774 	    goto exit;
26775 	}
26776     }
26777 
26778     if (vctxt->inode->decl == NULL)
26779 	goto type_validation;
26780 
26781     if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
26782 	int skip;
26783 	/*
26784 	* Wildcards.
26785 	*/
26786 	ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
26787 	if (ret != 0) {
26788 	    if (ret < 0) {
26789 		VERROR_INT("xmlSchemaValidateElem",
26790 		    "calling xmlSchemaValidateElemWildcard()");
26791 		goto internal_error;
26792 	    }
26793 	    goto exit;
26794 	}
26795 	if (skip) {
26796 	    vctxt->skipDepth = vctxt->depth;
26797 	    goto exit;
26798 	}
26799 	/*
26800 	* The declaration might be set by the wildcard validation,
26801 	* when the processContents is "lax" or "strict".
26802 	*/
26803 	if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
26804 	    /*
26805 	    * Clear the "decl" field to not confuse further processing.
26806 	    */
26807 	    vctxt->inode->decl = NULL;
26808 	    goto type_validation;
26809 	}
26810     }
26811     /*
26812     * Validate against the declaration.
26813     */
26814     ret = xmlSchemaValidateElemDecl(vctxt);
26815     if (ret != 0) {
26816 	if (ret < 0) {
26817 	    VERROR_INT("xmlSchemaValidateElem",
26818 		"calling xmlSchemaValidateElemDecl()");
26819 	    goto internal_error;
26820 	}
26821 	goto exit;
26822     }
26823     /*
26824     * Validate against the type definition.
26825     */
26826 type_validation:
26827 
26828     if (vctxt->inode->typeDef == NULL) {
26829 	vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26830 	ret = XML_SCHEMAV_CVC_TYPE_1;
26831     	VERROR(ret, NULL,
26832     	    "The type definition is absent");
26833 	goto exit;
26834     }
26835     if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
26836 	vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26837 	ret = XML_SCHEMAV_CVC_TYPE_2;
26838     	    VERROR(ret, NULL,
26839     	    "The type definition is abstract");
26840 	goto exit;
26841     }
26842     /*
26843     * Evaluate IDCs. Do it here, since new IDC matchers are registered
26844     * during validation against the declaration. This must be done
26845     * _before_ attribute validation.
26846     */
26847     if (vctxt->xpathStates != NULL) {
26848 	ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
26849 	vctxt->inode->appliedXPath = 1;
26850 	if (ret == -1) {
26851 	    VERROR_INT("xmlSchemaValidateElem",
26852 		"calling xmlSchemaXPathEvaluate()");
26853 	    goto internal_error;
26854 	}
26855     }
26856     /*
26857     * Validate attributes.
26858     */
26859     if (WXS_IS_COMPLEX(vctxt->inode->typeDef)) {
26860 	if ((vctxt->nbAttrInfos != 0) ||
26861 	    (vctxt->inode->typeDef->attrUses != NULL)) {
26862 
26863 	    ret = xmlSchemaVAttributesComplex(vctxt);
26864 	}
26865     } else if (vctxt->nbAttrInfos != 0) {
26866 
26867 	ret = xmlSchemaVAttributesSimple(vctxt);
26868     }
26869     /*
26870     * Clear registered attributes.
26871     */
26872     if (vctxt->nbAttrInfos != 0)
26873 	xmlSchemaClearAttrInfos(vctxt);
26874     if (ret == -1) {
26875 	VERROR_INT("xmlSchemaValidateElem",
26876 	    "calling attributes validation");
26877 	goto internal_error;
26878     }
26879     /*
26880     * Don't return an error if attributes are invalid on purpose.
26881     */
26882     ret = 0;
26883 
26884 exit:
26885     if (ret != 0)
26886 	vctxt->skipDepth = vctxt->depth;
26887     return (ret);
26888 internal_error:
26889     return (-1);
26890 }
26891 
26892 #ifdef XML_SCHEMA_READER_ENABLED
26893 static int
26894 xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
26895 {
26896     const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
26897     int depth, nodeType, ret = 0, consumed;
26898     xmlSchemaNodeInfoPtr ielem;
26899 
26900     vctxt->depth = -1;
26901     ret = xmlTextReaderRead(vctxt->reader);
26902     /*
26903     * Move to the document element.
26904     */
26905     while (ret == 1) {
26906 	nodeType = xmlTextReaderNodeType(vctxt->reader);
26907 	if (nodeType == XML_ELEMENT_NODE)
26908 	    goto root_found;
26909 	ret = xmlTextReaderRead(vctxt->reader);
26910     }
26911     goto exit;
26912 
26913 root_found:
26914 
26915     do {
26916 	depth = xmlTextReaderDepth(vctxt->reader);
26917 	nodeType = xmlTextReaderNodeType(vctxt->reader);
26918 
26919 	if (nodeType == XML_ELEMENT_NODE) {
26920 
26921 	    vctxt->depth++;
26922 	    if (xmlSchemaValidatorPushElem(vctxt) == -1) {
26923 		VERROR_INT("xmlSchemaVReaderWalk",
26924 		    "calling xmlSchemaValidatorPushElem()");
26925 		goto internal_error;
26926 	    }
26927 	    ielem = vctxt->inode;
26928 	    ielem->localName = xmlTextReaderLocalName(vctxt->reader);
26929 	    ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
26930 	    ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
26931 	    /*
26932 	    * Is the element empty?
26933 	    */
26934 	    ret = xmlTextReaderIsEmptyElement(vctxt->reader);
26935 	    if (ret == -1) {
26936 		VERROR_INT("xmlSchemaVReaderWalk",
26937 		    "calling xmlTextReaderIsEmptyElement()");
26938 		goto internal_error;
26939 	    }
26940 	    if (ret) {
26941 		ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
26942 	    }
26943 	    /*
26944 	    * Register attributes.
26945 	    */
26946 	    vctxt->nbAttrInfos = 0;
26947 	    ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
26948 	    if (ret == -1) {
26949 		VERROR_INT("xmlSchemaVReaderWalk",
26950 		    "calling xmlTextReaderMoveToFirstAttribute()");
26951 		goto internal_error;
26952 	    }
26953 	    if (ret == 1) {
26954 		do {
26955 		    /*
26956 		    * VAL TODO: How do we know that the reader works on a
26957 		    * node tree, to be able to pass a node here?
26958 		    */
26959 		    if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
26960 			(const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
26961 			xmlTextReaderNamespaceUri(vctxt->reader), 1,
26962 			xmlTextReaderValue(vctxt->reader), 1) == -1) {
26963 
26964 			VERROR_INT("xmlSchemaVReaderWalk",
26965 			    "calling xmlSchemaValidatorPushAttribute()");
26966 			goto internal_error;
26967 		    }
26968 		    ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
26969 		    if (ret == -1) {
26970 			VERROR_INT("xmlSchemaVReaderWalk",
26971 			    "calling xmlTextReaderMoveToFirstAttribute()");
26972 			goto internal_error;
26973 		    }
26974 		} while (ret == 1);
26975 		/*
26976 		* Back to element position.
26977 		*/
26978 		ret = xmlTextReaderMoveToElement(vctxt->reader);
26979 		if (ret == -1) {
26980 		    VERROR_INT("xmlSchemaVReaderWalk",
26981 			"calling xmlTextReaderMoveToElement()");
26982 		    goto internal_error;
26983 		}
26984 	    }
26985 	    /*
26986 	    * Validate the element.
26987 	    */
26988 	    ret= xmlSchemaValidateElem(vctxt);
26989 	    if (ret != 0) {
26990 		if (ret == -1) {
26991 		    VERROR_INT("xmlSchemaVReaderWalk",
26992 			"calling xmlSchemaValidateElem()");
26993 		    goto internal_error;
26994 		}
26995 		goto exit;
26996 	    }
26997 	    if (vctxt->depth == vctxt->skipDepth) {
26998 		int curDepth;
26999 		/*
27000 		* Skip all content.
27001 		*/
27002 		if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
27003 		    ret = xmlTextReaderRead(vctxt->reader);
27004 		    curDepth = xmlTextReaderDepth(vctxt->reader);
27005 		    while ((ret == 1) && (curDepth != depth)) {
27006 			ret = xmlTextReaderRead(vctxt->reader);
27007 			curDepth = xmlTextReaderDepth(vctxt->reader);
27008 		    }
27009 		    if (ret < 0) {
27010 			/*
27011 			* VAL TODO: A reader error occured; what to do here?
27012 			*/
27013 			ret = 1;
27014 			goto exit;
27015 		    }
27016 		}
27017 		goto leave_elem;
27018 	    }
27019 	    /*
27020 	    * READER VAL TODO: Is an END_ELEM really never called
27021 	    * if the elem is empty?
27022 	    */
27023 	    if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27024 		goto leave_elem;
27025 	} else if (nodeType == END_ELEM) {
27026 	    /*
27027 	    * Process END of element.
27028 	    */
27029 leave_elem:
27030 	    ret = xmlSchemaValidatorPopElem(vctxt);
27031 	    if (ret != 0) {
27032 		if (ret < 0) {
27033 		    VERROR_INT("xmlSchemaVReaderWalk",
27034 			"calling xmlSchemaValidatorPopElem()");
27035 		    goto internal_error;
27036 		}
27037 		goto exit;
27038 	    }
27039 	    if (vctxt->depth >= 0)
27040 		ielem = vctxt->inode;
27041 	    else
27042 		ielem = NULL;
27043 	} else if ((nodeType == XML_TEXT_NODE) ||
27044 	    (nodeType == XML_CDATA_SECTION_NODE) ||
27045 	    (nodeType == WHTSP) ||
27046 	    (nodeType == SIGN_WHTSP)) {
27047 	    /*
27048 	    * Process character content.
27049 	    */
27050 	    xmlChar *value;
27051 
27052 	    if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
27053 		nodeType = XML_TEXT_NODE;
27054 
27055 	    value = xmlTextReaderValue(vctxt->reader);
27056 	    ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
27057 		-1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
27058 	    if (! consumed)
27059 		xmlFree(value);
27060 	    if (ret == -1) {
27061 		VERROR_INT("xmlSchemaVReaderWalk",
27062 		    "calling xmlSchemaVPushText()");
27063 		goto internal_error;
27064 	    }
27065 	} else if ((nodeType == XML_ENTITY_NODE) ||
27066 	    (nodeType == XML_ENTITY_REF_NODE)) {
27067 	    /*
27068 	    * VAL TODO: What to do with entities?
27069 	    */
27070 	    TODO
27071 	}
27072 	/*
27073 	* Read next node.
27074 	*/
27075 	ret = xmlTextReaderRead(vctxt->reader);
27076     } while (ret == 1);
27077 
27078 exit:
27079     return (ret);
27080 internal_error:
27081     return (-1);
27082 }
27083 #endif
27084 
27085 /************************************************************************
27086  * 									*
27087  * 			SAX validation handlers				*
27088  * 									*
27089  ************************************************************************/
27090 
27091 /*
27092 * Process text content.
27093 */
27094 static void
27095 xmlSchemaSAXHandleText(void *ctx,
27096 		       const xmlChar * ch,
27097 		       int len)
27098 {
27099     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27100 
27101     if (vctxt->depth < 0)
27102 	return;
27103     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27104 	return;
27105     if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27106 	vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27107     if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
27108 	XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27109 	VERROR_INT("xmlSchemaSAXHandleCDataSection",
27110 	    "calling xmlSchemaVPushText()");
27111 	vctxt->err = -1;
27112 	xmlStopParser(vctxt->parserCtxt);
27113     }
27114 }
27115 
27116 /*
27117 * Process CDATA content.
27118 */
27119 static void
27120 xmlSchemaSAXHandleCDataSection(void *ctx,
27121 			     const xmlChar * ch,
27122 			     int len)
27123 {
27124     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27125 
27126     if (vctxt->depth < 0)
27127 	return;
27128     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27129 	return;
27130     if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27131 	vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27132     if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
27133 	XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27134 	VERROR_INT("xmlSchemaSAXHandleCDataSection",
27135 	    "calling xmlSchemaVPushText()");
27136 	vctxt->err = -1;
27137 	xmlStopParser(vctxt->parserCtxt);
27138     }
27139 }
27140 
27141 static void
27142 xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
27143 			    const xmlChar * name ATTRIBUTE_UNUSED)
27144 {
27145     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27146 
27147     if (vctxt->depth < 0)
27148 	return;
27149     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27150 	return;
27151     /* SAX VAL TODO: What to do here? */
27152     TODO
27153 }
27154 
27155 static void
27156 xmlSchemaSAXHandleStartElementNs(void *ctx,
27157 				 const xmlChar * localname,
27158 				 const xmlChar * prefix ATTRIBUTE_UNUSED,
27159 				 const xmlChar * URI,
27160 				 int nb_namespaces,
27161 				 const xmlChar ** namespaces,
27162 				 int nb_attributes,
27163 				 int nb_defaulted ATTRIBUTE_UNUSED,
27164 				 const xmlChar ** attributes)
27165 {
27166     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27167     int ret;
27168     xmlSchemaNodeInfoPtr ielem;
27169     int i, j;
27170 
27171     /*
27172     * SAX VAL TODO: What to do with nb_defaulted?
27173     */
27174     /*
27175     * Skip elements if inside a "skip" wildcard or invalid.
27176     */
27177     vctxt->depth++;
27178     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27179 	return;
27180     /*
27181     * Push the element.
27182     */
27183     if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27184 	VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27185 	    "calling xmlSchemaValidatorPushElem()");
27186 	goto internal_error;
27187     }
27188     ielem = vctxt->inode;
27189     /*
27190     * TODO: Is this OK?
27191     */
27192     ielem->nodeLine = xmlSAX2GetLineNumber(vctxt->parserCtxt);
27193     ielem->localName = localname;
27194     ielem->nsName = URI;
27195     ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27196     /*
27197     * Register namespaces on the elem info.
27198     */
27199     if (nb_namespaces != 0) {
27200 	/*
27201 	* Although the parser builds its own namespace list,
27202 	* we have no access to it, so we'll use an own one.
27203 	*/
27204         for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
27205 	    /*
27206 	    * Store prefix and namespace name.
27207 	    */
27208 	    if (ielem->nsBindings == NULL) {
27209 		ielem->nsBindings =
27210 		    (const xmlChar **) xmlMalloc(10 *
27211 			sizeof(const xmlChar *));
27212 		if (ielem->nsBindings == NULL) {
27213 		    xmlSchemaVErrMemory(vctxt,
27214 			"allocating namespace bindings for SAX validation",
27215 			NULL);
27216 		    goto internal_error;
27217 		}
27218 		ielem->nbNsBindings = 0;
27219 		ielem->sizeNsBindings = 5;
27220 	    } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
27221 		ielem->sizeNsBindings *= 2;
27222 		ielem->nsBindings =
27223 		    (const xmlChar **) xmlRealloc(
27224 			(void *) ielem->nsBindings,
27225 			ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
27226 		if (ielem->nsBindings == NULL) {
27227 		    xmlSchemaVErrMemory(vctxt,
27228 			"re-allocating namespace bindings for SAX validation",
27229 			NULL);
27230 		    goto internal_error;
27231 		}
27232 	    }
27233 
27234 	    ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
27235 	    if (namespaces[j+1][0] == 0) {
27236 		/*
27237 		* Handle xmlns="".
27238 		*/
27239 		ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
27240 	    } else
27241 		ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
27242 		    namespaces[j+1];
27243 	    ielem->nbNsBindings++;
27244 	}
27245     }
27246     /*
27247     * Register attributes.
27248     * SAX VAL TODO: We are not adding namespace declaration
27249     * attributes yet.
27250     */
27251     if (nb_attributes != 0) {
27252 	xmlChar *value;
27253 
27254         for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
27255 	    /*
27256 	    * Duplicate the value.
27257 	    */
27258 	    value = xmlStrndup(attributes[j+3],
27259 		attributes[j+4] - attributes[j+3]);
27260 	    /*
27261 	    * TODO: Set the node line.
27262 	    */
27263 	    ret = xmlSchemaValidatorPushAttribute(vctxt,
27264 		NULL, ielem->nodeLine, attributes[j], attributes[j+2], 0,
27265 		value, 1);
27266 	    if (ret == -1) {
27267 		VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27268 		    "calling xmlSchemaValidatorPushAttribute()");
27269 		goto internal_error;
27270 	    }
27271 	}
27272     }
27273     /*
27274     * Validate the element.
27275     */
27276     ret = xmlSchemaValidateElem(vctxt);
27277     if (ret != 0) {
27278 	if (ret == -1) {
27279 	    VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27280 		"calling xmlSchemaValidateElem()");
27281 	    goto internal_error;
27282 	}
27283 	goto exit;
27284     }
27285 
27286 exit:
27287     return;
27288 internal_error:
27289     vctxt->err = -1;
27290     xmlStopParser(vctxt->parserCtxt);
27291     return;
27292 }
27293 
27294 static void
27295 xmlSchemaSAXHandleEndElementNs(void *ctx,
27296 			       const xmlChar * localname ATTRIBUTE_UNUSED,
27297 			       const xmlChar * prefix ATTRIBUTE_UNUSED,
27298 			       const xmlChar * URI ATTRIBUTE_UNUSED)
27299 {
27300     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27301     int res;
27302 
27303     /*
27304     * Skip elements if inside a "skip" wildcard or if invalid.
27305     */
27306     if (vctxt->skipDepth != -1) {
27307 	if (vctxt->depth > vctxt->skipDepth) {
27308 	    vctxt->depth--;
27309 	    return;
27310 	} else
27311 	    vctxt->skipDepth = -1;
27312     }
27313     /*
27314     * SAX VAL TODO: Just a temporary check.
27315     */
27316     if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
27317 	(!xmlStrEqual(vctxt->inode->nsName, URI))) {
27318 	VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27319 	    "elem pop mismatch");
27320     }
27321     res = xmlSchemaValidatorPopElem(vctxt);
27322     if (res != 0) {
27323 	if (res < 0) {
27324 	    VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27325 		"calling xmlSchemaValidatorPopElem()");
27326 	    goto internal_error;
27327 	}
27328 	goto exit;
27329     }
27330 exit:
27331     return;
27332 internal_error:
27333     vctxt->err = -1;
27334     xmlStopParser(vctxt->parserCtxt);
27335     return;
27336 }
27337 
27338 /************************************************************************
27339  * 									*
27340  * 			Validation interfaces				*
27341  * 									*
27342  ************************************************************************/
27343 
27344 /**
27345  * xmlSchemaNewValidCtxt:
27346  * @schema:  a precompiled XML Schemas
27347  *
27348  * Create an XML Schemas validation context based on the given schema.
27349  *
27350  * Returns the validation context or NULL in case of error
27351  */
27352 xmlSchemaValidCtxtPtr
27353 xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
27354 {
27355     xmlSchemaValidCtxtPtr ret;
27356 
27357     ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
27358     if (ret == NULL) {
27359         xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
27360         return (NULL);
27361     }
27362     memset(ret, 0, sizeof(xmlSchemaValidCtxt));
27363     ret->type = XML_SCHEMA_CTXT_VALIDATOR;
27364     ret->dict = xmlDictCreate();
27365     ret->nodeQNames = xmlSchemaItemListCreate();
27366     ret->schema = schema;
27367     return (ret);
27368 }
27369 
27370 /**
27371  * xmlSchemaClearValidCtxt:
27372  * @ctxt: the schema validation context
27373  *
27374  * Free the resources associated to the schema validation context;
27375  * leaves some fields alive intended for reuse of the context.
27376  */
27377 static void
27378 xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
27379 {
27380     if (vctxt == NULL)
27381         return;
27382 
27383     /*
27384     * TODO: Should we clear the flags?
27385     *   Might be problematic if one reuses the context
27386     *   and assumes that the options remain the same.
27387     */
27388     vctxt->flags = 0;
27389     vctxt->validationRoot = NULL;
27390     vctxt->doc = NULL;
27391 #ifdef LIBXML_READER_ENABLED
27392     vctxt->reader = NULL;
27393 #endif
27394     vctxt->hasKeyrefs = 0;
27395 
27396     if (vctxt->value != NULL) {
27397         xmlSchemaFreeValue(vctxt->value);
27398 	vctxt->value = NULL;
27399     }
27400     /*
27401     * Augmented IDC information.
27402     */
27403     if (vctxt->aidcs != NULL) {
27404 	xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
27405 	do {
27406 	    next = cur->next;
27407 	    xmlFree(cur);
27408 	    cur = next;
27409 	} while (cur != NULL);
27410 	vctxt->aidcs = NULL;
27411     }
27412     if (vctxt->idcMatcherCache != NULL) {
27413 	xmlSchemaIDCMatcherPtr matcher = vctxt->idcMatcherCache, tmp;
27414 
27415 	while (matcher) {
27416 	    tmp = matcher;
27417 	    matcher = matcher->nextCached;
27418 	    xmlSchemaIDCFreeMatcherList(tmp);
27419 	}
27420 	vctxt->idcMatcherCache = NULL;
27421     }
27422 
27423 
27424     if (vctxt->idcNodes != NULL) {
27425 	int i;
27426 	xmlSchemaPSVIIDCNodePtr item;
27427 
27428 	for (i = 0; i < vctxt->nbIdcNodes; i++) {
27429 	    item = vctxt->idcNodes[i];
27430 	    xmlFree(item->keys);
27431 	    xmlFree(item);
27432 	}
27433 	xmlFree(vctxt->idcNodes);
27434 	vctxt->idcNodes = NULL;
27435 	vctxt->nbIdcNodes = 0;
27436 	vctxt->sizeIdcNodes = 0;
27437     }
27438     /*
27439     * Note that we won't delete the XPath state pool here.
27440     */
27441     if (vctxt->xpathStates != NULL) {
27442 	xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
27443 	vctxt->xpathStates = NULL;
27444     }
27445     /*
27446     * Attribute info.
27447     */
27448     if (vctxt->nbAttrInfos != 0) {
27449 	xmlSchemaClearAttrInfos(vctxt);
27450     }
27451     /*
27452     * Element info.
27453     */
27454     if (vctxt->elemInfos != NULL) {
27455 	int i;
27456 	xmlSchemaNodeInfoPtr ei;
27457 
27458 	for (i = 0; i < vctxt->sizeElemInfos; i++) {
27459 	    ei = vctxt->elemInfos[i];
27460 	    if (ei == NULL)
27461 		break;
27462 	    xmlSchemaClearElemInfo(vctxt, ei);
27463 	}
27464     }
27465     xmlSchemaItemListClear(vctxt->nodeQNames);
27466     /* Recreate the dict. */
27467     xmlDictFree(vctxt->dict);
27468     /*
27469     * TODO: Is is save to recreate it? Do we have a scenario
27470     * where the user provides the dict?
27471     */
27472     vctxt->dict = xmlDictCreate();
27473 }
27474 
27475 /**
27476  * xmlSchemaFreeValidCtxt:
27477  * @ctxt:  the schema validation context
27478  *
27479  * Free the resources associated to the schema validation context
27480  */
27481 void
27482 xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
27483 {
27484     if (ctxt == NULL)
27485         return;
27486     if (ctxt->value != NULL)
27487         xmlSchemaFreeValue(ctxt->value);
27488     if (ctxt->pctxt != NULL)
27489 	xmlSchemaFreeParserCtxt(ctxt->pctxt);
27490     if (ctxt->idcNodes != NULL) {
27491 	int i;
27492 	xmlSchemaPSVIIDCNodePtr item;
27493 
27494 	for (i = 0; i < ctxt->nbIdcNodes; i++) {
27495 	    item = ctxt->idcNodes[i];
27496 	    xmlFree(item->keys);
27497 	    xmlFree(item);
27498 	}
27499 	xmlFree(ctxt->idcNodes);
27500     }
27501     if (ctxt->idcKeys != NULL) {
27502 	int i;
27503 	for (i = 0; i < ctxt->nbIdcKeys; i++)
27504 	    xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
27505 	xmlFree(ctxt->idcKeys);
27506     }
27507 
27508     if (ctxt->xpathStates != NULL) {
27509 	xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
27510 	ctxt->xpathStates = NULL;
27511     }
27512     if (ctxt->xpathStatePool != NULL) {
27513 	xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
27514 	ctxt->xpathStatePool = NULL;
27515     }
27516 
27517     /*
27518     * Augmented IDC information.
27519     */
27520     if (ctxt->aidcs != NULL) {
27521 	xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
27522 	do {
27523 	    next = cur->next;
27524 	    xmlFree(cur);
27525 	    cur = next;
27526 	} while (cur != NULL);
27527     }
27528     if (ctxt->attrInfos != NULL) {
27529 	int i;
27530 	xmlSchemaAttrInfoPtr attr;
27531 
27532 	/* Just a paranoid call to the cleanup. */
27533 	if (ctxt->nbAttrInfos != 0)
27534 	    xmlSchemaClearAttrInfos(ctxt);
27535 	for (i = 0; i < ctxt->sizeAttrInfos; i++) {
27536 	    attr = ctxt->attrInfos[i];
27537 	    xmlFree(attr);
27538 	}
27539 	xmlFree(ctxt->attrInfos);
27540     }
27541     if (ctxt->elemInfos != NULL) {
27542 	int i;
27543 	xmlSchemaNodeInfoPtr ei;
27544 
27545 	for (i = 0; i < ctxt->sizeElemInfos; i++) {
27546 	    ei = ctxt->elemInfos[i];
27547 	    if (ei == NULL)
27548 		break;
27549 	    xmlSchemaClearElemInfo(ctxt, ei);
27550 	    xmlFree(ei);
27551 	}
27552 	xmlFree(ctxt->elemInfos);
27553     }
27554     if (ctxt->nodeQNames != NULL)
27555 	xmlSchemaItemListFree(ctxt->nodeQNames);
27556     if (ctxt->dict != NULL)
27557 	xmlDictFree(ctxt->dict);
27558     xmlFree(ctxt);
27559 }
27560 
27561 /**
27562  * xmlSchemaIsValid:
27563  * @ctxt: the schema validation context
27564  *
27565  * Check if any error was detected during validation.
27566  *
27567  * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
27568  *         of internal error.
27569  */
27570 int
27571 xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
27572 {
27573     if (ctxt == NULL)
27574         return(-1);
27575     return(ctxt->err == 0);
27576 }
27577 
27578 /**
27579  * xmlSchemaSetValidErrors:
27580  * @ctxt:  a schema validation context
27581  * @err:  the error function
27582  * @warn: the warning function
27583  * @ctx: the functions context
27584  *
27585  * Set the error and warning callback informations
27586  */
27587 void
27588 xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
27589                         xmlSchemaValidityErrorFunc err,
27590                         xmlSchemaValidityWarningFunc warn, void *ctx)
27591 {
27592     if (ctxt == NULL)
27593         return;
27594     ctxt->error = err;
27595     ctxt->warning = warn;
27596     ctxt->errCtxt = ctx;
27597     if (ctxt->pctxt != NULL)
27598 	xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
27599 }
27600 
27601 /**
27602  * xmlSchemaSetValidStructuredErrors:
27603  * @ctxt:  a schema validation context
27604  * @serror:  the structured error function
27605  * @ctx: the functions context
27606  *
27607  * Set the structured error callback
27608  */
27609 void
27610 xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
27611 				  xmlStructuredErrorFunc serror, void *ctx)
27612 {
27613     if (ctxt == NULL)
27614         return;
27615 	ctxt->serror = serror;
27616     ctxt->error = NULL;
27617     ctxt->warning = NULL;
27618     ctxt->errCtxt = ctx;
27619     if (ctxt->pctxt != NULL)
27620 	xmlSchemaSetParserStructuredErrors(ctxt->pctxt, serror, ctx);
27621 }
27622 
27623 /**
27624  * xmlSchemaGetValidErrors:
27625  * @ctxt:	a XML-Schema validation context
27626  * @err: the error function result
27627  * @warn: the warning function result
27628  * @ctx: the functions context result
27629  *
27630  * Get the error and warning callback informations
27631  *
27632  * Returns -1 in case of error and 0 otherwise
27633  */
27634 int
27635 xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
27636 			xmlSchemaValidityErrorFunc * err,
27637 			xmlSchemaValidityWarningFunc * warn, void **ctx)
27638 {
27639 	if (ctxt == NULL)
27640 		return (-1);
27641 	if (err != NULL)
27642 		*err = ctxt->error;
27643 	if (warn != NULL)
27644 		*warn = ctxt->warning;
27645 	if (ctx != NULL)
27646 		*ctx = ctxt->errCtxt;
27647 	return (0);
27648 }
27649 
27650 
27651 /**
27652  * xmlSchemaSetValidOptions:
27653  * @ctxt:	a schema validation context
27654  * @options: a combination of xmlSchemaValidOption
27655  *
27656  * Sets the options to be used during the validation.
27657  *
27658  * Returns 0 in case of success, -1 in case of an
27659  * API error.
27660  */
27661 int
27662 xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
27663 			 int options)
27664 
27665 {
27666     int i;
27667 
27668     if (ctxt == NULL)
27669 	return (-1);
27670     /*
27671     * WARNING: Change the start value if adding to the
27672     * xmlSchemaValidOption.
27673     * TODO: Is there an other, more easy to maintain,
27674     * way?
27675     */
27676     for (i = 1; i < (int) sizeof(int) * 8; i++) {
27677         if (options & 1<<i)
27678 	    return (-1);
27679     }
27680     ctxt->options = options;
27681     return (0);
27682 }
27683 
27684 /**
27685  * xmlSchemaValidCtxtGetOptions:
27686  * @ctxt:	a schema validation context
27687  *
27688  * Get the validation context options.
27689  *
27690  * Returns the option combination or -1 on error.
27691  */
27692 int
27693 xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
27694 
27695 {
27696     if (ctxt == NULL)
27697 	return (-1);
27698     else
27699 	return (ctxt->options);
27700 }
27701 
27702 static int
27703 xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
27704 {
27705     xmlAttrPtr attr;
27706     int ret = 0;
27707     xmlSchemaNodeInfoPtr ielem = NULL;
27708     xmlNodePtr node, valRoot;
27709     const xmlChar *nsName;
27710 
27711     /* DOC VAL TODO: Move this to the start function. */
27712     valRoot = xmlDocGetRootElement(vctxt->doc);
27713     if (valRoot == NULL) {
27714 	/* VAL TODO: Error code? */
27715 	VERROR(1, NULL, "The document has no document element");
27716 	return (1);
27717     }
27718     vctxt->depth = -1;
27719     vctxt->validationRoot = valRoot;
27720     node = valRoot;
27721     while (node != NULL) {
27722 	if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27723 	    goto next_sibling;
27724 	if (node->type == XML_ELEMENT_NODE) {
27725 
27726 	    /*
27727 	    * Init the node-info.
27728 	    */
27729 	    vctxt->depth++;
27730 	    if (xmlSchemaValidatorPushElem(vctxt) == -1)
27731 		goto internal_error;
27732 	    ielem = vctxt->inode;
27733 	    ielem->node = node;
27734 	    ielem->nodeLine = node->line;
27735 	    ielem->localName = node->name;
27736 	    if (node->ns != NULL)
27737 		ielem->nsName = node->ns->href;
27738 	    ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27739 	    /*
27740 	    * Register attributes.
27741 	    * DOC VAL TODO: We do not register namespace declaration
27742 	    * attributes yet.
27743 	    */
27744 	    vctxt->nbAttrInfos = 0;
27745 	    if (node->properties != NULL) {
27746 		attr = node->properties;
27747 		do {
27748 		    if (attr->ns != NULL)
27749 			nsName = attr->ns->href;
27750 		    else
27751 			nsName = NULL;
27752 		    ret = xmlSchemaValidatorPushAttribute(vctxt,
27753 			(xmlNodePtr) attr,
27754 			/*
27755 			* Note that we give it the line number of the
27756 			* parent element.
27757 			*/
27758 			ielem->nodeLine,
27759 			attr->name, nsName, 0,
27760 			xmlNodeListGetString(attr->doc, attr->children, 1), 1);
27761 		    if (ret == -1) {
27762 			VERROR_INT("xmlSchemaDocWalk",
27763 			    "calling xmlSchemaValidatorPushAttribute()");
27764 			goto internal_error;
27765 		    }
27766 		    attr = attr->next;
27767 		} while (attr);
27768 	    }
27769 	    /*
27770 	    * Validate the element.
27771 	    */
27772 	    ret = xmlSchemaValidateElem(vctxt);
27773 	    if (ret != 0) {
27774 		if (ret == -1) {
27775 		    VERROR_INT("xmlSchemaDocWalk",
27776 			"calling xmlSchemaValidateElem()");
27777 		    goto internal_error;
27778 		}
27779 		/*
27780 		* Don't stop validation; just skip the content
27781 		* of this element.
27782 		*/
27783 		goto leave_node;
27784 	    }
27785 	    if ((vctxt->skipDepth != -1) &&
27786 		(vctxt->depth >= vctxt->skipDepth))
27787 		goto leave_node;
27788 	} else if ((node->type == XML_TEXT_NODE) ||
27789 	    (node->type == XML_CDATA_SECTION_NODE)) {
27790 	    /*
27791 	    * Process character content.
27792 	    */
27793 	    if ((ielem != NULL) && (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY))
27794 		ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27795 	    ret = xmlSchemaVPushText(vctxt, node->type, node->content,
27796 		-1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
27797 	    if (ret < 0) {
27798 		VERROR_INT("xmlSchemaVDocWalk",
27799 		    "calling xmlSchemaVPushText()");
27800 		goto internal_error;
27801 	    }
27802 	    /*
27803 	    * DOC VAL TODO: Should we skip further validation of the
27804 	    * element content here?
27805 	    */
27806 	} else if ((node->type == XML_ENTITY_NODE) ||
27807 	    (node->type == XML_ENTITY_REF_NODE)) {
27808 	    /*
27809 	    * DOC VAL TODO: What to do with entities?
27810 	    */
27811 	    VERROR_INT("xmlSchemaVDocWalk",
27812 		"there is at least one entity reference in the node-tree "
27813 		"currently being validated. Processing of entities with "
27814 		"this XML Schema processor is not supported (yet). Please "
27815 		"substitute entities before validation.");
27816 	    goto internal_error;
27817 	} else {
27818 	    goto leave_node;
27819 	    /*
27820 	    * DOC VAL TODO: XInclude nodes, etc.
27821 	    */
27822 	}
27823 	/*
27824 	* Walk the doc.
27825 	*/
27826 	if (node->children != NULL) {
27827 	    node = node->children;
27828 	    continue;
27829 	}
27830 leave_node:
27831 	if (node->type == XML_ELEMENT_NODE) {
27832 	    /*
27833 	    * Leaving the scope of an element.
27834 	    */
27835 	    if (node != vctxt->inode->node) {
27836 		VERROR_INT("xmlSchemaVDocWalk",
27837 		    "element position mismatch");
27838 		goto internal_error;
27839 	    }
27840 	    ret = xmlSchemaValidatorPopElem(vctxt);
27841 	    if (ret != 0) {
27842 		if (ret < 0) {
27843 		    VERROR_INT("xmlSchemaVDocWalk",
27844 			"calling xmlSchemaValidatorPopElem()");
27845 		    goto internal_error;
27846 		}
27847 	    }
27848 	    if (node == valRoot)
27849 		goto exit;
27850 	}
27851 next_sibling:
27852 	if (node->next != NULL)
27853 	    node = node->next;
27854 	else {
27855 	    node = node->parent;
27856 	    goto leave_node;
27857 	}
27858     }
27859 
27860 exit:
27861     return (ret);
27862 internal_error:
27863     return (-1);
27864 }
27865 
27866 static int
27867 xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
27868     /*
27869     * Some initialization.
27870     */
27871     vctxt->err = 0;
27872     vctxt->nberrors = 0;
27873     vctxt->depth = -1;
27874     vctxt->skipDepth = -1;
27875     vctxt->xsiAssemble = 0;
27876     vctxt->hasKeyrefs = 0;
27877 #ifdef ENABLE_IDC_NODE_TABLES_TEST
27878     vctxt->createIDCNodeTables = 1;
27879 #else
27880     vctxt->createIDCNodeTables = 0;
27881 #endif
27882     /*
27883     * Create a schema + parser if necessary.
27884     */
27885     if (vctxt->schema == NULL) {
27886 	xmlSchemaParserCtxtPtr pctxt;
27887 
27888 	vctxt->xsiAssemble = 1;
27889 	/*
27890 	* If not schema was given then we will create a schema
27891 	* dynamically using XSI schema locations.
27892 	*
27893 	* Create the schema parser context.
27894 	*/
27895 	if ((vctxt->pctxt == NULL) &&
27896 	   (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
27897 	   return (-1);
27898 	pctxt = vctxt->pctxt;
27899 	pctxt->xsiAssemble = 1;
27900 	/*
27901 	* Create the schema.
27902 	*/
27903 	vctxt->schema = xmlSchemaNewSchema(pctxt);
27904 	if (vctxt->schema == NULL)
27905 	    return (-1);
27906 	/*
27907 	* Create the schema construction context.
27908 	*/
27909 	pctxt->constructor = xmlSchemaConstructionCtxtCreate(pctxt->dict);
27910 	if (pctxt->constructor == NULL)
27911 	    return(-1);
27912 	pctxt->constructor->mainSchema = vctxt->schema;
27913 	/*
27914 	* Take ownership of the constructor to be able to free it.
27915 	*/
27916 	pctxt->ownsConstructor = 1;
27917     }
27918     /*
27919     * Augment the IDC definitions for the main schema and all imported ones
27920     * NOTE: main schema if the first in the imported list
27921     */
27922     xmlHashScan(vctxt->schema->schemasImports,(xmlHashScanner)xmlSchemaAugmentImportedIDC, vctxt);
27923 
27924     return(0);
27925 }
27926 
27927 static void
27928 xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
27929     if (vctxt->xsiAssemble) {
27930 	if (vctxt->schema != NULL) {
27931 	    xmlSchemaFree(vctxt->schema);
27932 	    vctxt->schema = NULL;
27933 	}
27934     }
27935     xmlSchemaClearValidCtxt(vctxt);
27936 }
27937 
27938 static int
27939 xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
27940 {
27941     int ret = 0;
27942 
27943     if (xmlSchemaPreRun(vctxt) < 0)
27944         return(-1);
27945 
27946     if (vctxt->doc != NULL) {
27947 	/*
27948 	 * Tree validation.
27949 	 */
27950 	ret = xmlSchemaVDocWalk(vctxt);
27951 #ifdef LIBXML_READER_ENABLED
27952     } else if (vctxt->reader != NULL) {
27953 	/*
27954 	 * XML Reader validation.
27955 	 */
27956 #ifdef XML_SCHEMA_READER_ENABLED
27957 	ret = xmlSchemaVReaderWalk(vctxt);
27958 #endif
27959 #endif
27960     } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
27961 	/*
27962 	 * SAX validation.
27963 	 */
27964 	ret = xmlParseDocument(vctxt->parserCtxt);
27965     } else {
27966 	VERROR_INT("xmlSchemaVStart",
27967 	    "no instance to validate");
27968 	ret = -1;
27969     }
27970 
27971     xmlSchemaPostRun(vctxt);
27972     if (ret == 0)
27973 	ret = vctxt->err;
27974     return (ret);
27975 }
27976 
27977 /**
27978  * xmlSchemaValidateOneElement:
27979  * @ctxt:  a schema validation context
27980  * @elem:  an element node
27981  *
27982  * Validate a branch of a tree, starting with the given @elem.
27983  *
27984  * Returns 0 if the element and its subtree is valid, a positive error
27985  * code number otherwise and -1 in case of an internal or API error.
27986  */
27987 int
27988 xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
27989 {
27990     if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
27991 	return (-1);
27992 
27993     if (ctxt->schema == NULL)
27994 	return (-1);
27995 
27996     ctxt->doc = elem->doc;
27997     ctxt->node = elem;
27998     ctxt->validationRoot = elem;
27999     return(xmlSchemaVStart(ctxt));
28000 }
28001 
28002 /**
28003  * xmlSchemaValidateDoc:
28004  * @ctxt:  a schema validation context
28005  * @doc:  a parsed document tree
28006  *
28007  * Validate a document tree in memory.
28008  *
28009  * Returns 0 if the document is schemas valid, a positive error code
28010  *     number otherwise and -1 in case of internal or API error.
28011  */
28012 int
28013 xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
28014 {
28015     if ((ctxt == NULL) || (doc == NULL))
28016         return (-1);
28017 
28018     ctxt->doc = doc;
28019     ctxt->node = xmlDocGetRootElement(doc);
28020     if (ctxt->node == NULL) {
28021         xmlSchemaCustomErr(ACTXT_CAST ctxt,
28022 	    XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
28023 	    (xmlNodePtr) doc, NULL,
28024 	    "The document has no document element", NULL, NULL);
28025         return (ctxt->err);
28026     }
28027     ctxt->validationRoot = ctxt->node;
28028     return (xmlSchemaVStart(ctxt));
28029 }
28030 
28031 
28032 /************************************************************************
28033  * 									*
28034  * 		Function and data for SAX streaming API			*
28035  * 									*
28036  ************************************************************************/
28037 typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
28038 typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
28039 
28040 struct _xmlSchemaSplitSAXData {
28041     xmlSAXHandlerPtr      user_sax;
28042     void                 *user_data;
28043     xmlSchemaValidCtxtPtr ctxt;
28044     xmlSAXHandlerPtr      schemas_sax;
28045 };
28046 
28047 #define XML_SAX_PLUG_MAGIC 0xdc43ba21
28048 
28049 struct _xmlSchemaSAXPlug {
28050     unsigned int magic;
28051 
28052     /* the original callbacks informations */
28053     xmlSAXHandlerPtr     *user_sax_ptr;
28054     xmlSAXHandlerPtr      user_sax;
28055     void                **user_data_ptr;
28056     void                 *user_data;
28057 
28058     /* the block plugged back and validation informations */
28059     xmlSAXHandler         schemas_sax;
28060     xmlSchemaValidCtxtPtr ctxt;
28061 };
28062 
28063 /* All those functions just bounces to the user provided SAX handlers */
28064 static void
28065 internalSubsetSplit(void *ctx, const xmlChar *name,
28066 	       const xmlChar *ExternalID, const xmlChar *SystemID)
28067 {
28068     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28069     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28070         (ctxt->user_sax->internalSubset != NULL))
28071 	ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
28072 	                               SystemID);
28073 }
28074 
28075 static int
28076 isStandaloneSplit(void *ctx)
28077 {
28078     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28079     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28080         (ctxt->user_sax->isStandalone != NULL))
28081 	return(ctxt->user_sax->isStandalone(ctxt->user_data));
28082     return(0);
28083 }
28084 
28085 static int
28086 hasInternalSubsetSplit(void *ctx)
28087 {
28088     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28089     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28090         (ctxt->user_sax->hasInternalSubset != NULL))
28091 	return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
28092     return(0);
28093 }
28094 
28095 static int
28096 hasExternalSubsetSplit(void *ctx)
28097 {
28098     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28099     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28100         (ctxt->user_sax->hasExternalSubset != NULL))
28101 	return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
28102     return(0);
28103 }
28104 
28105 static void
28106 externalSubsetSplit(void *ctx, const xmlChar *name,
28107 	       const xmlChar *ExternalID, const xmlChar *SystemID)
28108 {
28109     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28110     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28111         (ctxt->user_sax->externalSubset != NULL))
28112 	ctxt->user_sax->externalSubset(ctxt->user_data, name, ExternalID,
28113 	                               SystemID);
28114 }
28115 
28116 static xmlParserInputPtr
28117 resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
28118 {
28119     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28120     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28121         (ctxt->user_sax->resolveEntity != NULL))
28122 	return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
28123 	                                     systemId));
28124     return(NULL);
28125 }
28126 
28127 static xmlEntityPtr
28128 getEntitySplit(void *ctx, const xmlChar *name)
28129 {
28130     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28131     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28132         (ctxt->user_sax->getEntity != NULL))
28133 	return(ctxt->user_sax->getEntity(ctxt->user_data, name));
28134     return(NULL);
28135 }
28136 
28137 static xmlEntityPtr
28138 getParameterEntitySplit(void *ctx, const xmlChar *name)
28139 {
28140     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28141     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28142         (ctxt->user_sax->getParameterEntity != NULL))
28143 	return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
28144     return(NULL);
28145 }
28146 
28147 
28148 static void
28149 entityDeclSplit(void *ctx, const xmlChar *name, int type,
28150           const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
28151 {
28152     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28153     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28154         (ctxt->user_sax->entityDecl != NULL))
28155 	ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
28156 	                           systemId, content);
28157 }
28158 
28159 static void
28160 attributeDeclSplit(void *ctx, const xmlChar * elem,
28161                    const xmlChar * name, int type, int def,
28162                    const xmlChar * defaultValue, xmlEnumerationPtr tree)
28163 {
28164     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28165     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28166         (ctxt->user_sax->attributeDecl != NULL)) {
28167 	ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
28168 	                              def, defaultValue, tree);
28169     } else {
28170 	xmlFreeEnumeration(tree);
28171     }
28172 }
28173 
28174 static void
28175 elementDeclSplit(void *ctx, const xmlChar *name, int type,
28176 	    xmlElementContentPtr content)
28177 {
28178     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28179     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28180         (ctxt->user_sax->elementDecl != NULL))
28181 	ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
28182 }
28183 
28184 static void
28185 notationDeclSplit(void *ctx, const xmlChar *name,
28186 	     const xmlChar *publicId, const xmlChar *systemId)
28187 {
28188     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28189     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28190         (ctxt->user_sax->notationDecl != NULL))
28191 	ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
28192 	                             systemId);
28193 }
28194 
28195 static void
28196 unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
28197 		   const xmlChar *publicId, const xmlChar *systemId,
28198 		   const xmlChar *notationName)
28199 {
28200     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28201     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28202         (ctxt->user_sax->unparsedEntityDecl != NULL))
28203 	ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
28204 	                                   systemId, notationName);
28205 }
28206 
28207 static void
28208 setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
28209 {
28210     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28211     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28212         (ctxt->user_sax->setDocumentLocator != NULL))
28213 	ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
28214 }
28215 
28216 static void
28217 startDocumentSplit(void *ctx)
28218 {
28219     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28220     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28221         (ctxt->user_sax->startDocument != NULL))
28222 	ctxt->user_sax->startDocument(ctxt->user_data);
28223 }
28224 
28225 static void
28226 endDocumentSplit(void *ctx)
28227 {
28228     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28229     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28230         (ctxt->user_sax->endDocument != NULL))
28231 	ctxt->user_sax->endDocument(ctxt->user_data);
28232 }
28233 
28234 static void
28235 processingInstructionSplit(void *ctx, const xmlChar *target,
28236                       const xmlChar *data)
28237 {
28238     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28239     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28240         (ctxt->user_sax->processingInstruction != NULL))
28241 	ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
28242 }
28243 
28244 static void
28245 commentSplit(void *ctx, const xmlChar *value)
28246 {
28247     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28248     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28249         (ctxt->user_sax->comment != NULL))
28250 	ctxt->user_sax->comment(ctxt->user_data, value);
28251 }
28252 
28253 /*
28254  * Varargs error callbacks to the user application, harder ...
28255  */
28256 
28257 static void XMLCDECL
28258 warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28259     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28260     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28261         (ctxt->user_sax->warning != NULL)) {
28262 	TODO
28263     }
28264 }
28265 static void XMLCDECL
28266 errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28267     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28268     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28269         (ctxt->user_sax->error != NULL)) {
28270 	TODO
28271     }
28272 }
28273 static void XMLCDECL
28274 fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28275     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28276     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28277         (ctxt->user_sax->fatalError != NULL)) {
28278 	TODO
28279     }
28280 }
28281 
28282 /*
28283  * Those are function where both the user handler and the schemas handler
28284  * need to be called.
28285  */
28286 static void
28287 charactersSplit(void *ctx, const xmlChar *ch, int len)
28288 {
28289     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28290     if (ctxt == NULL)
28291         return;
28292     if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
28293 	ctxt->user_sax->characters(ctxt->user_data, ch, len);
28294     if (ctxt->ctxt != NULL)
28295 	xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28296 }
28297 
28298 static void
28299 ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
28300 {
28301     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28302     if (ctxt == NULL)
28303         return;
28304     if ((ctxt->user_sax != NULL) &&
28305         (ctxt->user_sax->ignorableWhitespace != NULL))
28306 	ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
28307     if (ctxt->ctxt != NULL)
28308 	xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28309 }
28310 
28311 static void
28312 cdataBlockSplit(void *ctx, const xmlChar *value, int len)
28313 {
28314     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28315     if (ctxt == NULL)
28316         return;
28317     if ((ctxt->user_sax != NULL) &&
28318         (ctxt->user_sax->cdataBlock != NULL))
28319 	ctxt->user_sax->cdataBlock(ctxt->user_data, value, len);
28320     if (ctxt->ctxt != NULL)
28321 	xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
28322 }
28323 
28324 static void
28325 referenceSplit(void *ctx, const xmlChar *name)
28326 {
28327     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28328     if (ctxt == NULL)
28329         return;
28330     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28331         (ctxt->user_sax->reference != NULL))
28332 	ctxt->user_sax->reference(ctxt->user_data, name);
28333     if (ctxt->ctxt != NULL)
28334         xmlSchemaSAXHandleReference(ctxt->user_data, name);
28335 }
28336 
28337 static void
28338 startElementNsSplit(void *ctx, const xmlChar * localname,
28339 		    const xmlChar * prefix, const xmlChar * URI,
28340 		    int nb_namespaces, const xmlChar ** namespaces,
28341 		    int nb_attributes, int nb_defaulted,
28342 		    const xmlChar ** attributes) {
28343     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28344     if (ctxt == NULL)
28345         return;
28346     if ((ctxt->user_sax != NULL) &&
28347         (ctxt->user_sax->startElementNs != NULL))
28348 	ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
28349 	                               URI, nb_namespaces, namespaces,
28350 				       nb_attributes, nb_defaulted,
28351 				       attributes);
28352     if (ctxt->ctxt != NULL)
28353 	xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
28354 	                                 URI, nb_namespaces, namespaces,
28355 					 nb_attributes, nb_defaulted,
28356 					 attributes);
28357 }
28358 
28359 static void
28360 endElementNsSplit(void *ctx, const xmlChar * localname,
28361 		    const xmlChar * prefix, const xmlChar * URI) {
28362     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28363     if (ctxt == NULL)
28364         return;
28365     if ((ctxt->user_sax != NULL) &&
28366         (ctxt->user_sax->endElementNs != NULL))
28367 	ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
28368     if (ctxt->ctxt != NULL)
28369 	xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
28370 }
28371 
28372 /**
28373  * xmlSchemaSAXPlug:
28374  * @ctxt:  a schema validation context
28375  * @sax:  a pointer to the original xmlSAXHandlerPtr
28376  * @user_data:  a pointer to the original SAX user data pointer
28377  *
28378  * Plug a SAX based validation layer in a SAX parsing event flow.
28379  * The original @saxptr and @dataptr data are replaced by new pointers
28380  * but the calls to the original will be maintained.
28381  *
28382  * Returns a pointer to a data structure needed to unplug the validation layer
28383  *         or NULL in case of errors.
28384  */
28385 xmlSchemaSAXPlugPtr
28386 xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
28387 		 xmlSAXHandlerPtr *sax, void **user_data)
28388 {
28389     xmlSchemaSAXPlugPtr ret;
28390     xmlSAXHandlerPtr old_sax;
28391 
28392     if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
28393         return(NULL);
28394 
28395     /*
28396      * We only allow to plug into SAX2 event streams
28397      */
28398     old_sax = *sax;
28399     if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
28400         return(NULL);
28401     if ((old_sax != NULL) &&
28402         (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
28403         ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
28404         return(NULL);
28405 
28406     /*
28407      * everything seems right allocate the local data needed for that layer
28408      */
28409     ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
28410     if (ret == NULL) {
28411         return(NULL);
28412     }
28413     memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
28414     ret->magic = XML_SAX_PLUG_MAGIC;
28415     ret->schemas_sax.initialized = XML_SAX2_MAGIC;
28416     ret->ctxt = ctxt;
28417     ret->user_sax_ptr = sax;
28418     ret->user_sax = old_sax;
28419     if (old_sax == NULL) {
28420         /*
28421 	 * go direct, no need for the split block and functions.
28422 	 */
28423 	ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
28424 	ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
28425 	/*
28426 	 * Note that we use the same text-function for both, to prevent
28427 	 * the parser from testing for ignorable whitespace.
28428 	 */
28429 	ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
28430 	ret->schemas_sax.characters = xmlSchemaSAXHandleText;
28431 
28432 	ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
28433 	ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
28434 
28435 	ret->user_data = ctxt;
28436 	*user_data = ctxt;
28437     } else {
28438        /*
28439         * for each callback unused by Schemas initialize it to the Split
28440 	* routine only if non NULL in the user block, this can speed up
28441 	* things at the SAX level.
28442 	*/
28443         if (old_sax->internalSubset != NULL)
28444             ret->schemas_sax.internalSubset = internalSubsetSplit;
28445         if (old_sax->isStandalone != NULL)
28446             ret->schemas_sax.isStandalone = isStandaloneSplit;
28447         if (old_sax->hasInternalSubset != NULL)
28448             ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
28449         if (old_sax->hasExternalSubset != NULL)
28450             ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
28451         if (old_sax->resolveEntity != NULL)
28452             ret->schemas_sax.resolveEntity = resolveEntitySplit;
28453         if (old_sax->getEntity != NULL)
28454             ret->schemas_sax.getEntity = getEntitySplit;
28455         if (old_sax->entityDecl != NULL)
28456             ret->schemas_sax.entityDecl = entityDeclSplit;
28457         if (old_sax->notationDecl != NULL)
28458             ret->schemas_sax.notationDecl = notationDeclSplit;
28459         if (old_sax->attributeDecl != NULL)
28460             ret->schemas_sax.attributeDecl = attributeDeclSplit;
28461         if (old_sax->elementDecl != NULL)
28462             ret->schemas_sax.elementDecl = elementDeclSplit;
28463         if (old_sax->unparsedEntityDecl != NULL)
28464             ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
28465         if (old_sax->setDocumentLocator != NULL)
28466             ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
28467         if (old_sax->startDocument != NULL)
28468             ret->schemas_sax.startDocument = startDocumentSplit;
28469         if (old_sax->endDocument != NULL)
28470             ret->schemas_sax.endDocument = endDocumentSplit;
28471         if (old_sax->processingInstruction != NULL)
28472             ret->schemas_sax.processingInstruction = processingInstructionSplit;
28473         if (old_sax->comment != NULL)
28474             ret->schemas_sax.comment = commentSplit;
28475         if (old_sax->warning != NULL)
28476             ret->schemas_sax.warning = warningSplit;
28477         if (old_sax->error != NULL)
28478             ret->schemas_sax.error = errorSplit;
28479         if (old_sax->fatalError != NULL)
28480             ret->schemas_sax.fatalError = fatalErrorSplit;
28481         if (old_sax->getParameterEntity != NULL)
28482             ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
28483         if (old_sax->externalSubset != NULL)
28484             ret->schemas_sax.externalSubset = externalSubsetSplit;
28485 
28486 	/*
28487 	 * the 6 schemas callback have to go to the splitter functions
28488 	 * Note that we use the same text-function for ignorableWhitespace
28489 	 * if possible, to prevent the parser from testing for ignorable
28490 	 * whitespace.
28491 	 */
28492         ret->schemas_sax.characters = charactersSplit;
28493 	if ((old_sax->ignorableWhitespace != NULL) &&
28494 	    (old_sax->ignorableWhitespace != old_sax->characters))
28495 	    ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
28496 	else
28497 	    ret->schemas_sax.ignorableWhitespace = charactersSplit;
28498         ret->schemas_sax.cdataBlock = cdataBlockSplit;
28499         ret->schemas_sax.reference = referenceSplit;
28500         ret->schemas_sax.startElementNs = startElementNsSplit;
28501         ret->schemas_sax.endElementNs = endElementNsSplit;
28502 
28503 	ret->user_data_ptr = user_data;
28504 	ret->user_data = *user_data;
28505 	*user_data = ret;
28506     }
28507 
28508     /*
28509      * plug the pointers back.
28510      */
28511     *sax = &(ret->schemas_sax);
28512     ctxt->sax = *sax;
28513     ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28514     xmlSchemaPreRun(ctxt);
28515     return(ret);
28516 }
28517 
28518 /**
28519  * xmlSchemaSAXUnplug:
28520  * @plug:  a data structure returned by xmlSchemaSAXPlug
28521  *
28522  * Unplug a SAX based validation layer in a SAX parsing event flow.
28523  * The original pointers used in the call are restored.
28524  *
28525  * Returns 0 in case of success and -1 in case of failure.
28526  */
28527 int
28528 xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
28529 {
28530     xmlSAXHandlerPtr *sax;
28531     void **user_data;
28532 
28533     if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
28534         return(-1);
28535     plug->magic = 0;
28536 
28537     xmlSchemaPostRun(plug->ctxt);
28538     /* restore the data */
28539     sax = plug->user_sax_ptr;
28540     *sax = plug->user_sax;
28541     if (plug->user_sax != NULL) {
28542 	user_data = plug->user_data_ptr;
28543 	*user_data = plug->user_data;
28544     }
28545 
28546     /* free and return */
28547     xmlFree(plug);
28548     return(0);
28549 }
28550 
28551 /**
28552  * xmlSchemaValidateStream:
28553  * @ctxt:  a schema validation context
28554  * @input:  the input to use for reading the data
28555  * @enc:  an optional encoding information
28556  * @sax:  a SAX handler for the resulting events
28557  * @user_data:  the context to provide to the SAX handler.
28558  *
28559  * Validate an input based on a flow of SAX event from the parser
28560  * and forward the events to the @sax handler with the provided @user_data
28561  * the user provided @sax handler must be a SAX2 one.
28562  *
28563  * Returns 0 if the document is schemas valid, a positive error code
28564  *     number otherwise and -1 in case of internal or API error.
28565  */
28566 int
28567 xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
28568                         xmlParserInputBufferPtr input, xmlCharEncoding enc,
28569                         xmlSAXHandlerPtr sax, void *user_data)
28570 {
28571     xmlSchemaSAXPlugPtr plug = NULL;
28572     xmlSAXHandlerPtr old_sax = NULL;
28573     xmlParserCtxtPtr pctxt = NULL;
28574     xmlParserInputPtr inputStream = NULL;
28575     int ret;
28576 
28577     if ((ctxt == NULL) || (input == NULL))
28578         return (-1);
28579 
28580     /*
28581      * prepare the parser
28582      */
28583     pctxt = xmlNewParserCtxt();
28584     if (pctxt == NULL)
28585         return (-1);
28586     old_sax = pctxt->sax;
28587     pctxt->sax = sax;
28588     pctxt->userData = user_data;
28589 #if 0
28590     if (options)
28591         xmlCtxtUseOptions(pctxt, options);
28592 #endif
28593     pctxt->linenumbers = 1;
28594 
28595     inputStream = xmlNewIOInputStream(pctxt, input, enc);;
28596     if (inputStream == NULL) {
28597         ret = -1;
28598 	goto done;
28599     }
28600     inputPush(pctxt, inputStream);
28601     ctxt->parserCtxt = pctxt;
28602     ctxt->input = input;
28603 
28604     /*
28605      * Plug the validation and launch the parsing
28606      */
28607     plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
28608     if (plug == NULL) {
28609         ret = -1;
28610 	goto done;
28611     }
28612     ctxt->input = input;
28613     ctxt->enc = enc;
28614     ctxt->sax = pctxt->sax;
28615     ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28616     ret = xmlSchemaVStart(ctxt);
28617 
28618     if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
28619 	ret = ctxt->parserCtxt->errNo;
28620 	if (ret == 0)
28621 	    ret = 1;
28622     }
28623 
28624 done:
28625     ctxt->parserCtxt = NULL;
28626     ctxt->sax = NULL;
28627     ctxt->input = NULL;
28628     if (plug != NULL) {
28629         xmlSchemaSAXUnplug(plug);
28630     }
28631     /* cleanup */
28632     if (pctxt != NULL) {
28633 	pctxt->sax = old_sax;
28634 	xmlFreeParserCtxt(pctxt);
28635     }
28636     return (ret);
28637 }
28638 
28639 /**
28640  * xmlSchemaValidateFile:
28641  * @ctxt: a schema validation context
28642  * @filename: the URI of the instance
28643  * @options: a future set of options, currently unused
28644  *
28645  * Do a schemas validation of the given resource, it will use the
28646  * SAX streamable validation internally.
28647  *
28648  * Returns 0 if the document is valid, a positive error code
28649  *     number otherwise and -1 in case of an internal or API error.
28650  */
28651 int
28652 xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
28653                       const char * filename,
28654 		      int options ATTRIBUTE_UNUSED)
28655 {
28656     int ret;
28657     xmlParserInputBufferPtr input;
28658 
28659     if ((ctxt == NULL) || (filename == NULL))
28660         return (-1);
28661 
28662     input = xmlParserInputBufferCreateFilename(filename,
28663 	XML_CHAR_ENCODING_NONE);
28664     if (input == NULL)
28665 	return (-1);
28666     ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
28667 	NULL, NULL);
28668     return (ret);
28669 }
28670 
28671 #define bottom_xmlschemas
28672 #include "elfgcchack.h"
28673 #endif /* LIBXML_SCHEMAS_ENABLED */
28674