• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, "%s", 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 
13310 static xmlSchemaTypePtr
13311 xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
13312 {
13313     if (type == NULL)
13314 	return (NULL);
13315     if (WXS_IS_COMPLEX(type))
13316 	return (NULL);
13317     if (type->type == XML_SCHEMA_TYPE_BASIC)
13318 	return(type);
13319     return(xmlSchemaQueryBuiltInType(type->subtypes));
13320 }
13321 #endif
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 #if 0
14598 /**
14599  * xmlSchemaGetParticleTotalRangeMax:
14600  * @particle: the particle
14601  *
14602  * Schema Component Constraint: Effective Total Range
14603  * (all and sequence) + (choice)
14604  *
14605  * Returns the maximum Effective Total Range.
14606  */
14607 static int
14608 xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
14609 {
14610     if ((particle->children == NULL) ||
14611 	(particle->children->children == NULL))
14612 	return (0);
14613     if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14614 	int max = -1, cur;
14615 	xmlSchemaParticlePtr part =
14616 	    (xmlSchemaParticlePtr) particle->children->children;
14617 
14618 	for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14619 	    if (part->children == NULL)
14620 		continue;
14621 	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14622 		(part->children->type == XML_SCHEMA_TYPE_ANY))
14623 		cur = part->maxOccurs;
14624 	    else
14625 		cur = xmlSchemaGetParticleTotalRangeMax(part);
14626 	    if (cur == UNBOUNDED)
14627 		return (UNBOUNDED);
14628 	    if ((max < cur) || (max == -1))
14629 		max = cur;
14630 	}
14631 	/* TODO: Handle overflows? */
14632 	return (particle->maxOccurs * max);
14633     } else {
14634 	/* <all> and <sequence> */
14635 	int sum = 0, cur;
14636 	xmlSchemaParticlePtr part =
14637 	    (xmlSchemaParticlePtr) particle->children->children;
14638 
14639 	for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14640 	    if (part->children == NULL)
14641 		continue;
14642 	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14643 		(part->children->type == XML_SCHEMA_TYPE_ANY))
14644 		cur = part->maxOccurs;
14645 	    else
14646 		cur = xmlSchemaGetParticleTotalRangeMax(part);
14647 	    if (cur == UNBOUNDED)
14648 		return (UNBOUNDED);
14649 	    if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
14650 		return (UNBOUNDED);
14651 	    sum += cur;
14652 	}
14653 	/* TODO: Handle overflows? */
14654 	return (particle->maxOccurs * sum);
14655     }
14656 }
14657 #endif
14658 
14659 /**
14660  * xmlSchemaIsParticleEmptiable:
14661  * @particle: the particle
14662  *
14663  * Schema Component Constraint: Particle Emptiable
14664  * Checks whether the given particle is emptiable.
14665  *
14666  * Returns 1 if emptiable, 0 otherwise.
14667  */
14668 static int
xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)14669 xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
14670 {
14671     /*
14672     * SPEC (1) "Its {min occurs} is 0."
14673     */
14674     if ((particle == NULL) || (particle->minOccurs == 0) ||
14675 	(particle->children == NULL))
14676 	return (1);
14677     /*
14678     * SPEC (2) "Its {term} is a group and the minimum part of the
14679     * effective total range of that group, [...] is 0."
14680     */
14681     if (WXS_IS_MODEL_GROUP(particle->children)) {
14682 	if (xmlSchemaGetParticleTotalRangeMin(particle) == 0)
14683 	    return (1);
14684     }
14685     return (0);
14686 }
14687 
14688 /**
14689  * xmlSchemaCheckCOSSTDerivedOK:
14690  * @actxt: a context
14691  * @type:  the derived simple type definition
14692  * @baseType:  the base type definition
14693  * @subset: the subset of ('restriction', ect.)
14694  *
14695  * Schema Component Constraint:
14696  * Type Derivation OK (Simple) (cos-st-derived-OK)
14697  *
14698  * Checks wheter @type can be validly
14699  * derived from @baseType.
14700  *
14701  * Returns 0 on success, an positive error code otherwise.
14702  */
14703 static int
xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,xmlSchemaTypePtr type,xmlSchemaTypePtr baseType,int subset)14704 xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
14705 			     xmlSchemaTypePtr type,
14706 			     xmlSchemaTypePtr baseType,
14707 			     int subset)
14708 {
14709     /*
14710     * 1 They are the same type definition.
14711     * TODO: The identy check might have to be more complex than this.
14712     */
14713     if (type == baseType)
14714 	return (0);
14715     /*
14716     * 2.1 restriction is not in the subset, or in the {final}
14717     * of its own {base type definition};
14718     *
14719     * NOTE that this will be used also via "xsi:type".
14720     *
14721     * TODO: Revise this, it looks strange. How can the "type"
14722     * not be fixed or *in* fixing?
14723     */
14724     if (WXS_IS_TYPE_NOT_FIXED(type))
14725 	if (xmlSchemaTypeFixup(type, actxt) == -1)
14726 	    return(-1);
14727     if (WXS_IS_TYPE_NOT_FIXED(baseType))
14728 	if (xmlSchemaTypeFixup(baseType, actxt) == -1)
14729 	    return(-1);
14730     if ((subset & SUBSET_RESTRICTION) ||
14731 	(xmlSchemaTypeFinalContains(type->baseType,
14732 	    XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
14733 	return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
14734     }
14735     /* 2.2 */
14736     if (type->baseType == baseType) {
14737 	/*
14738 	* 2.2.1 D's �base type definition� is B.
14739 	*/
14740 	return (0);
14741     }
14742     /*
14743     * 2.2.2 D's �base type definition� is not the �ur-type definition�
14744     * and is validly derived from B given the subset, as defined by this
14745     * constraint.
14746     */
14747     if ((! WXS_IS_ANYTYPE(type->baseType)) &&
14748 	(xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
14749 	    baseType, subset) == 0)) {
14750 	return (0);
14751     }
14752     /*
14753     * 2.2.3 D's {variety} is list or union and B is the �simple ur-type
14754     * definition�.
14755     */
14756     if (WXS_IS_ANY_SIMPLE_TYPE(baseType) &&
14757 	(WXS_IS_LIST(type) || WXS_IS_UNION(type))) {
14758 	return (0);
14759     }
14760     /*
14761     * 2.2.4 B's {variety} is union and D is validly derived from a type
14762     * definition in B's {member type definitions} given the subset, as
14763     * defined by this constraint.
14764     *
14765     * NOTE: This seems not to involve built-in types, since there is no
14766     * built-in Union Simple Type.
14767     */
14768     if (WXS_IS_UNION(baseType)) {
14769 	xmlSchemaTypeLinkPtr cur;
14770 
14771 	cur = baseType->memberTypes;
14772 	while (cur != NULL) {
14773 	    if (WXS_IS_TYPE_NOT_FIXED(cur->type))
14774 		if (xmlSchemaTypeFixup(cur->type, actxt) == -1)
14775 		    return(-1);
14776 	    if (xmlSchemaCheckCOSSTDerivedOK(actxt,
14777 		    type, cur->type, subset) == 0)
14778 	    {
14779 		/*
14780 		* It just has to be validly derived from at least one
14781 		* member-type.
14782 		*/
14783 		return (0);
14784 	    }
14785 	    cur = cur->next;
14786 	}
14787     }
14788     return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
14789 }
14790 
14791 /**
14792  * xmlSchemaCheckTypeDefCircularInternal:
14793  * @pctxt:  the schema parser context
14794  * @ctxtType:  the type definition
14795  * @ancestor: an ancestor of @ctxtType
14796  *
14797  * Checks st-props-correct (2) + ct-props-correct (3).
14798  * Circular type definitions are not allowed.
14799  *
14800  * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
14801  * circular, 0 otherwise.
14802  */
14803 static int
xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr ctxtType,xmlSchemaTypePtr ancestor)14804 xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
14805 			   xmlSchemaTypePtr ctxtType,
14806 			   xmlSchemaTypePtr ancestor)
14807 {
14808     int ret;
14809 
14810     if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
14811 	return (0);
14812 
14813     if (ctxtType == ancestor) {
14814 	xmlSchemaPCustomErr(pctxt,
14815 	    XML_SCHEMAP_ST_PROPS_CORRECT_2,
14816 	    WXS_BASIC_CAST ctxtType, WXS_ITEM_NODE(ctxtType),
14817 	    "The definition is circular", NULL);
14818 	return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
14819     }
14820     if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
14821 	/*
14822 	* Avoid inifinite recursion on circular types not yet checked.
14823 	*/
14824 	return (0);
14825     }
14826     ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
14827     ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
14828 	ancestor->baseType);
14829     ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
14830     return (ret);
14831 }
14832 
14833 /**
14834  * xmlSchemaCheckTypeDefCircular:
14835  * @item:  the complex/simple type definition
14836  * @ctxt:  the parser context
14837  * @name:  the name
14838  *
14839  * Checks for circular type definitions.
14840  */
14841 static void
xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,xmlSchemaParserCtxtPtr ctxt)14842 xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
14843 			      xmlSchemaParserCtxtPtr ctxt)
14844 {
14845     if ((item == NULL) ||
14846 	(item->type == XML_SCHEMA_TYPE_BASIC) ||
14847 	(item->baseType == NULL))
14848 	return;
14849     xmlSchemaCheckTypeDefCircularInternal(ctxt, item,
14850 	item->baseType);
14851 }
14852 
14853 /*
14854 * Simple Type Definition Representation OK (src-simple-type) 4
14855 *
14856 * "4 Circular union type definition is disallowed. That is, if the
14857 * <union> alternative is chosen, there must not be any entries in the
14858 * memberTypes [attribute] at any depth which resolve to the component
14859 * corresponding to the <simpleType>."
14860 *
14861 * Note that this should work on the *representation* of a component,
14862 * thus assumes any union types in the member types not being yet
14863 * substituted. At this stage we need the variety of the types
14864 * to be already computed.
14865 */
14866 static int
xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr ctxType,xmlSchemaTypeLinkPtr members)14867 xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,
14868 					xmlSchemaTypePtr ctxType,
14869 					xmlSchemaTypeLinkPtr members)
14870 {
14871     xmlSchemaTypeLinkPtr member;
14872     xmlSchemaTypePtr memberType;
14873 
14874     member = members;
14875     while (member != NULL) {
14876 	memberType = member->type;
14877 	while ((memberType != NULL) &&
14878 	    (memberType->type != XML_SCHEMA_TYPE_BASIC)) {
14879 	    if (memberType == ctxType) {
14880 		xmlSchemaPCustomErr(pctxt,
14881 		    XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
14882 		    WXS_BASIC_CAST ctxType, NULL,
14883 		    "The union type definition is circular", NULL);
14884 		return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
14885 	    }
14886 	    if ((WXS_IS_UNION(memberType)) &&
14887 		((memberType->flags & XML_SCHEMAS_TYPE_MARKED) == 0))
14888 	    {
14889 		int res;
14890 		memberType->flags |= XML_SCHEMAS_TYPE_MARKED;
14891 		res = xmlSchemaCheckUnionTypeDefCircularRecur(pctxt,
14892 		    ctxType,
14893 		    xmlSchemaGetUnionSimpleTypeMemberTypes(memberType));
14894 		memberType->flags ^= XML_SCHEMAS_TYPE_MARKED;
14895 		if (res != 0)
14896 		    return(res);
14897 	    }
14898 	    memberType = memberType->baseType;
14899 	}
14900 	member = member->next;
14901     }
14902     return(0);
14903 }
14904 
14905 static int
xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)14906 xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,
14907 				   xmlSchemaTypePtr type)
14908 {
14909     if (! WXS_IS_UNION(type))
14910 	return(0);
14911     return(xmlSchemaCheckUnionTypeDefCircularRecur(pctxt, type,
14912 	type->memberTypes));
14913 }
14914 
14915 /**
14916  * xmlSchemaResolveTypeReferences:
14917  * @item:  the complex/simple type definition
14918  * @ctxt:  the parser context
14919  * @name:  the name
14920  *
14921  * Resolvese type definition references
14922  */
14923 static void
xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,xmlSchemaParserCtxtPtr ctxt)14924 xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,
14925 			 xmlSchemaParserCtxtPtr ctxt)
14926 {
14927     if (typeDef == NULL)
14928 	return;
14929 
14930     /*
14931     * Resolve the base type.
14932     */
14933     if (typeDef->baseType == NULL) {
14934 	typeDef->baseType = xmlSchemaGetType(ctxt->schema,
14935 	    typeDef->base, typeDef->baseNs);
14936 	if (typeDef->baseType == NULL) {
14937 	    xmlSchemaPResCompAttrErr(ctxt,
14938 		XML_SCHEMAP_SRC_RESOLVE,
14939 		WXS_BASIC_CAST typeDef, typeDef->node,
14940 		"base", typeDef->base, typeDef->baseNs,
14941 		XML_SCHEMA_TYPE_SIMPLE, NULL);
14942 	    return;
14943 	}
14944     }
14945     if (WXS_IS_SIMPLE(typeDef)) {
14946 	if (WXS_IS_UNION(typeDef)) {
14947 	    /*
14948 	    * Resolve the memberTypes.
14949 	    */
14950 	    xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
14951 	    return;
14952 	} else if (WXS_IS_LIST(typeDef)) {
14953 	    /*
14954 	    * Resolve the itemType.
14955 	    */
14956 	    if ((typeDef->subtypes == NULL) && (typeDef->base != NULL)) {
14957 
14958 		typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
14959 		    typeDef->base, typeDef->baseNs);
14960 
14961 		if ((typeDef->subtypes == NULL) ||
14962 		    (! WXS_IS_SIMPLE(typeDef->subtypes)))
14963 		{
14964 		    typeDef->subtypes = NULL;
14965 		    xmlSchemaPResCompAttrErr(ctxt,
14966 			XML_SCHEMAP_SRC_RESOLVE,
14967 			WXS_BASIC_CAST typeDef, typeDef->node,
14968 			"itemType", typeDef->base, typeDef->baseNs,
14969 			XML_SCHEMA_TYPE_SIMPLE, NULL);
14970 		}
14971 	    }
14972 	    return;
14973 	}
14974     }
14975     /*
14976     * The ball of letters below means, that if we have a particle
14977     * which has a QName-helper component as its {term}, we want
14978     * to resolve it...
14979     */
14980     else if ((WXS_TYPE_CONTENTTYPE(typeDef) != NULL) &&
14981 	((WXS_TYPE_CONTENTTYPE(typeDef))->type ==
14982 	    XML_SCHEMA_TYPE_PARTICLE) &&
14983 	(WXS_TYPE_PARTICLE_TERM(typeDef) != NULL) &&
14984 	((WXS_TYPE_PARTICLE_TERM(typeDef))->type ==
14985 	    XML_SCHEMA_EXTRA_QNAMEREF))
14986     {
14987 	xmlSchemaQNameRefPtr ref =
14988 	    WXS_QNAME_CAST WXS_TYPE_PARTICLE_TERM(typeDef);
14989 	xmlSchemaModelGroupDefPtr groupDef;
14990 
14991 	/*
14992 	* URGENT TODO: Test this.
14993 	*/
14994 	WXS_TYPE_PARTICLE_TERM(typeDef) = NULL;
14995 	/*
14996 	* Resolve the MG definition reference.
14997 	*/
14998 	groupDef =
14999 	    WXS_MODEL_GROUPDEF_CAST xmlSchemaGetNamedComponent(ctxt->schema,
15000 		ref->itemType, ref->name, ref->targetNamespace);
15001 	if (groupDef == NULL) {
15002 	    xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
15003 		NULL, WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)),
15004 		"ref", ref->name, ref->targetNamespace, ref->itemType,
15005 		NULL);
15006 	    /* Remove the particle. */
15007 	    WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15008 	} else if (WXS_MODELGROUPDEF_MODEL(groupDef) == NULL)
15009 	    /* Remove the particle. */
15010 	    WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15011 	else {
15012 	    /*
15013 	    * Assign the MG definition's {model group} to the
15014 	    * particle's {term}.
15015 	    */
15016 	    WXS_TYPE_PARTICLE_TERM(typeDef) = WXS_MODELGROUPDEF_MODEL(groupDef);
15017 
15018 	    if (WXS_MODELGROUPDEF_MODEL(groupDef)->type == XML_SCHEMA_TYPE_ALL) {
15019 		/*
15020 		* SPEC cos-all-limited (1.2)
15021 		* "1.2 the {term} property of a particle with
15022 		* {max occurs}=1 which is part of a pair which constitutes
15023 		* the {content type} of a complex type definition."
15024 		*/
15025 		if ((WXS_TYPE_PARTICLE(typeDef))->maxOccurs != 1) {
15026 		    xmlSchemaCustomErr(ACTXT_CAST ctxt,
15027 			/* TODO: error code */
15028 			XML_SCHEMAP_COS_ALL_LIMITED,
15029 			WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)), NULL,
15030 			"The particle's {max occurs} must be 1, since the "
15031 			"reference resolves to an 'all' model group",
15032 			NULL, NULL);
15033 		}
15034 	    }
15035 	}
15036     }
15037 }
15038 
15039 
15040 
15041 /**
15042  * xmlSchemaCheckSTPropsCorrect:
15043  * @ctxt:  the schema parser context
15044  * @type:  the simple type definition
15045  *
15046  * Checks st-props-correct.
15047  *
15048  * Returns 0 if the properties are correct,
15049  * if not, a positive error code and -1 on internal
15050  * errors.
15051  */
15052 static int
xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)15053 xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
15054 			     xmlSchemaTypePtr type)
15055 {
15056     xmlSchemaTypePtr baseType = type->baseType;
15057     xmlChar *str = NULL;
15058 
15059     /* STATE: error funcs converted. */
15060     /*
15061     * Schema Component Constraint: Simple Type Definition Properties Correct
15062     *
15063     * NOTE: This is somehow redundant, since we actually built a simple type
15064     * to have all the needed information; this acts as an self test.
15065     */
15066     /* Base type: If the datatype has been �derived� by �restriction�
15067     * then the Simple Type Definition component from which it is �derived�,
15068     * otherwise the Simple Type Definition for anySimpleType (�4.1.6).
15069     */
15070     if (baseType == NULL) {
15071 	/*
15072 	* TODO: Think about: "modulo the impact of Missing
15073 	* Sub-components (�5.3)."
15074 	*/
15075 	xmlSchemaPCustomErr(ctxt,
15076 	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15077 	    WXS_BASIC_CAST type, NULL,
15078 	    "No base type existent", NULL);
15079 	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15080 
15081     }
15082     if (! WXS_IS_SIMPLE(baseType)) {
15083 	xmlSchemaPCustomErr(ctxt,
15084 	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15085 	    WXS_BASIC_CAST type, NULL,
15086 	    "The base type '%s' is not a simple type",
15087 	    xmlSchemaGetComponentQName(&str, baseType));
15088 	FREE_AND_NULL(str)
15089 	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15090     }
15091     if ( (WXS_IS_LIST(type) || WXS_IS_UNION(type)) &&
15092 	 (WXS_IS_RESTRICTION(type) == 0) &&
15093 	 (! WXS_IS_ANY_SIMPLE_TYPE(baseType))) {
15094 	xmlSchemaPCustomErr(ctxt,
15095 	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15096 	    WXS_BASIC_CAST type, NULL,
15097 	    "A type, derived by list or union, must have "
15098 	    "the simple ur-type definition as base type, not '%s'",
15099 	    xmlSchemaGetComponentQName(&str, baseType));
15100 	FREE_AND_NULL(str)
15101 	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15102     }
15103     /*
15104     * Variety: One of {atomic, list, union}.
15105     */
15106     if ((! WXS_IS_ATOMIC(type)) && (! WXS_IS_UNION(type)) &&
15107 	(! WXS_IS_LIST(type))) {
15108 	xmlSchemaPCustomErr(ctxt,
15109 	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15110 	    WXS_BASIC_CAST type, NULL,
15111 	    "The variety is absent", NULL);
15112 	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15113     }
15114     /* TODO: Finish this. Hmm, is this finished? */
15115 
15116     /*
15117     * 3 The {final} of the {base type definition} must not contain restriction.
15118     */
15119     if (xmlSchemaTypeFinalContains(baseType,
15120 	XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15121 	xmlSchemaPCustomErr(ctxt,
15122 	    XML_SCHEMAP_ST_PROPS_CORRECT_3,
15123 	    WXS_BASIC_CAST type, NULL,
15124 	    "The 'final' of its base type '%s' must not contain "
15125 	    "'restriction'",
15126 	    xmlSchemaGetComponentQName(&str, baseType));
15127 	FREE_AND_NULL(str)
15128 	return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
15129     }
15130 
15131     /*
15132     * 2 All simple type definitions must be derived ultimately from the �simple
15133     * ur-type definition (so� circular definitions are disallowed). That is, it
15134     * must be possible to reach a built-in primitive datatype or the �simple
15135     * ur-type definition� by repeatedly following the {base type definition}.
15136     *
15137     * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
15138     */
15139     return (0);
15140 }
15141 
15142 /**
15143  * xmlSchemaCheckCOSSTRestricts:
15144  * @ctxt:  the schema parser context
15145  * @type:  the simple type definition
15146  *
15147  * Schema Component Constraint:
15148  * Derivation Valid (Restriction, Simple) (cos-st-restricts)
15149 
15150  * Checks if the given @type (simpleType) is derived validly by restriction.
15151  * STATUS:
15152  *
15153  * Returns -1 on internal errors, 0 if the type is validly derived,
15154  * a positive error code otherwise.
15155  */
15156 static int
xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)15157 xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
15158 			     xmlSchemaTypePtr type)
15159 {
15160     xmlChar *str = NULL;
15161 
15162     if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
15163 	PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15164 	    "given type is not a user-derived simpleType");
15165 	return (-1);
15166     }
15167 
15168     if (WXS_IS_ATOMIC(type)) {
15169 	xmlSchemaTypePtr primitive;
15170 	/*
15171 	* 1.1 The {base type definition} must be an atomic simple
15172 	* type definition or a built-in primitive datatype.
15173 	*/
15174 	if (! WXS_IS_ATOMIC(type->baseType)) {
15175 	    xmlSchemaPCustomErr(pctxt,
15176 		XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
15177 		WXS_BASIC_CAST type, NULL,
15178 		"The base type '%s' is not an atomic simple type",
15179 		xmlSchemaGetComponentQName(&str, type->baseType));
15180 	    FREE_AND_NULL(str)
15181 	    return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
15182 	}
15183 	/* 1.2 The {final} of the {base type definition} must not contain
15184 	* restriction.
15185 	*/
15186 	/* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
15187 	if (xmlSchemaTypeFinalContains(type->baseType,
15188 	    XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15189 	    xmlSchemaPCustomErr(pctxt,
15190 		XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
15191 		WXS_BASIC_CAST type, NULL,
15192 		"The final of its base type '%s' must not contain 'restriction'",
15193 		xmlSchemaGetComponentQName(&str, type->baseType));
15194 	    FREE_AND_NULL(str)
15195 	    return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
15196 	}
15197 
15198 	/*
15199 	* 1.3.1 DF must be an allowed constraining facet for the {primitive
15200 	* type definition}, as specified in the appropriate subsection of 3.2
15201 	* Primitive datatypes.
15202 	*/
15203 	if (type->facets != NULL) {
15204 	    xmlSchemaFacetPtr facet;
15205 	    int ok = 1;
15206 
15207 	    primitive = xmlSchemaGetPrimitiveType(type);
15208 	    if (primitive == NULL) {
15209 		PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15210 		    "failed to get primitive type");
15211 		return (-1);
15212 	    }
15213 	    facet = type->facets;
15214 	    do {
15215 		if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
15216 		    ok = 0;
15217 		    xmlSchemaPIllegalFacetAtomicErr(pctxt,
15218 			XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
15219 			type, primitive, facet);
15220 		}
15221 		facet = facet->next;
15222 	    } while (facet != NULL);
15223 	    if (ok == 0)
15224 		return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
15225 	}
15226 	/*
15227 	* SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
15228 	* of the {base type definition} (call this BF),then the DF's {value}
15229 	* must be a valid restriction of BF's {value} as defined in
15230 	* [XML Schemas: Datatypes]."
15231 	*
15232 	* NOTE (1.3.2) Facet derivation constraints are currently handled in
15233 	* xmlSchemaDeriveAndValidateFacets()
15234 	*/
15235     } else if (WXS_IS_LIST(type)) {
15236 	xmlSchemaTypePtr itemType = NULL;
15237 
15238 	itemType = type->subtypes;
15239 	if ((itemType == NULL) || (! WXS_IS_SIMPLE(itemType))) {
15240 	    PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15241 		"failed to evaluate the item type");
15242 	    return (-1);
15243 	}
15244 	if (WXS_IS_TYPE_NOT_FIXED(itemType))
15245 	    xmlSchemaTypeFixup(itemType, ACTXT_CAST pctxt);
15246 	/*
15247 	* 2.1 The {item type definition} must have a {variety} of atomic or
15248 	* union (in which case all the {member type definitions}
15249 	* must be atomic).
15250 	*/
15251 	if ((! WXS_IS_ATOMIC(itemType)) &&
15252 	    (! WXS_IS_UNION(itemType))) {
15253 	    xmlSchemaPCustomErr(pctxt,
15254 		XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15255 		WXS_BASIC_CAST type, NULL,
15256 		"The item type '%s' does not have a variety of atomic or union",
15257 		xmlSchemaGetComponentQName(&str, itemType));
15258 	    FREE_AND_NULL(str)
15259 	    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15260 	} else if (WXS_IS_UNION(itemType)) {
15261 	    xmlSchemaTypeLinkPtr member;
15262 
15263 	    member = itemType->memberTypes;
15264 	    while (member != NULL) {
15265 		if (! WXS_IS_ATOMIC(member->type)) {
15266 		    xmlSchemaPCustomErr(pctxt,
15267 			XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15268 			WXS_BASIC_CAST type, NULL,
15269 			"The item type is a union type, but the "
15270 			"member type '%s' of this item type is not atomic",
15271 			xmlSchemaGetComponentQName(&str, member->type));
15272 		    FREE_AND_NULL(str)
15273 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15274 		}
15275 		member = member->next;
15276 	    }
15277 	}
15278 
15279 	if (WXS_IS_ANY_SIMPLE_TYPE(type->baseType)) {
15280 	    xmlSchemaFacetPtr facet;
15281 	    /*
15282 	    * This is the case if we have: <simpleType><list ..
15283 	    */
15284 	    /*
15285 	    * 2.3.1
15286 	    * 2.3.1.1 The {final} of the {item type definition} must not
15287 	    * contain list.
15288 	    */
15289 	    if (xmlSchemaTypeFinalContains(itemType,
15290 		XML_SCHEMAS_TYPE_FINAL_LIST)) {
15291 		xmlSchemaPCustomErr(pctxt,
15292 		    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
15293 		    WXS_BASIC_CAST type, NULL,
15294 		    "The final of its item type '%s' must not contain 'list'",
15295 		    xmlSchemaGetComponentQName(&str, itemType));
15296 		FREE_AND_NULL(str)
15297 		return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
15298 	    }
15299 	    /*
15300 	    * 2.3.1.2 The {facets} must only contain the whiteSpace
15301 	    * facet component.
15302 	    * OPTIMIZE TODO: the S4S already disallows any facet
15303 	    * to be specified.
15304 	    */
15305 	    if (type->facets != NULL) {
15306 		facet = type->facets;
15307 		do {
15308 		    if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
15309 			xmlSchemaPIllegalFacetListUnionErr(pctxt,
15310 			    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
15311 			    type, facet);
15312 			return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
15313 		    }
15314 		    facet = facet->next;
15315 		} while (facet != NULL);
15316 	    }
15317 	    /*
15318 	    * MAYBE TODO: (Hmm, not really) Datatypes states:
15319 	    * A �list� datatype can be �derived� from an �atomic� datatype
15320 	    * whose �lexical space� allows space (such as string or anyURI)or
15321 	    * a �union� datatype any of whose {member type definitions}'s
15322 	    * �lexical space� allows space.
15323 	    */
15324 	} else {
15325 	    /*
15326 	    * This is the case if we have: <simpleType><restriction ...
15327 	    * I.e. the variety of "list" is inherited.
15328 	    */
15329 	    /*
15330 	    * 2.3.2
15331 	    * 2.3.2.1 The {base type definition} must have a {variety} of list.
15332 	    */
15333 	    if (! WXS_IS_LIST(type->baseType)) {
15334 		xmlSchemaPCustomErr(pctxt,
15335 		    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
15336 		    WXS_BASIC_CAST type, NULL,
15337 		    "The base type '%s' must be a list type",
15338 		    xmlSchemaGetComponentQName(&str, type->baseType));
15339 		FREE_AND_NULL(str)
15340 		return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
15341 	    }
15342 	    /*
15343 	    * 2.3.2.2 The {final} of the {base type definition} must not
15344 	    * contain restriction.
15345 	    */
15346 	    if (xmlSchemaTypeFinalContains(type->baseType,
15347 		XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15348 		xmlSchemaPCustomErr(pctxt,
15349 		    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
15350 		    WXS_BASIC_CAST type, NULL,
15351 		    "The 'final' of the base type '%s' must not contain 'restriction'",
15352 		    xmlSchemaGetComponentQName(&str, type->baseType));
15353 		FREE_AND_NULL(str)
15354 		return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
15355 	    }
15356 	    /*
15357 	    * 2.3.2.3 The {item type definition} must be validly derived
15358 	    * from the {base type definition}'s {item type definition} given
15359 	    * the empty set, as defined in Type Derivation OK (Simple) (�3.14.6).
15360 	    */
15361 	    {
15362 		xmlSchemaTypePtr baseItemType;
15363 
15364 		baseItemType = type->baseType->subtypes;
15365 		if ((baseItemType == NULL) || (! WXS_IS_SIMPLE(baseItemType))) {
15366 		    PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15367 			"failed to eval the item type of a base type");
15368 		    return (-1);
15369 		}
15370 		if ((itemType != baseItemType) &&
15371 		    (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt, itemType,
15372 			baseItemType, 0) != 0)) {
15373 		    xmlChar *strBIT = NULL, *strBT = NULL;
15374 		    xmlSchemaPCustomErrExt(pctxt,
15375 			XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
15376 			WXS_BASIC_CAST type, NULL,
15377 			"The item type '%s' is not validly derived from "
15378 			"the item type '%s' of the base type '%s'",
15379 			xmlSchemaGetComponentQName(&str, itemType),
15380 			xmlSchemaGetComponentQName(&strBIT, baseItemType),
15381 			xmlSchemaGetComponentQName(&strBT, type->baseType));
15382 
15383 		    FREE_AND_NULL(str)
15384 		    FREE_AND_NULL(strBIT)
15385 		    FREE_AND_NULL(strBT)
15386 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
15387 		}
15388 	    }
15389 
15390 	    if (type->facets != NULL) {
15391 		xmlSchemaFacetPtr facet;
15392 		int ok = 1;
15393 		/*
15394 		* 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
15395 		* and enumeration facet components are allowed among the {facets}.
15396 		*/
15397 		facet = type->facets;
15398 		do {
15399 		    switch (facet->type) {
15400 			case XML_SCHEMA_FACET_LENGTH:
15401 			case XML_SCHEMA_FACET_MINLENGTH:
15402 			case XML_SCHEMA_FACET_MAXLENGTH:
15403 			case XML_SCHEMA_FACET_WHITESPACE:
15404 			    /*
15405 			    * TODO: 2.5.1.2 List datatypes
15406 			    * The value of �whiteSpace� is fixed to the value collapse.
15407 			    */
15408 			case XML_SCHEMA_FACET_PATTERN:
15409 			case XML_SCHEMA_FACET_ENUMERATION:
15410 			    break;
15411 			default: {
15412 			    xmlSchemaPIllegalFacetListUnionErr(pctxt,
15413 				XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
15414 				type, facet);
15415 			    /*
15416 			    * We could return, but it's nicer to report all
15417 			    * invalid facets.
15418 			    */
15419 			    ok = 0;
15420 			}
15421 		    }
15422 		    facet = facet->next;
15423 		} while (facet != NULL);
15424 		if (ok == 0)
15425 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
15426 		/*
15427 		* SPEC (2.3.2.5) (same as 1.3.2)
15428 		*
15429 		* NOTE (2.3.2.5) This is currently done in
15430 		* xmlSchemaDeriveAndValidateFacets()
15431 		*/
15432 	    }
15433 	}
15434     } else if (WXS_IS_UNION(type)) {
15435 	/*
15436 	* 3.1 The {member type definitions} must all have {variety} of
15437 	* atomic or list.
15438 	*/
15439 	xmlSchemaTypeLinkPtr member;
15440 
15441 	member = type->memberTypes;
15442 	while (member != NULL) {
15443 	    if (WXS_IS_TYPE_NOT_FIXED(member->type))
15444 		xmlSchemaTypeFixup(member->type, ACTXT_CAST pctxt);
15445 
15446 	    if ((! WXS_IS_ATOMIC(member->type)) &&
15447 		(! WXS_IS_LIST(member->type))) {
15448 		xmlSchemaPCustomErr(pctxt,
15449 		    XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
15450 		    WXS_BASIC_CAST type, NULL,
15451 		    "The member type '%s' is neither an atomic, nor a list type",
15452 		    xmlSchemaGetComponentQName(&str, member->type));
15453 		FREE_AND_NULL(str)
15454 		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
15455 	    }
15456 	    member = member->next;
15457 	}
15458 	/*
15459 	* 3.3.1 If the {base type definition} is the �simple ur-type
15460 	* definition�
15461 	*/
15462 	if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
15463 	    /*
15464 	    * 3.3.1.1 All of the {member type definitions} must have a
15465 	    * {final} which does not contain union.
15466 	    */
15467 	    member = type->memberTypes;
15468 	    while (member != NULL) {
15469 		if (xmlSchemaTypeFinalContains(member->type,
15470 		    XML_SCHEMAS_TYPE_FINAL_UNION)) {
15471 		    xmlSchemaPCustomErr(pctxt,
15472 			XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
15473 			WXS_BASIC_CAST type, NULL,
15474 			"The 'final' of member type '%s' contains 'union'",
15475 			xmlSchemaGetComponentQName(&str, member->type));
15476 		    FREE_AND_NULL(str)
15477 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
15478 		}
15479 		member = member->next;
15480 	    }
15481 	    /*
15482 	    * 3.3.1.2 The {facets} must be empty.
15483 	    */
15484 	    if (type->facetSet != NULL) {
15485 		xmlSchemaPCustomErr(pctxt,
15486 		    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
15487 		    WXS_BASIC_CAST type, NULL,
15488 		    "No facets allowed", NULL);
15489 		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
15490 	    }
15491 	} else {
15492 	    /*
15493 	    * 3.3.2.1 The {base type definition} must have a {variety} of union.
15494 	    * I.e. the variety of "list" is inherited.
15495 	    */
15496 	    if (! WXS_IS_UNION(type->baseType)) {
15497 		xmlSchemaPCustomErr(pctxt,
15498 		    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
15499 		    WXS_BASIC_CAST type, NULL,
15500 		    "The base type '%s' is not a union type",
15501 		    xmlSchemaGetComponentQName(&str, type->baseType));
15502 		FREE_AND_NULL(str)
15503 		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
15504 	    }
15505 	    /*
15506 	    * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
15507 	    */
15508 	    if (xmlSchemaTypeFinalContains(type->baseType,
15509 		XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15510 		xmlSchemaPCustomErr(pctxt,
15511 		    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
15512 		    WXS_BASIC_CAST type, NULL,
15513 		    "The 'final' of its base type '%s' must not contain 'restriction'",
15514 		    xmlSchemaGetComponentQName(&str, type->baseType));
15515 		FREE_AND_NULL(str)
15516 		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
15517 	    }
15518 	    /*
15519 	    * 3.3.2.3 The {member type definitions}, in order, must be validly
15520 	    * derived from the corresponding type definitions in the {base
15521 	    * type definition}'s {member type definitions} given the empty set,
15522 	    * as defined in Type Derivation OK (Simple) (�3.14.6).
15523 	    */
15524 	    {
15525 		xmlSchemaTypeLinkPtr baseMember;
15526 
15527 		/*
15528 		* OPTIMIZE: if the type is restricting, it has no local defined
15529 		* member types and inherits the member types of the base type;
15530 		* thus a check for equality can be skipped.
15531 		*/
15532 		/*
15533 		* Even worse: I cannot see a scenario where a restricting
15534 		* union simple type can have other member types as the member
15535 		* types of it's base type. This check seems not necessary with
15536 		* respect to the derivation process in libxml2.
15537 		* But necessary if constructing types with an API.
15538 		*/
15539 		if (type->memberTypes != NULL) {
15540 		    member = type->memberTypes;
15541 		    baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
15542 		    if ((member == NULL) && (baseMember != NULL)) {
15543 			PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15544 			    "different number of member types in base");
15545 		    }
15546 		    while (member != NULL) {
15547 			if (baseMember == NULL) {
15548 			    PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15549 			    "different number of member types in base");
15550 			} else if ((member->type != baseMember->type) &&
15551 			    (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
15552 				member->type, baseMember->type, 0) != 0)) {
15553 			    xmlChar *strBMT = NULL, *strBT = NULL;
15554 
15555 			    xmlSchemaPCustomErrExt(pctxt,
15556 				XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
15557 				WXS_BASIC_CAST type, NULL,
15558 				"The member type %s is not validly "
15559 				"derived from its corresponding member "
15560 				"type %s of the base type %s",
15561 				xmlSchemaGetComponentQName(&str, member->type),
15562 				xmlSchemaGetComponentQName(&strBMT, baseMember->type),
15563 				xmlSchemaGetComponentQName(&strBT, type->baseType));
15564 			    FREE_AND_NULL(str)
15565 			    FREE_AND_NULL(strBMT)
15566 			    FREE_AND_NULL(strBT)
15567 			    return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
15568 			}
15569 			member = member->next;
15570 			baseMember = baseMember->next;
15571 		    }
15572 		}
15573 	    }
15574 	    /*
15575 	    * 3.3.2.4 Only pattern and enumeration facet components are
15576 	    * allowed among the {facets}.
15577 	    */
15578 	    if (type->facets != NULL) {
15579 		xmlSchemaFacetPtr facet;
15580 		int ok = 1;
15581 
15582 		facet = type->facets;
15583 		do {
15584 		    if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
15585 			(facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
15586 			xmlSchemaPIllegalFacetListUnionErr(pctxt,
15587 				XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
15588 				type, facet);
15589 			ok = 0;
15590 		    }
15591 		    facet = facet->next;
15592 		} while (facet != NULL);
15593 		if (ok == 0)
15594 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
15595 
15596 	    }
15597 	    /*
15598 	    * SPEC (3.3.2.5) (same as 1.3.2)
15599 	    *
15600 	    * NOTE (3.3.2.5) This is currently done in
15601 	    * xmlSchemaDeriveAndValidateFacets()
15602 	    */
15603 	}
15604     }
15605 
15606     return (0);
15607 }
15608 
15609 /**
15610  * xmlSchemaCheckSRCSimpleType:
15611  * @ctxt:  the schema parser context
15612  * @type:  the simple type definition
15613  *
15614  * Checks crc-simple-type constraints.
15615  *
15616  * Returns 0 if the constraints are satisfied,
15617  * if not a positive error code and -1 on internal
15618  * errors.
15619  */
15620 #if 0
15621 static int
15622 xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
15623 			    xmlSchemaTypePtr type)
15624 {
15625     /*
15626     * src-simple-type.1 The corresponding simple type definition, if any,
15627     * must satisfy the conditions set out in Constraints on Simple Type
15628     * Definition Schema Components (�3.14.6).
15629     */
15630     if (WXS_IS_RESTRICTION(type)) {
15631 	/*
15632 	* src-simple-type.2 "If the <restriction> alternative is chosen,
15633 	* either it must have a base [attribute] or a <simpleType> among its
15634 	* [children], but not both."
15635 	* NOTE: This is checked in the parse function of <restriction>.
15636 	*/
15637 	/*
15638 	*
15639 	*/
15640     } else if (WXS_IS_LIST(type)) {
15641 	/* src-simple-type.3 "If the <list> alternative is chosen, either it must have
15642 	* an itemType [attribute] or a <simpleType> among its [children],
15643 	* but not both."
15644 	*
15645 	* NOTE: This is checked in the parse function of <list>.
15646 	*/
15647     } else if (WXS_IS_UNION(type)) {
15648 	/*
15649 	* src-simple-type.4 is checked in xmlSchemaCheckUnionTypeDefCircular().
15650 	*/
15651     }
15652     return (0);
15653 }
15654 #endif
15655 
15656 static int
xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)15657 xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
15658 {
15659    if (ctxt->vctxt == NULL) {
15660 	ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
15661 	if (ctxt->vctxt == NULL) {
15662 	    xmlSchemaPErr(ctxt, NULL,
15663 		XML_SCHEMAP_INTERNAL,
15664 		"Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
15665 		"failed to create a temp. validation context.\n",
15666 		NULL, NULL);
15667 	    return (-1);
15668 	}
15669 	/* TODO: Pass user data. */
15670 	xmlSchemaSetValidErrors(ctxt->vctxt,
15671 	    ctxt->error, ctxt->warning, ctxt->errCtxt);
15672 	xmlSchemaSetValidStructuredErrors(ctxt->vctxt,
15673 	    ctxt->serror, ctxt->errCtxt);
15674     }
15675     return (0);
15676 }
15677 
15678 static int
15679 xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
15680 			     xmlNodePtr node,
15681 			     xmlSchemaTypePtr type,
15682 			     const xmlChar *value,
15683 			     xmlSchemaValPtr *retVal,
15684 			     int fireErrors,
15685 			     int normalize,
15686 			     int isNormalized);
15687 
15688 /**
15689  * xmlSchemaParseCheckCOSValidDefault:
15690  * @pctxt:  the schema parser context
15691  * @type:  the simple type definition
15692  * @value: the default value
15693  * @node: an optional node (the holder of the value)
15694  *
15695  * Schema Component Constraint: Element Default Valid (Immediate)
15696  * (cos-valid-default)
15697  * This will be used by the parser only. For the validator there's
15698  * an other version.
15699  *
15700  * Returns 0 if the constraints are satisfied,
15701  * if not, a positive error code and -1 on internal
15702  * errors.
15703  */
15704 static int
xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,xmlNodePtr node,xmlSchemaTypePtr type,const xmlChar * value,xmlSchemaValPtr * val)15705 xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
15706 				   xmlNodePtr node,
15707 				   xmlSchemaTypePtr type,
15708 				   const xmlChar *value,
15709 				   xmlSchemaValPtr *val)
15710 {
15711     int ret = 0;
15712 
15713     /*
15714     * cos-valid-default:
15715     * Schema Component Constraint: Element Default Valid (Immediate)
15716     * For a string to be a valid default with respect to a type
15717     * definition the appropriate case among the following must be true:
15718     */
15719     if WXS_IS_COMPLEX(type) {
15720 	/*
15721 	* Complex type.
15722 	*
15723 	* SPEC (2.1) "its {content type} must be a simple type definition
15724 	* or mixed."
15725 	* SPEC (2.2.2) "If the {content type} is mixed, then the {content
15726 	* type}'s particle must be �emptiable� as defined by
15727 	* Particle Emptiable (�3.9.6)."
15728 	*/
15729 	if ((! WXS_HAS_SIMPLE_CONTENT(type)) &&
15730 	    ((! WXS_HAS_MIXED_CONTENT(type)) || (! WXS_EMPTIABLE(type)))) {
15731 	    /* NOTE that this covers (2.2.2) as well. */
15732 	    xmlSchemaPCustomErr(pctxt,
15733 		XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
15734 		WXS_BASIC_CAST type, type->node,
15735 		"For a string to be a valid default, the type definition "
15736 		"must be a simple type or a complex type with mixed content "
15737 		"and a particle emptiable", NULL);
15738 	    return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
15739 	}
15740     }
15741     /*
15742     * 1 If the type definition is a simple type definition, then the string
15743     * must be �valid� with respect to that definition as defined by String
15744     * Valid (�3.14.4).
15745     *
15746     * AND
15747     *
15748     * 2.2.1 If the {content type} is a simple type definition, then the
15749     * string must be �valid� with respect to that simple type definition
15750     * as defined by String Valid (�3.14.4).
15751     */
15752     if (WXS_IS_SIMPLE(type))
15753 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15754 	    type, value, val, 1, 1, 0);
15755     else if (WXS_HAS_SIMPLE_CONTENT(type))
15756 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15757 	    type->contentTypeDef, value, val, 1, 1, 0);
15758     else
15759 	return (ret);
15760 
15761     if (ret < 0) {
15762 	PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
15763 	    "calling xmlSchemaVCheckCVCSimpleType()");
15764     }
15765 
15766     return (ret);
15767 }
15768 
15769 /**
15770  * xmlSchemaCheckCTPropsCorrect:
15771  * @ctxt:  the schema parser context
15772  * @type:  the complex type definition
15773  *
15774  *.(4.6) Constraints on Complex Type Definition Schema Components
15775  * Schema Component Constraint:
15776  * Complex Type Definition Properties Correct (ct-props-correct)
15777  * STATUS: (seems) complete
15778  *
15779  * Returns 0 if the constraints are satisfied, a positive
15780  * error code if not and -1 if an internal error occured.
15781  */
15782 static int
xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)15783 xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
15784 			     xmlSchemaTypePtr type)
15785 {
15786     /*
15787     * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
15788     *
15789     * SPEC (1) "The values of the properties of a complex type definition must
15790     * be as described in the property tableau in The Complex Type Definition
15791     * Schema Component (�3.4.1), modulo the impact of Missing
15792     * Sub-components (�5.3)."
15793     */
15794     if ((type->baseType != NULL) &&
15795 	(WXS_IS_SIMPLE(type->baseType)) &&
15796 	(WXS_IS_EXTENSION(type) == 0)) {
15797 	/*
15798 	* SPEC (2) "If the {base type definition} is a simple type definition,
15799 	* the {derivation method} must be extension."
15800 	*/
15801 	xmlSchemaCustomErr(ACTXT_CAST pctxt,
15802 	    XML_SCHEMAP_SRC_CT_1,
15803 	    NULL, WXS_BASIC_CAST type,
15804 	    "If the base type is a simple type, the derivation method must be "
15805 	    "'extension'", NULL, NULL);
15806 	return (XML_SCHEMAP_SRC_CT_1);
15807     }
15808     /*
15809     * SPEC (3) "Circular definitions are disallowed, except for the �ur-type
15810     * definition�. That is, it must be possible to reach the �ur-type
15811     * definition by repeatedly following the {base type definition}."
15812     *
15813     * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
15814     */
15815     /*
15816     * NOTE that (4) and (5) need the following:
15817     *   - attribute uses need to be already inherited (apply attr. prohibitions)
15818     *   - attribute group references need to be expanded already
15819     *   - simple types need to be typefixed already
15820     */
15821     if (type->attrUses &&
15822 	(((xmlSchemaItemListPtr) type->attrUses)->nbItems > 1))
15823     {
15824 	xmlSchemaItemListPtr uses = (xmlSchemaItemListPtr) type->attrUses;
15825 	xmlSchemaAttributeUsePtr use, tmp;
15826 	int i, j, hasId = 0;
15827 
15828 	for (i = uses->nbItems -1; i >= 0; i--) {
15829 	    use = uses->items[i];
15830 
15831 	    /*
15832 	    * SPEC ct-props-correct
15833 	    * (4) "Two distinct attribute declarations in the
15834 	    * {attribute uses} must not have identical {name}s and
15835 	    * {target namespace}s."
15836 	    */
15837 	    if (i > 0) {
15838 		for (j = i -1; j >= 0; j--) {
15839 		    tmp = uses->items[j];
15840 		    if ((WXS_ATTRUSE_DECL_NAME(use) ==
15841 			WXS_ATTRUSE_DECL_NAME(tmp)) &&
15842 			(WXS_ATTRUSE_DECL_TNS(use) ==
15843 			WXS_ATTRUSE_DECL_TNS(tmp)))
15844 		    {
15845 			xmlChar *str = NULL;
15846 
15847 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
15848 			    XML_SCHEMAP_AG_PROPS_CORRECT,
15849 			    NULL, WXS_BASIC_CAST type,
15850 			    "Duplicate %s",
15851 			    xmlSchemaGetComponentDesignation(&str, use),
15852 			    NULL);
15853 			FREE_AND_NULL(str);
15854 			/*
15855 			* Remove the duplicate.
15856 			*/
15857 			if (xmlSchemaItemListRemove(uses, i) == -1)
15858 			    goto exit_failure;
15859 			goto next_use;
15860 		    }
15861 		}
15862 	    }
15863 	    /*
15864 	    * SPEC ct-props-correct
15865 	    * (5) "Two distinct attribute declarations in the
15866 	    * {attribute uses} must not have {type definition}s which
15867 	    * are or are derived from ID."
15868 	    */
15869 	    if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
15870 		if (xmlSchemaIsDerivedFromBuiltInType(
15871 		    WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
15872 		{
15873 		    if (hasId) {
15874 			xmlChar *str = NULL;
15875 
15876 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
15877 			    XML_SCHEMAP_AG_PROPS_CORRECT,
15878 			    NULL, WXS_BASIC_CAST type,
15879 			    "There must not exist more than one attribute "
15880 			    "declaration of type 'xs:ID' "
15881 			    "(or derived from 'xs:ID'). The %s violates this "
15882 			    "constraint",
15883 			    xmlSchemaGetComponentDesignation(&str, use),
15884 			    NULL);
15885 			FREE_AND_NULL(str);
15886 			if (xmlSchemaItemListRemove(uses, i) == -1)
15887 			    goto exit_failure;
15888 		    }
15889 
15890 		    hasId = 1;
15891 		}
15892 	    }
15893 next_use: {}
15894 	}
15895     }
15896     return (0);
15897 exit_failure:
15898     return(-1);
15899 }
15900 
15901 static int
xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,xmlSchemaTypePtr typeB)15902 xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
15903 		       xmlSchemaTypePtr typeB)
15904 {
15905     /*
15906     * TODO: This should implement component-identity
15907     * in the future.
15908     */
15909     if ((typeA == NULL) || (typeB == NULL))
15910 	return (0);
15911     return (typeA == typeB);
15912 }
15913 
15914 /**
15915  * xmlSchemaCheckCOSCTDerivedOK:
15916  * @ctxt:  the schema parser context
15917  * @type:  the to-be derived complex type definition
15918  * @baseType:  the base complex type definition
15919  * @set: the given set
15920  *
15921  * Schema Component Constraint:
15922  * Type Derivation OK (Complex) (cos-ct-derived-ok)
15923  *
15924  * STATUS: completed
15925  *
15926  * Returns 0 if the constraints are satisfied, or 1
15927  * if not.
15928  */
15929 static int
xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,xmlSchemaTypePtr type,xmlSchemaTypePtr baseType,int set)15930 xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
15931 			     xmlSchemaTypePtr type,
15932 			     xmlSchemaTypePtr baseType,
15933 			     int set)
15934 {
15935     int equal = xmlSchemaAreEqualTypes(type, baseType);
15936     /* TODO: Error codes. */
15937     /*
15938     * SPEC "For a complex type definition (call it D, for derived)
15939     * to be validly derived from a type definition (call this
15940     * B, for base) given a subset of {extension, restriction}
15941     * all of the following must be true:"
15942     */
15943     if (! equal) {
15944 	/*
15945 	* SPEC (1) "If B and D are not the same type definition, then the
15946 	* {derivation method} of D must not be in the subset."
15947 	*/
15948 	if (((set & SUBSET_EXTENSION) && (WXS_IS_EXTENSION(type))) ||
15949 	    ((set & SUBSET_RESTRICTION) && (WXS_IS_RESTRICTION(type))))
15950 	    return (1);
15951     } else {
15952 	/*
15953 	* SPEC (2.1) "B and D must be the same type definition."
15954 	*/
15955 	return (0);
15956     }
15957     /*
15958     * SPEC (2.2) "B must be D's {base type definition}."
15959     */
15960     if (type->baseType == baseType)
15961 	return (0);
15962     /*
15963     * SPEC (2.3.1) "D's {base type definition} must not be the �ur-type
15964     * definition�."
15965     */
15966     if (WXS_IS_ANYTYPE(type->baseType))
15967 	return (1);
15968 
15969     if (WXS_IS_COMPLEX(type->baseType)) {
15970 	/*
15971 	* SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
15972 	* must be validly derived from B given the subset as defined by this
15973 	* constraint."
15974 	*/
15975 	return (xmlSchemaCheckCOSCTDerivedOK(actxt, type->baseType,
15976 	    baseType, set));
15977     } else {
15978 	/*
15979 	* SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
15980 	* must be validly derived from B given the subset as defined in Type
15981 	* Derivation OK (Simple) (�3.14.6).
15982 	*/
15983 	return (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
15984 	    baseType, set));
15985     }
15986 }
15987 
15988 /**
15989  * xmlSchemaCheckCOSDerivedOK:
15990  * @type:  the derived simple type definition
15991  * @baseType:  the base type definition
15992  *
15993  * Calls:
15994  * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
15995  *
15996  * Checks wheter @type can be validly derived from @baseType.
15997  *
15998  * Returns 0 on success, an positive error code otherwise.
15999  */
16000 static int
xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt,xmlSchemaTypePtr type,xmlSchemaTypePtr baseType,int set)16001 xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16002 			   xmlSchemaTypePtr type,
16003 			   xmlSchemaTypePtr baseType,
16004 			   int set)
16005 {
16006     if (WXS_IS_SIMPLE(type))
16007 	return (xmlSchemaCheckCOSSTDerivedOK(actxt, type, baseType, set));
16008     else
16009 	return (xmlSchemaCheckCOSCTDerivedOK(actxt, type, baseType, set));
16010 }
16011 
16012 /**
16013  * xmlSchemaCheckCOSCTExtends:
16014  * @ctxt:  the schema parser context
16015  * @type:  the complex type definition
16016  *
16017  * (3.4.6) Constraints on Complex Type Definition Schema Components
16018  * Schema Component Constraint:
16019  * Derivation Valid (Extension) (cos-ct-extends)
16020  *
16021  * STATUS:
16022  *   missing:
16023  *     (1.5)
16024  *     (1.4.3.2.2.2) "Particle Valid (Extension)"
16025  *
16026  * Returns 0 if the constraints are satisfied, a positive
16027  * error code if not and -1 if an internal error occured.
16028  */
16029 static int
xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)16030 xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
16031 			   xmlSchemaTypePtr type)
16032 {
16033     xmlSchemaTypePtr base = type->baseType;
16034     /*
16035     * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
16036     * temporarily only.
16037     */
16038     /*
16039     * SPEC (1) "If the {base type definition} is a complex type definition,
16040     * then all of the following must be true:"
16041     */
16042     if (WXS_IS_COMPLEX(base)) {
16043 	/*
16044 	* SPEC (1.1) "The {final} of the {base type definition} must not
16045 	* contain extension."
16046 	*/
16047 	if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16048 	    xmlSchemaPCustomErr(ctxt,
16049 		XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16050 		WXS_BASIC_CAST type, NULL,
16051 		"The 'final' of the base type definition "
16052 		"contains 'extension'", NULL);
16053 	    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16054 	}
16055 
16056 	/*
16057 	* ATTENTION: The constrains (1.2) and (1.3) are not applied,
16058 	* since they are automatically satisfied through the
16059 	* inheriting mechanism.
16060 	* Note that even if redefining components, the inheriting mechanism
16061 	* is used.
16062 	*/
16063 #if 0
16064 	/*
16065 	* SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
16066 	* uses}
16067 	* of the complex type definition itself, that is, for every attribute
16068 	* use in the {attribute uses} of the {base type definition}, there
16069 	* must be an attribute use in the {attribute uses} of the complex
16070 	* type definition itself whose {attribute declaration} has the same
16071 	* {name}, {target namespace} and {type definition} as its attribute
16072 	* declaration"
16073 	*/
16074 	if (base->attrUses != NULL) {
16075 	    int i, j, found;
16076 	    xmlSchemaAttributeUsePtr use, buse;
16077 
16078 	    for (i = 0; i < (WXS_LIST_CAST base->attrUses)->nbItems; i ++) {
16079 		buse = (WXS_LIST_CAST base->attrUses)->items[i];
16080 		found = 0;
16081 		if (type->attrUses != NULL) {
16082 		    use = (WXS_LIST_CAST type->attrUses)->items[j];
16083 		    for (j = 0; j < (WXS_LIST_CAST type->attrUses)->nbItems; j ++)
16084 		    {
16085 			if ((WXS_ATTRUSE_DECL_NAME(use) ==
16086 				WXS_ATTRUSE_DECL_NAME(buse)) &&
16087 			    (WXS_ATTRUSE_DECL_TNS(use) ==
16088 				WXS_ATTRUSE_DECL_TNS(buse)) &&
16089 			    (WXS_ATTRUSE_TYPEDEF(use) ==
16090 				WXS_ATTRUSE_TYPEDEF(buse))
16091 			{
16092 			    found = 1;
16093 			    break;
16094 			}
16095 		    }
16096 		}
16097 		if (! found) {
16098 		    xmlChar *str = NULL;
16099 
16100 		    xmlSchemaCustomErr(ACTXT_CAST ctxt,
16101 			XML_SCHEMAP_COS_CT_EXTENDS_1_2,
16102 			NULL, WXS_BASIC_CAST type,
16103 			/*
16104 			* TODO: The report does not indicate that also the
16105 			* type needs to be the same.
16106 			*/
16107 			"This type is missing a matching correspondent "
16108 			"for its {base type}'s %s in its {attribute uses}",
16109 			xmlSchemaGetComponentDesignation(&str,
16110 			    buse->children),
16111 			NULL);
16112 		    FREE_AND_NULL(str)
16113 		}
16114 	    }
16115 	}
16116 	/*
16117 	* SPEC (1.3) "If it has an {attribute wildcard}, the complex type
16118 	* definition must also have one, and the base type definition's
16119 	* {attribute  wildcard}'s {namespace constraint} must be a subset
16120 	* of the complex  type definition's {attribute wildcard}'s {namespace
16121 	* constraint}, as defined by Wildcard Subset (�3.10.6)."
16122 	*/
16123 
16124 	/*
16125 	* MAYBE TODO: Enable if ever needed. But this will be needed only
16126 	* if created the type via a schema construction API.
16127 	*/
16128 	if (base->attributeWildcard != NULL) {
16129 	    if (type->attributeWilcard == NULL) {
16130 		xmlChar *str = NULL;
16131 
16132 		xmlSchemaCustomErr(ACTXT_CAST pctxt,
16133 		    XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16134 		    NULL, type,
16135 		    "The base %s has an attribute wildcard, "
16136 		    "but this type is missing an attribute wildcard",
16137 		    xmlSchemaGetComponentDesignation(&str, base));
16138 		FREE_AND_NULL(str)
16139 
16140 	    } else if (xmlSchemaCheckCOSNSSubset(
16141 		base->attributeWildcard, type->attributeWildcard))
16142 	    {
16143 		xmlChar *str = NULL;
16144 
16145 		xmlSchemaCustomErr(ACTXT_CAST pctxt,
16146 		    XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16147 		    NULL, type,
16148 		    "The attribute wildcard is not a valid "
16149 		    "superset of the one in the base %s",
16150 		    xmlSchemaGetComponentDesignation(&str, base));
16151 		FREE_AND_NULL(str)
16152 	    }
16153 	}
16154 #endif
16155 	/*
16156 	* SPEC (1.4) "One of the following must be true:"
16157 	*/
16158 	if ((type->contentTypeDef != NULL) &&
16159 	    (type->contentTypeDef == base->contentTypeDef)) {
16160 	    /*
16161 	    * SPEC (1.4.1) "The {content type} of the {base type definition}
16162 	    * and the {content type} of the complex type definition itself
16163 	    * must be the same simple type definition"
16164 	    * PASS
16165 	    */
16166 	} else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
16167 	    (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
16168 	    /*
16169 	    * SPEC (1.4.2) "The {content type} of both the {base type
16170 	    * definition} and the complex type definition itself must
16171 	    * be empty."
16172 	    * PASS
16173 	    */
16174 	} else {
16175 	    /*
16176 	    * SPEC (1.4.3) "All of the following must be true:"
16177 	    */
16178 	    if (type->subtypes == NULL) {
16179 		/*
16180 		* SPEC 1.4.3.1 The {content type} of the complex type
16181 		* definition itself must specify a particle.
16182 		*/
16183 		xmlSchemaPCustomErr(ctxt,
16184 		    XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16185 		    WXS_BASIC_CAST type, NULL,
16186 		    "The content type must specify a particle", NULL);
16187 		return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16188 	    }
16189 	    /*
16190 	    * SPEC (1.4.3.2) "One of the following must be true:"
16191 	    */
16192 	    if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16193 		/*
16194 		* SPEC (1.4.3.2.1) "The {content type} of the {base type
16195 		* definition} must be empty.
16196 		* PASS
16197 		*/
16198 	    } else {
16199 		/*
16200 		* SPEC (1.4.3.2.2) "All of the following must be true:"
16201 		*/
16202 		if ((type->contentType != base->contentType) ||
16203 		    ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
16204 		    (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
16205 		    /*
16206 		    * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
16207 		    * or both must be element-only."
16208 		    */
16209 		    xmlSchemaPCustomErr(ctxt,
16210 			XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16211 			WXS_BASIC_CAST type, NULL,
16212 			"The content type of both, the type and its base "
16213 			"type, must either 'mixed' or 'element-only'", NULL);
16214 		    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16215 		}
16216 		/*
16217 		* URGENT TODO SPEC (1.4.3.2.2.2) "The particle of the
16218 		* complex type definition must be a �valid extension�
16219 		* of the {base type definition}'s particle, as defined
16220 		* in Particle Valid (Extension) (�3.9.6)."
16221 		*
16222 		* NOTE that we won't check "Particle Valid (Extension)",
16223 		* since it is ensured by the derivation process in
16224 		* xmlSchemaTypeFixup(). We need to implement this when heading
16225 		* for a construction API
16226 		* TODO: !! This is needed to be checked if redefining a type !!
16227 		*/
16228 	    }
16229 	    /*
16230 	    * URGENT TODO (1.5)
16231 	    */
16232 	}
16233     } else {
16234 	/*
16235 	* SPEC (2) "If the {base type definition} is a simple type definition,
16236 	* then all of the following must be true:"
16237 	*/
16238 	if (type->contentTypeDef != base) {
16239 	    /*
16240 	    * SPEC (2.1) "The {content type} must be the same simple type
16241 	    * definition."
16242 	    */
16243 	    xmlSchemaPCustomErr(ctxt,
16244 		XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16245 		WXS_BASIC_CAST type, NULL,
16246 		"The content type must be the simple base type", NULL);
16247 	    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16248 	}
16249 	if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16250 	    /*
16251 	    * SPEC (2.2) "The {final} of the {base type definition} must not
16252 	    * contain extension"
16253 	    * NOTE that this is the same as (1.1).
16254 	    */
16255 	    xmlSchemaPCustomErr(ctxt,
16256 		XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16257 		WXS_BASIC_CAST type, NULL,
16258 		"The 'final' of the base type definition "
16259 		"contains 'extension'", NULL);
16260 	    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16261 	}
16262     }
16263     return (0);
16264 }
16265 
16266 /**
16267  * xmlSchemaCheckDerivationOKRestriction:
16268  * @ctxt:  the schema parser context
16269  * @type:  the complex type definition
16270  *
16271  * (3.4.6) Constraints on Complex Type Definition Schema Components
16272  * Schema Component Constraint:
16273  * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
16274  *
16275  * STATUS:
16276  *   missing:
16277  *     (5.4.2) ???
16278  *
16279  * ATTENTION:
16280  * In XML Schema 1.1 this will be:
16281  * Validation Rule: Checking complex type subsumption
16282  *
16283  * Returns 0 if the constraints are satisfied, a positive
16284  * error code if not and -1 if an internal error occured.
16285  */
16286 static int
xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)16287 xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
16288 				      xmlSchemaTypePtr type)
16289 {
16290     xmlSchemaTypePtr base;
16291 
16292     /*
16293     * TODO: Correct the error code; XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1 is used
16294     * temporarily only.
16295     */
16296     base = type->baseType;
16297     if (! WXS_IS_COMPLEX(base)) {
16298 	xmlSchemaCustomErr(ACTXT_CAST ctxt,
16299 	    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16300 	    type->node, WXS_BASIC_CAST type,
16301 	    "The base type must be a complex type", NULL, NULL);
16302 	return(ctxt->err);
16303     }
16304     if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
16305 	/*
16306 	* SPEC (1) "The {base type definition} must be a complex type
16307 	* definition whose {final} does not contain restriction."
16308 	*/
16309 	xmlSchemaCustomErr(ACTXT_CAST ctxt,
16310 	    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16311 	    type->node, WXS_BASIC_CAST type,
16312 	    "The 'final' of the base type definition "
16313 	    "contains 'restriction'", NULL, NULL);
16314 	return (ctxt->err);
16315     }
16316     /*
16317     * SPEC (2), (3) and (4)
16318     * Those are handled in a separate function, since the
16319     * same constraints are needed for redefinition of
16320     * attribute groups as well.
16321     */
16322     if (xmlSchemaCheckDerivationOKRestriction2to4(ctxt,
16323 	XML_SCHEMA_ACTION_DERIVE,
16324 	WXS_BASIC_CAST type, WXS_BASIC_CAST base,
16325 	type->attrUses, base->attrUses,
16326 	type->attributeWildcard,
16327 	base->attributeWildcard) == -1)
16328     {
16329 	return(-1);
16330     }
16331     /*
16332     * SPEC (5) "One of the following must be true:"
16333     */
16334     if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
16335 	/*
16336 	* SPEC (5.1) "The {base type definition} must be the
16337 	* �ur-type definition�."
16338 	* PASS
16339 	*/
16340     } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16341 	    (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16342 	/*
16343 	* SPEC (5.2.1) "The {content type} of the complex type definition
16344 	* must be a simple type definition"
16345 	*
16346 	* SPEC (5.2.2) "One of the following must be true:"
16347 	*/
16348 	if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16349 	    (base->contentType == XML_SCHEMA_CONTENT_BASIC))
16350 	{
16351 	    int err;
16352 	    /*
16353 	    * SPEC (5.2.2.1) "The {content type} of the {base type
16354 	    * definition} must be a simple type definition from which
16355 	    * the {content type} is validly derived given the empty
16356 	    * set as defined in Type Derivation OK (Simple) (�3.14.6)."
16357 	    *
16358 	    * ATTENTION TODO: This seems not needed if the type implicitely
16359 	    * derived from the base type.
16360 	    *
16361 	    */
16362 	    err = xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST ctxt,
16363 		type->contentTypeDef, base->contentTypeDef, 0);
16364 	    if (err != 0) {
16365 		xmlChar *strA = NULL, *strB = NULL;
16366 
16367 		if (err == -1)
16368 		    return(-1);
16369 		xmlSchemaCustomErr(ACTXT_CAST ctxt,
16370 		    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16371 		    NULL, WXS_BASIC_CAST type,
16372 		    "The {content type} %s is not validly derived from the "
16373 		    "base type's {content type} %s",
16374 		    xmlSchemaGetComponentDesignation(&strA,
16375 			type->contentTypeDef),
16376 		    xmlSchemaGetComponentDesignation(&strB,
16377 			base->contentTypeDef));
16378 		FREE_AND_NULL(strA);
16379 		FREE_AND_NULL(strB);
16380 		return(ctxt->err);
16381 	    }
16382 	} else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16383 	    (xmlSchemaIsParticleEmptiable(
16384 		(xmlSchemaParticlePtr) base->subtypes))) {
16385 	    /*
16386 	    * SPEC (5.2.2.2) "The {base type definition} must be mixed
16387 	    * and have a particle which is �emptiable� as defined in
16388 	    * Particle Emptiable (�3.9.6)."
16389 	    * PASS
16390 	    */
16391 	} else {
16392 	    xmlSchemaPCustomErr(ctxt,
16393 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16394 		WXS_BASIC_CAST type, NULL,
16395 		"The content type of the base type must be either "
16396 		"a simple type or 'mixed' and an emptiable particle", NULL);
16397 	    return (ctxt->err);
16398 	}
16399     } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16400 	/*
16401 	* SPEC (5.3.1) "The {content type} of the complex type itself must
16402 	* be empty"
16403 	*/
16404 	if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16405 	    /*
16406 	    * SPEC (5.3.2.1) "The {content type} of the {base type
16407 	    * definition} must also be empty."
16408 	    * PASS
16409 	    */
16410 	} else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16411 	    (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
16412 	    xmlSchemaIsParticleEmptiable(
16413 		(xmlSchemaParticlePtr) base->subtypes)) {
16414 	    /*
16415 	    * SPEC (5.3.2.2) "The {content type} of the {base type
16416 	    * definition} must be elementOnly or mixed and have a particle
16417 	    * which is �emptiable� as defined in Particle Emptiable (�3.9.6)."
16418 	    * PASS
16419 	    */
16420 	} else {
16421 	    xmlSchemaPCustomErr(ctxt,
16422 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16423 		WXS_BASIC_CAST type, NULL,
16424 		"The content type of the base type must be either "
16425 		"empty or 'mixed' (or 'elements-only') and an emptiable "
16426 		"particle", NULL);
16427 	    return (ctxt->err);
16428 	}
16429     } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16430 	WXS_HAS_MIXED_CONTENT(type)) {
16431 	/*
16432 	* SPEC (5.4.1.1) "The {content type} of the complex type definition
16433 	* itself must be element-only"
16434 	*/
16435 	if (WXS_HAS_MIXED_CONTENT(type) && (! WXS_HAS_MIXED_CONTENT(base))) {
16436 	    /*
16437 	    * SPEC (5.4.1.2) "The {content type} of the complex type
16438 	    * definition itself and of the {base type definition} must be
16439 	    * mixed"
16440 	    */
16441 	    xmlSchemaPCustomErr(ctxt,
16442 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16443 		WXS_BASIC_CAST type, NULL,
16444 		"If the content type is 'mixed', then the content type of the "
16445 		"base type must also be 'mixed'", NULL);
16446 	    return (ctxt->err);
16447 	}
16448 	/*
16449 	* SPEC (5.4.2) "The particle of the complex type definition itself
16450 	* must be a �valid restriction� of the particle of the {content
16451 	* type} of the {base type definition} as defined in Particle Valid
16452 	* (Restriction) (�3.9.6).
16453 	*
16454 	* URGENT TODO: (5.4.2)
16455 	*/
16456     } else {
16457 	xmlSchemaPCustomErr(ctxt,
16458 	    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16459 	    WXS_BASIC_CAST type, NULL,
16460 	    "The type is not a valid restriction of its base type", NULL);
16461 	return (ctxt->err);
16462     }
16463     return (0);
16464 }
16465 
16466 /**
16467  * xmlSchemaCheckCTComponent:
16468  * @ctxt:  the schema parser context
16469  * @type:  the complex type definition
16470  *
16471  * (3.4.6) Constraints on Complex Type Definition Schema Components
16472  *
16473  * Returns 0 if the constraints are satisfied, a positive
16474  * error code if not and -1 if an internal error occured.
16475  */
16476 static int
xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)16477 xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
16478 			  xmlSchemaTypePtr type)
16479 {
16480     int ret;
16481     /*
16482     * Complex Type Definition Properties Correct
16483     */
16484     ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
16485     if (ret != 0)
16486 	return (ret);
16487     if (WXS_IS_EXTENSION(type))
16488 	ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
16489     else
16490 	ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
16491     return (ret);
16492 }
16493 
16494 /**
16495  * xmlSchemaCheckSRCCT:
16496  * @ctxt:  the schema parser context
16497  * @type:  the complex type definition
16498  *
16499  * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
16500  * Schema Representation Constraint:
16501  * Complex Type Definition Representation OK (src-ct)
16502  *
16503  * Returns 0 if the constraints are satisfied, a positive
16504  * error code if not and -1 if an internal error occured.
16505  */
16506 static int
xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)16507 xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
16508 		    xmlSchemaTypePtr type)
16509 {
16510     xmlSchemaTypePtr base;
16511     int ret = 0;
16512 
16513     /*
16514     * TODO: Adjust the error codes here, as I used
16515     * XML_SCHEMAP_SRC_CT_1 only yet.
16516     */
16517     base = type->baseType;
16518     if (! WXS_HAS_SIMPLE_CONTENT(type)) {
16519 	/*
16520 	* 1 If the <complexContent> alternative is chosen, the type definition
16521 	* �resolved� to by the �actual value� of the base [attribute]
16522 	* must be a complex type definition;
16523 	*/
16524 	if (! WXS_IS_COMPLEX(base)) {
16525 	    xmlChar *str = NULL;
16526 	    xmlSchemaPCustomErr(ctxt,
16527 		XML_SCHEMAP_SRC_CT_1,
16528 		WXS_BASIC_CAST type, type->node,
16529 		"If using <complexContent>, the base type is expected to be "
16530 		"a complex type. The base type '%s' is a simple type",
16531 		xmlSchemaFormatQName(&str, base->targetNamespace,
16532 		base->name));
16533 	    FREE_AND_NULL(str)
16534 	    return (XML_SCHEMAP_SRC_CT_1);
16535 	}
16536     } else {
16537 	/*
16538 	* SPEC
16539 	* 2 If the <simpleContent> alternative is chosen, all of the
16540 	* following must be true:
16541 	* 2.1 The type definition �resolved� to by the �actual value� of the
16542 	* base [attribute] must be one of the following:
16543 	*/
16544 	if (WXS_IS_SIMPLE(base)) {
16545 	    if (WXS_IS_EXTENSION(type) == 0) {
16546 		xmlChar *str = NULL;
16547 		/*
16548 		* 2.1.3 only if the <extension> alternative is also
16549 		* chosen, a simple type definition.
16550 		*/
16551 		/* TODO: Change error code to ..._SRC_CT_2_1_3. */
16552 		xmlSchemaPCustomErr(ctxt,
16553 		    XML_SCHEMAP_SRC_CT_1,
16554 		    WXS_BASIC_CAST type, NULL,
16555 		    "If using <simpleContent> and <restriction>, the base "
16556 		    "type must be a complex type. The base type '%s' is "
16557 		    "a simple type",
16558 		    xmlSchemaFormatQName(&str, base->targetNamespace,
16559 			base->name));
16560 		FREE_AND_NULL(str)
16561 		return (XML_SCHEMAP_SRC_CT_1);
16562 	    }
16563 	} else {
16564 	    /* Base type is a complex type. */
16565 	    if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16566 		(base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16567 		/*
16568 		* 2.1.1 a complex type definition whose {content type} is a
16569 		* simple type definition;
16570 		* PASS
16571 		*/
16572 		if (base->contentTypeDef == NULL) {
16573 		    xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
16574 			WXS_BASIC_CAST type, NULL,
16575 			"Internal error: xmlSchemaCheckSRCCT, "
16576 			"'%s', base type has no content type",
16577 			type->name);
16578 		    return (-1);
16579 		}
16580 	    } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16581 		(WXS_IS_RESTRICTION(type))) {
16582 
16583 		/*
16584 		* 2.1.2 only if the <restriction> alternative is also
16585 		* chosen, a complex type definition whose {content type}
16586 		* is mixed and a particle emptiable.
16587 		*/
16588 		if (! xmlSchemaIsParticleEmptiable(
16589 		    (xmlSchemaParticlePtr) base->subtypes)) {
16590 		    ret = XML_SCHEMAP_SRC_CT_1;
16591 		} else
16592 		    /*
16593 		    * Attention: at this point the <simpleType> child is in
16594 		    * ->contentTypeDef (put there during parsing).
16595 		    */
16596 		    if (type->contentTypeDef == NULL) {
16597 		    xmlChar *str = NULL;
16598 		    /*
16599 		    * 2.2 If clause 2.1.2 above is satisfied, then there
16600 		    * must be a <simpleType> among the [children] of
16601 		    * <restriction>.
16602 		    */
16603 		    /* TODO: Change error code to ..._SRC_CT_2_2. */
16604 		    xmlSchemaPCustomErr(ctxt,
16605 			XML_SCHEMAP_SRC_CT_1,
16606 			WXS_BASIC_CAST type, NULL,
16607 			"A <simpleType> is expected among the children "
16608 			"of <restriction>, if <simpleContent> is used and "
16609 			"the base type '%s' is a complex type",
16610 			xmlSchemaFormatQName(&str, base->targetNamespace,
16611 			base->name));
16612 		    FREE_AND_NULL(str)
16613 		    return (XML_SCHEMAP_SRC_CT_1);
16614 		}
16615 	    } else {
16616 		ret = XML_SCHEMAP_SRC_CT_1;
16617 	    }
16618 	}
16619 	if (ret > 0) {
16620 	    xmlChar *str = NULL;
16621 	    if (WXS_IS_RESTRICTION(type)) {
16622 		xmlSchemaPCustomErr(ctxt,
16623 		    XML_SCHEMAP_SRC_CT_1,
16624 		    WXS_BASIC_CAST type, NULL,
16625 		    "If <simpleContent> and <restriction> is used, the "
16626 		    "base type must be a simple type or a complex type with "
16627 		    "mixed content and particle emptiable. The base type "
16628 		    "'%s' is none of those",
16629 		    xmlSchemaFormatQName(&str, base->targetNamespace,
16630 		    base->name));
16631 	    } else {
16632 		xmlSchemaPCustomErr(ctxt,
16633 		    XML_SCHEMAP_SRC_CT_1,
16634 		    WXS_BASIC_CAST type, NULL,
16635 		    "If <simpleContent> and <extension> is used, the "
16636 		    "base type must be a simple type. The base type '%s' "
16637 		    "is a complex type",
16638 		    xmlSchemaFormatQName(&str, base->targetNamespace,
16639 		    base->name));
16640 	    }
16641 	    FREE_AND_NULL(str)
16642 	}
16643     }
16644     /*
16645     * SPEC (3) "The corresponding complex type definition component must
16646     * satisfy the conditions set out in Constraints on Complex Type
16647     * Definition Schema Components (�3.4.6);"
16648     * NOTE (3) will be done in xmlSchemaTypeFixup().
16649     */
16650     /*
16651     * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
16652     * above for {attribute wildcard} is satisfied, the intensional
16653     * intersection must be expressible, as defined in Attribute Wildcard
16654     * Intersection (�3.10.6).
16655     * NOTE (4) is done in xmlSchemaFixupTypeAttributeUses().
16656     */
16657     return (ret);
16658 }
16659 
16660 #ifdef ENABLE_PARTICLE_RESTRICTION
16661 /**
16662  * xmlSchemaCheckParticleRangeOK:
16663  * @ctxt:  the schema parser context
16664  * @type:  the complex type definition
16665  *
16666  * (3.9.6) Constraints on Particle Schema Components
16667  * Schema Component Constraint:
16668  * Occurrence Range OK (range-ok)
16669  *
16670  * STATUS: complete
16671  *
16672  * Returns 0 if the constraints are satisfied, a positive
16673  * error code if not and -1 if an internal error occured.
16674  */
16675 static int
xmlSchemaCheckParticleRangeOK(int rmin,int rmax,int bmin,int bmax)16676 xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
16677 			      int bmin, int bmax)
16678 {
16679     if (rmin < bmin)
16680 	return (1);
16681     if ((bmax != UNBOUNDED) &&
16682 	(rmax > bmax))
16683 	return (1);
16684     return (0);
16685 }
16686 
16687 /**
16688  * xmlSchemaCheckRCaseNameAndTypeOK:
16689  * @ctxt:  the schema parser context
16690  * @r: the restricting element declaration particle
16691  * @b: the base element declaration particle
16692  *
16693  * (3.9.6) Constraints on Particle Schema Components
16694  * Schema Component Constraint:
16695  * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
16696  * (rcase-NameAndTypeOK)
16697  *
16698  * STATUS:
16699  *   MISSING (3.2.3)
16700  *   CLARIFY: (3.2.2)
16701  *
16702  * Returns 0 if the constraints are satisfied, a positive
16703  * error code if not and -1 if an internal error occured.
16704  */
16705 static int
xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)16706 xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
16707 				 xmlSchemaParticlePtr r,
16708 				 xmlSchemaParticlePtr b)
16709 {
16710     xmlSchemaElementPtr elemR, elemB;
16711 
16712     /* TODO: Error codes (rcase-NameAndTypeOK). */
16713     elemR = (xmlSchemaElementPtr) r->children;
16714     elemB = (xmlSchemaElementPtr) b->children;
16715     /*
16716     * SPEC (1) "The declarations' {name}s and {target namespace}s are
16717     * the same."
16718     */
16719     if ((elemR != elemB) &&
16720 	((! xmlStrEqual(elemR->name, elemB->name)) ||
16721 	(! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
16722 	return (1);
16723     /*
16724     * SPEC (2) "R's occurrence range is a valid restriction of B's
16725     * occurrence range as defined by Occurrence Range OK (�3.9.6)."
16726     */
16727     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16728 	    b->minOccurs, b->maxOccurs) != 0)
16729 	return (1);
16730     /*
16731     * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
16732     * {scope} are global."
16733     */
16734     if (elemR == elemB)
16735 	return (0);
16736     /*
16737     * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
16738     */
16739     if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
16740 	(elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
16741 	 return (1);
16742     /*
16743     * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
16744     * or is not fixed, or R's declaration's {value constraint} is fixed
16745     * with the same value."
16746     */
16747     if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
16748 	((elemR->value == NULL) ||
16749 	 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
16750 	 /* TODO: Equality of the initial value or normalized or canonical? */
16751 	 (! xmlStrEqual(elemR->value, elemB->value))))
16752 	 return (1);
16753     /*
16754     * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
16755     * definitions} is a subset of B's declaration's {identity-constraint
16756     * definitions}, if any."
16757     */
16758     if (elemB->idcs != NULL) {
16759 	/* TODO */
16760     }
16761     /*
16762     * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
16763     * superset of B's declaration's {disallowed substitutions}."
16764     */
16765     if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
16766 	 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
16767 	((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
16768 	 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
16769 	((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
16770 	 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
16771 	 return (1);
16772     /*
16773     * SPEC (3.2.5) "R's {type definition} is validly derived given
16774     * {extension, list, union} from B's {type definition}"
16775     *
16776     * BADSPEC TODO: What's the point of adding "list" and "union" to the
16777     * set, if the corresponding constraints handle "restriction" and
16778     * "extension" only?
16779     *
16780     */
16781     {
16782 	int set = 0;
16783 
16784 	set |= SUBSET_EXTENSION;
16785 	set |= SUBSET_LIST;
16786 	set |= SUBSET_UNION;
16787 	if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST ctxt, elemR->subtypes,
16788 	    elemB->subtypes, set) != 0)
16789 	    return (1);
16790     }
16791     return (0);
16792 }
16793 
16794 /**
16795  * xmlSchemaCheckRCaseNSCompat:
16796  * @ctxt:  the schema parser context
16797  * @r: the restricting element declaration particle
16798  * @b: the base wildcard particle
16799  *
16800  * (3.9.6) Constraints on Particle Schema Components
16801  * Schema Component Constraint:
16802  * Particle Derivation OK (Elt:Any -- NSCompat)
16803  * (rcase-NSCompat)
16804  *
16805  * STATUS: complete
16806  *
16807  * Returns 0 if the constraints are satisfied, a positive
16808  * error code if not and -1 if an internal error occured.
16809  */
16810 static int
xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)16811 xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
16812 			    xmlSchemaParticlePtr r,
16813 			    xmlSchemaParticlePtr b)
16814 {
16815     /* TODO:Error codes (rcase-NSCompat). */
16816     /*
16817     * SPEC "For an element declaration particle to be a �valid restriction�
16818     * of a wildcard particle all of the following must be true:"
16819     *
16820     * SPEC (1) "The element declaration's {target namespace} is �valid�
16821     * with respect to the wildcard's {namespace constraint} as defined by
16822     * Wildcard allows Namespace Name (�3.10.4)."
16823     */
16824     if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
16825 	((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
16826 	return (1);
16827     /*
16828     * SPEC (2) "R's occurrence range is a valid restriction of B's
16829     * occurrence range as defined by Occurrence Range OK (�3.9.6)."
16830     */
16831     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16832 	    b->minOccurs, b->maxOccurs) != 0)
16833 	return (1);
16834 
16835     return (0);
16836 }
16837 
16838 /**
16839  * xmlSchemaCheckRCaseRecurseAsIfGroup:
16840  * @ctxt:  the schema parser context
16841  * @r: the restricting element declaration particle
16842  * @b: the base model group particle
16843  *
16844  * (3.9.6) Constraints on Particle Schema Components
16845  * Schema Component Constraint:
16846  * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
16847  * (rcase-RecurseAsIfGroup)
16848  *
16849  * STATUS: TODO
16850  *
16851  * Returns 0 if the constraints are satisfied, a positive
16852  * error code if not and -1 if an internal error occured.
16853  */
16854 static int
xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)16855 xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
16856 				    xmlSchemaParticlePtr r,
16857 				    xmlSchemaParticlePtr b)
16858 {
16859     /* TODO: Error codes (rcase-RecurseAsIfGroup). */
16860     TODO
16861     return (0);
16862 }
16863 
16864 /**
16865  * xmlSchemaCheckRCaseNSSubset:
16866  * @ctxt:  the schema parser context
16867  * @r: the restricting wildcard particle
16868  * @b: the base wildcard particle
16869  *
16870  * (3.9.6) Constraints on Particle Schema Components
16871  * Schema Component Constraint:
16872  * Particle Derivation OK (Any:Any -- NSSubset)
16873  * (rcase-NSSubset)
16874  *
16875  * STATUS: complete
16876  *
16877  * Returns 0 if the constraints are satisfied, a positive
16878  * error code if not and -1 if an internal error occured.
16879  */
16880 static int
xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b,int isAnyTypeBase)16881 xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
16882 				    xmlSchemaParticlePtr r,
16883 				    xmlSchemaParticlePtr b,
16884 				    int isAnyTypeBase)
16885 {
16886     /* TODO: Error codes (rcase-NSSubset). */
16887     /*
16888     * SPEC (1) "R's occurrence range is a valid restriction of B's
16889     * occurrence range as defined by Occurrence Range OK (�3.9.6)."
16890     */
16891     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16892 	    b->minOccurs, b->maxOccurs))
16893 	return (1);
16894     /*
16895     * SPEC (2) "R's {namespace constraint} must be an intensional subset
16896     * of B's {namespace constraint} as defined by Wildcard Subset (�3.10.6)."
16897     */
16898     if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
16899 	(xmlSchemaWildcardPtr) b->children))
16900 	return (1);
16901     /*
16902     * SPEC (3) "Unless B is the content model wildcard of the �ur-type
16903     * definition�, R's {process contents} must be identical to or stronger
16904     * than B's {process contents}, where strict is stronger than lax is
16905     * stronger than skip."
16906     */
16907     if (! isAnyTypeBase) {
16908 	if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
16909 	    ((xmlSchemaWildcardPtr) b->children)->processContents)
16910 	    return (1);
16911     }
16912 
16913     return (0);
16914 }
16915 
16916 /**
16917  * xmlSchemaCheckCOSParticleRestrict:
16918  * @ctxt:  the schema parser context
16919  * @type:  the complex type definition
16920  *
16921  * (3.9.6) Constraints on Particle Schema Components
16922  * Schema Component Constraint:
16923  * Particle Valid (Restriction) (cos-particle-restrict)
16924  *
16925  * STATUS: TODO
16926  *
16927  * Returns 0 if the constraints are satisfied, a positive
16928  * error code if not and -1 if an internal error occured.
16929  */
16930 static int
xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)16931 xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
16932 				  xmlSchemaParticlePtr r,
16933 				  xmlSchemaParticlePtr b)
16934 {
16935     int ret = 0;
16936 
16937     /*part = WXS_TYPE_PARTICLE(type);
16938     basePart = WXS_TYPE_PARTICLE(base);
16939     */
16940 
16941     TODO
16942 
16943     /*
16944     * SPEC (1) "They are the same particle."
16945     */
16946     if (r == b)
16947 	return (0);
16948 
16949 
16950     return (0);
16951 }
16952 
16953 #if 0
16954 /**
16955  * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
16956  * @ctxt:  the schema parser context
16957  * @r: the model group particle
16958  * @b: the base wildcard particle
16959  *
16960  * (3.9.6) Constraints on Particle Schema Components
16961  * Schema Component Constraint:
16962  * Particle Derivation OK (All/Choice/Sequence:Any --
16963  *                         NSRecurseCheckCardinality)
16964  * (rcase-NSRecurseCheckCardinality)
16965  *
16966  * STATUS: TODO: subst-groups
16967  *
16968  * Returns 0 if the constraints are satisfied, a positive
16969  * error code if not and -1 if an internal error occured.
16970  */
16971 static int
16972 xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
16973 					     xmlSchemaParticlePtr r,
16974 					     xmlSchemaParticlePtr b)
16975 {
16976     xmlSchemaParticlePtr part;
16977     /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
16978     if ((r->children == NULL) || (r->children->children == NULL))
16979 	return (-1);
16980     /*
16981     * SPEC "For a group particle to be a �valid restriction� of a
16982     * wildcard particle..."
16983     *
16984     * SPEC (1) "Every member of the {particles} of the group is a �valid
16985     * restriction� of the wildcard as defined by
16986     * Particle Valid (Restriction) (�3.9.6)."
16987     */
16988     part = (xmlSchemaParticlePtr) r->children->children;
16989     do {
16990 	if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
16991 	    return (1);
16992 	part = (xmlSchemaParticlePtr) part->next;
16993     } while (part != NULL);
16994     /*
16995     * SPEC (2) "The effective total range of the group [...] is a
16996     * valid restriction of B's occurrence range as defined by
16997     * Occurrence Range OK (�3.9.6)."
16998     */
16999     if (xmlSchemaCheckParticleRangeOK(
17000 	    xmlSchemaGetParticleTotalRangeMin(r),
17001 	    xmlSchemaGetParticleTotalRangeMax(r),
17002 	    b->minOccurs, b->maxOccurs) != 0)
17003 	return (1);
17004     return (0);
17005 }
17006 #endif
17007 
17008 /**
17009  * xmlSchemaCheckRCaseRecurse:
17010  * @ctxt:  the schema parser context
17011  * @r: the <all> or <sequence> model group particle
17012  * @b: the base <all> or <sequence> model group particle
17013  *
17014  * (3.9.6) Constraints on Particle Schema Components
17015  * Schema Component Constraint:
17016  * Particle Derivation OK (All:All,Sequence:Sequence --
17017                            Recurse)
17018  * (rcase-Recurse)
17019  *
17020  * STATUS:  ?
17021  * TODO: subst-groups
17022  *
17023  * Returns 0 if the constraints are satisfied, a positive
17024  * error code if not and -1 if an internal error occured.
17025  */
17026 static int
xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)17027 xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
17028 			   xmlSchemaParticlePtr r,
17029 			   xmlSchemaParticlePtr b)
17030 {
17031     /* xmlSchemaParticlePtr part; */
17032     /* TODO: Error codes (rcase-Recurse). */
17033     if ((r->children == NULL) || (b->children == NULL) ||
17034 	(r->children->type != b->children->type))
17035 	return (-1);
17036     /*
17037     * SPEC "For an all or sequence group particle to be a �valid
17038     * restriction� of another group particle with the same {compositor}..."
17039     *
17040     * SPEC (1) "R's occurrence range is a valid restriction of B's
17041     * occurrence range as defined by Occurrence Range OK (�3.9.6)."
17042     */
17043     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17044 	    b->minOccurs, b->maxOccurs))
17045 	return (1);
17046 
17047 
17048     return (0);
17049 }
17050 
17051 #endif
17052 
17053 #define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
17054     xmlSchemaPCustomErrExt(pctxt,      \
17055 	XML_SCHEMAP_INVALID_FACET_VALUE, \
17056 	WXS_BASIC_CAST fac1, fac1->node, \
17057 	"It is an error for both '%s' and '%s' to be specified on the "\
17058 	"same type definition", \
17059 	BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
17060 	BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
17061 
17062 #define FACET_RESTR_ERR(fac1, msg) \
17063     xmlSchemaPCustomErr(pctxt,      \
17064 	XML_SCHEMAP_INVALID_FACET_VALUE, \
17065 	WXS_BASIC_CAST fac1, fac1->node, \
17066 	msg, NULL);
17067 
17068 #define FACET_RESTR_FIXED_ERR(fac) \
17069     xmlSchemaPCustomErr(pctxt, \
17070 	XML_SCHEMAP_INVALID_FACET_VALUE, \
17071 	WXS_BASIC_CAST fac, fac->node, \
17072 	"The base type's facet is 'fixed', thus the value must not " \
17073 	"differ", NULL);
17074 
17075 static void
xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,xmlSchemaFacetPtr facet1,xmlSchemaFacetPtr facet2,int lessGreater,int orEqual,int ofBase)17076 xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
17077 			xmlSchemaFacetPtr facet1,
17078 			xmlSchemaFacetPtr facet2,
17079 			int lessGreater,
17080 			int orEqual,
17081 			int ofBase)
17082 {
17083     xmlChar *msg = NULL;
17084 
17085     msg = xmlStrdup(BAD_CAST "'");
17086     msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
17087     msg = xmlStrcat(msg, BAD_CAST "' has to be");
17088     if (lessGreater == 0)
17089 	msg = xmlStrcat(msg, BAD_CAST " equal to");
17090     if (lessGreater == 1)
17091 	msg = xmlStrcat(msg, BAD_CAST " greater than");
17092     else
17093 	msg = xmlStrcat(msg, BAD_CAST " less than");
17094 
17095     if (orEqual)
17096 	msg = xmlStrcat(msg, BAD_CAST " or equal to");
17097     msg = xmlStrcat(msg, BAD_CAST " '");
17098     msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
17099     if (ofBase)
17100 	msg = xmlStrcat(msg, BAD_CAST "' of the base type");
17101     else
17102 	msg = xmlStrcat(msg, BAD_CAST "'");
17103 
17104     xmlSchemaPCustomErr(pctxt,
17105 	XML_SCHEMAP_INVALID_FACET_VALUE,
17106 	WXS_BASIC_CAST facet1, NULL,
17107 	(const char *) msg, NULL);
17108 
17109     if (msg != NULL)
17110 	xmlFree(msg);
17111 }
17112 
17113 /*
17114 * xmlSchemaDeriveAndValidateFacets:
17115 *
17116 * Schema Component Constraint: Simple Type Restriction (Facets)
17117 * (st-restrict-facets)
17118 */
17119 static int
xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)17120 xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
17121 				 xmlSchemaTypePtr type)
17122 {
17123     xmlSchemaTypePtr base = type->baseType;
17124     xmlSchemaFacetLinkPtr link, cur, last = NULL;
17125     xmlSchemaFacetPtr facet, bfacet,
17126 	flength = NULL, ftotdig = NULL, ffracdig = NULL,
17127 	fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
17128 	fmininc = NULL, fmaxinc = NULL,
17129 	fminexc = NULL, fmaxexc = NULL,
17130 	bflength = NULL, bftotdig = NULL, bffracdig = NULL,
17131 	bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
17132 	bfmininc = NULL, bfmaxinc = NULL,
17133 	bfminexc = NULL, bfmaxexc = NULL;
17134     int res; /* err = 0, fixedErr; */
17135 
17136     /*
17137     * SPEC st-restrict-facets 1:
17138     * "The {variety} of R is the same as that of B."
17139     */
17140     /*
17141     * SPEC st-restrict-facets 2:
17142     * "If {variety} is atomic, the {primitive type definition}
17143     * of R is the same as that of B."
17144     *
17145     * NOTE: we leave 1 & 2 out for now, since this will be
17146     * satisfied by the derivation process.
17147     * CONSTRUCTION TODO: Maybe needed if using a construction API.
17148     */
17149     /*
17150     * SPEC st-restrict-facets 3:
17151     * "The {facets} of R are the union of S and the {facets}
17152     * of B, eliminating duplicates. To eliminate duplicates,
17153     * when a facet of the same kind occurs in both S and the
17154     * {facets} of B, the one in the {facets} of B is not
17155     * included, with the exception of enumeration and pattern
17156     * facets, for which multiple occurrences with distinct values
17157     * are allowed."
17158     */
17159 
17160     if ((type->facetSet == NULL) && (base->facetSet == NULL))
17161 	return (0);
17162 
17163     last = type->facetSet;
17164     if (last != NULL)
17165 	while (last->next != NULL)
17166 	    last = last->next;
17167 
17168     for (cur = type->facetSet; cur != NULL; cur = cur->next) {
17169 	facet = cur->facet;
17170 	switch (facet->type) {
17171 	    case XML_SCHEMA_FACET_LENGTH:
17172 		flength = facet; break;
17173 	    case XML_SCHEMA_FACET_MINLENGTH:
17174 		fminlen = facet; break;
17175 	    case XML_SCHEMA_FACET_MININCLUSIVE:
17176 		fmininc = facet; break;
17177 	    case XML_SCHEMA_FACET_MINEXCLUSIVE:
17178 		fminexc = facet; break;
17179 	    case XML_SCHEMA_FACET_MAXLENGTH:
17180 		fmaxlen = facet; break;
17181 	    case XML_SCHEMA_FACET_MAXINCLUSIVE:
17182 		fmaxinc = facet; break;
17183 	    case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17184 		fmaxexc = facet; break;
17185 	    case XML_SCHEMA_FACET_TOTALDIGITS:
17186 		ftotdig = facet; break;
17187 	    case XML_SCHEMA_FACET_FRACTIONDIGITS:
17188 		ffracdig = facet; break;
17189 	    default:
17190 		break;
17191 	}
17192     }
17193     for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17194 	facet = cur->facet;
17195 	switch (facet->type) {
17196 	    case XML_SCHEMA_FACET_LENGTH:
17197 		bflength = facet; break;
17198 	    case XML_SCHEMA_FACET_MINLENGTH:
17199 		bfminlen = facet; break;
17200 	    case XML_SCHEMA_FACET_MININCLUSIVE:
17201 		bfmininc = facet; break;
17202 	    case XML_SCHEMA_FACET_MINEXCLUSIVE:
17203 		bfminexc = facet; break;
17204 	    case XML_SCHEMA_FACET_MAXLENGTH:
17205 		bfmaxlen = facet; break;
17206 	    case XML_SCHEMA_FACET_MAXINCLUSIVE:
17207 		bfmaxinc = facet; break;
17208 	    case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17209 		bfmaxexc = facet; break;
17210 	    case XML_SCHEMA_FACET_TOTALDIGITS:
17211 		bftotdig = facet; break;
17212 	    case XML_SCHEMA_FACET_FRACTIONDIGITS:
17213 		bffracdig = facet; break;
17214 	    default:
17215 		break;
17216 	}
17217     }
17218     /*
17219     * length and minLength or maxLength (2.2) + (3.2)
17220     */
17221     if (flength && (fminlen || fmaxlen)) {
17222 	FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
17223 	    "either of 'minLength' or 'maxLength' to be specified on "
17224 	    "the same type definition")
17225     }
17226     /*
17227     * Mutual exclusions in the same derivation step.
17228     */
17229     if ((fmaxinc) && (fmaxexc)) {
17230 	/*
17231 	* SCC "maxInclusive and maxExclusive"
17232 	*/
17233 	FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
17234     }
17235     if ((fmininc) && (fminexc)) {
17236 	/*
17237 	* SCC "minInclusive and minExclusive"
17238 	*/
17239 	FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
17240     }
17241 
17242     if (flength && bflength) {
17243 	/*
17244 	* SCC "length valid restriction"
17245 	* The values have to be equal.
17246 	*/
17247 	res = xmlSchemaCompareValues(flength->val, bflength->val);
17248 	if (res == -2)
17249 	    goto internal_error;
17250 	if (res != 0)
17251 	    xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
17252 	if ((res != 0) && (bflength->fixed)) {
17253 	    FACET_RESTR_FIXED_ERR(flength)
17254 	}
17255 
17256     }
17257     if (fminlen && bfminlen) {
17258 	/*
17259 	* SCC "minLength valid restriction"
17260 	* minLength >= BASE minLength
17261 	*/
17262 	res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
17263 	if (res == -2)
17264 	    goto internal_error;
17265 	if (res == -1)
17266 	    xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
17267 	if ((res != 0) && (bfminlen->fixed)) {
17268 	    FACET_RESTR_FIXED_ERR(fminlen)
17269 	}
17270     }
17271     if (fmaxlen && bfmaxlen) {
17272 	/*
17273 	* SCC "maxLength valid restriction"
17274 	* maxLength <= BASE minLength
17275 	*/
17276 	res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
17277 	if (res == -2)
17278 	    goto internal_error;
17279 	if (res == 1)
17280 	    xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
17281 	if ((res != 0) && (bfmaxlen->fixed)) {
17282 	    FACET_RESTR_FIXED_ERR(fmaxlen)
17283 	}
17284     }
17285     /*
17286     * SCC "length and minLength or maxLength"
17287     */
17288     if (! flength)
17289 	flength = bflength;
17290     if (flength) {
17291 	if (! fminlen)
17292 	    flength = bflength;
17293 	if (fminlen) {
17294 	    /* (1.1) length >= minLength */
17295 	    res = xmlSchemaCompareValues(flength->val, fminlen->val);
17296 	    if (res == -2)
17297 		goto internal_error;
17298 	    if (res == -1)
17299 		xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
17300 	}
17301 	if (! fmaxlen)
17302 	    fmaxlen = bfmaxlen;
17303 	if (fmaxlen) {
17304 	    /* (2.1) length <= maxLength */
17305 	    res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
17306 	    if (res == -2)
17307 		goto internal_error;
17308 	    if (res == 1)
17309 		xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
17310 	}
17311     }
17312     if (fmaxinc) {
17313 	/*
17314 	* "maxInclusive"
17315 	*/
17316 	if (fmininc) {
17317 	    /* SCC "maxInclusive >= minInclusive" */
17318 	    res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
17319 	    if (res == -2)
17320 		goto internal_error;
17321 	    if (res == -1) {
17322 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
17323 	    }
17324 	}
17325 	/*
17326 	* SCC "maxInclusive valid restriction"
17327 	*/
17328 	if (bfmaxinc) {
17329 	    /* maxInclusive <= BASE maxInclusive */
17330 	    res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
17331 	    if (res == -2)
17332 		goto internal_error;
17333 	    if (res == 1)
17334 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
17335 	    if ((res != 0) && (bfmaxinc->fixed)) {
17336 		FACET_RESTR_FIXED_ERR(fmaxinc)
17337 	    }
17338 	}
17339 	if (bfmaxexc) {
17340 	    /* maxInclusive < BASE maxExclusive */
17341 	    res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
17342 	    if (res == -2)
17343 		goto internal_error;
17344 	    if (res != -1) {
17345 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
17346 	    }
17347 	}
17348 	if (bfmininc) {
17349 	    /* maxInclusive >= BASE minInclusive */
17350 	    res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
17351 	    if (res == -2)
17352 		goto internal_error;
17353 	    if (res == -1) {
17354 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
17355 	    }
17356 	}
17357 	if (bfminexc) {
17358 	    /* maxInclusive > BASE minExclusive */
17359 	    res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
17360 	    if (res == -2)
17361 		goto internal_error;
17362 	    if (res != 1) {
17363 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
17364 	    }
17365 	}
17366     }
17367     if (fmaxexc) {
17368 	/*
17369 	* "maxExclusive >= minExclusive"
17370 	*/
17371 	if (fminexc) {
17372 	    res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
17373 	    if (res == -2)
17374 		goto internal_error;
17375 	    if (res == -1) {
17376 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
17377 	    }
17378 	}
17379 	/*
17380 	* "maxExclusive valid restriction"
17381 	*/
17382 	if (bfmaxexc) {
17383 	    /* maxExclusive <= BASE maxExclusive */
17384 	    res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
17385 	    if (res == -2)
17386 		goto internal_error;
17387 	    if (res == 1) {
17388 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
17389 	    }
17390 	    if ((res != 0) && (bfmaxexc->fixed)) {
17391 		FACET_RESTR_FIXED_ERR(fmaxexc)
17392 	    }
17393 	}
17394 	if (bfmaxinc) {
17395 	    /* maxExclusive <= BASE maxInclusive */
17396 	    res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
17397 	    if (res == -2)
17398 		goto internal_error;
17399 	    if (res == 1) {
17400 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
17401 	    }
17402 	}
17403 	if (bfmininc) {
17404 	    /* maxExclusive > BASE minInclusive */
17405 	    res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
17406 	    if (res == -2)
17407 		goto internal_error;
17408 	    if (res != 1) {
17409 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
17410 	    }
17411 	}
17412 	if (bfminexc) {
17413 	    /* maxExclusive > BASE minExclusive */
17414 	    res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
17415 	    if (res == -2)
17416 		goto internal_error;
17417 	    if (res != 1) {
17418 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
17419 	    }
17420 	}
17421     }
17422     if (fminexc) {
17423 	/*
17424 	* "minExclusive < maxInclusive"
17425 	*/
17426 	if (fmaxinc) {
17427 	    res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
17428 	    if (res == -2)
17429 		goto internal_error;
17430 	    if (res != -1) {
17431 		xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
17432 	    }
17433 	}
17434 	/*
17435 	* "minExclusive valid restriction"
17436 	*/
17437 	if (bfminexc) {
17438 	    /* minExclusive >= BASE minExclusive */
17439 	    res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
17440 	    if (res == -2)
17441 		goto internal_error;
17442 	    if (res == -1) {
17443 		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
17444 	    }
17445 	    if ((res != 0) && (bfminexc->fixed)) {
17446 		FACET_RESTR_FIXED_ERR(fminexc)
17447 	    }
17448 	}
17449 	if (bfmaxinc) {
17450 	    /* minExclusive <= BASE maxInclusive */
17451 	    res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
17452 	    if (res == -2)
17453 		goto internal_error;
17454 	    if (res == 1) {
17455 		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
17456 	    }
17457 	}
17458 	if (bfmininc) {
17459 	    /* minExclusive >= BASE minInclusive */
17460 	    res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
17461 	    if (res == -2)
17462 		goto internal_error;
17463 	    if (res == -1) {
17464 		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
17465 	    }
17466 	}
17467 	if (bfmaxexc) {
17468 	    /* minExclusive < BASE maxExclusive */
17469 	    res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
17470 	    if (res == -2)
17471 		goto internal_error;
17472 	    if (res != -1) {
17473 		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
17474 	    }
17475 	}
17476     }
17477     if (fmininc) {
17478 	/*
17479 	* "minInclusive < maxExclusive"
17480 	*/
17481 	if (fmaxexc) {
17482 	    res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
17483 	    if (res == -2)
17484 		goto internal_error;
17485 	    if (res != -1) {
17486 		xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
17487 	    }
17488 	}
17489 	/*
17490 	* "minExclusive valid restriction"
17491 	*/
17492 	if (bfmininc) {
17493 	    /* minInclusive >= BASE minInclusive */
17494 	    res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
17495 	    if (res == -2)
17496 		goto internal_error;
17497 	    if (res == -1) {
17498 		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
17499 	    }
17500 	    if ((res != 0) && (bfmininc->fixed)) {
17501 		FACET_RESTR_FIXED_ERR(fmininc)
17502 	    }
17503 	}
17504 	if (bfmaxinc) {
17505 	    /* minInclusive <= BASE maxInclusive */
17506 	    res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
17507 	    if (res == -2)
17508 		goto internal_error;
17509 	    if (res == 1) {
17510 		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
17511 	    }
17512 	}
17513 	if (bfminexc) {
17514 	    /* minInclusive > BASE minExclusive */
17515 	    res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
17516 	    if (res == -2)
17517 		goto internal_error;
17518 	    if (res != 1)
17519 		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
17520 	}
17521 	if (bfmaxexc) {
17522 	    /* minInclusive < BASE maxExclusive */
17523 	    res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
17524 	    if (res == -2)
17525 		goto internal_error;
17526 	    if (res != -1)
17527 		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
17528 	}
17529     }
17530     if (ftotdig && bftotdig) {
17531 	/*
17532 	* SCC " totalDigits valid restriction"
17533 	* totalDigits <= BASE totalDigits
17534 	*/
17535 	res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
17536 	if (res == -2)
17537 	    goto internal_error;
17538 	if (res == 1)
17539 	    xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
17540 	    -1, 1, 1);
17541 	if ((res != 0) && (bftotdig->fixed)) {
17542 	    FACET_RESTR_FIXED_ERR(ftotdig)
17543 	}
17544     }
17545     if (ffracdig && bffracdig) {
17546 	/*
17547 	* SCC  "fractionDigits valid restriction"
17548 	* fractionDigits <= BASE fractionDigits
17549 	*/
17550 	res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
17551 	if (res == -2)
17552 	    goto internal_error;
17553 	if (res == 1)
17554 	    xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
17555 	    -1, 1, 1);
17556 	if ((res != 0) && (bffracdig->fixed)) {
17557 	    FACET_RESTR_FIXED_ERR(ffracdig)
17558 	}
17559     }
17560     /*
17561     * SCC "fractionDigits less than or equal to totalDigits"
17562     */
17563     if (! ftotdig)
17564 	ftotdig = bftotdig;
17565     if (! ffracdig)
17566 	ffracdig = bffracdig;
17567     if (ftotdig && ffracdig) {
17568 	res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
17569 	if (res == -2)
17570 	    goto internal_error;
17571 	if (res == 1)
17572 	    xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
17573 		-1, 1, 0);
17574     }
17575     /*
17576     * *Enumerations* won' be added here, since only the first set
17577     * of enumerations in the ancestor-or-self axis is used
17578     * for validation, plus we need to use the base type of those
17579     * enumerations for whitespace.
17580     *
17581     * *Patterns*: won't be add here, since they are ORed at
17582     * type level and ANDed at ancestor level. This will
17583     * happed during validation by walking the base axis
17584     * of the type.
17585     */
17586     for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17587 	bfacet = cur->facet;
17588 	/*
17589 	* Special handling of enumerations and patterns.
17590 	* TODO: hmm, they should not appear in the set, so remove this.
17591 	*/
17592 	if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
17593 	    (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
17594 	    continue;
17595 	/*
17596 	* Search for a duplicate facet in the current type.
17597 	*/
17598 	link = type->facetSet;
17599 	/* err = 0; */
17600 	/* fixedErr = 0; */
17601 	while (link != NULL) {
17602 	    facet = link->facet;
17603 	    if (facet->type == bfacet->type) {
17604 		switch (facet->type) {
17605 		    case XML_SCHEMA_FACET_WHITESPACE:
17606 			/*
17607 			* The whitespace must be stronger.
17608 			*/
17609 			if (facet->whitespace < bfacet->whitespace) {
17610 			    FACET_RESTR_ERR(facet,
17611 				"The 'whitespace' value has to be equal to "
17612 				"or stronger than the 'whitespace' value of "
17613 				"the base type")
17614 			}
17615 			if ((bfacet->fixed) &&
17616 			    (facet->whitespace != bfacet->whitespace)) {
17617 			    FACET_RESTR_FIXED_ERR(facet)
17618 			}
17619 			break;
17620 		    default:
17621 			break;
17622 		}
17623 		/* Duplicate found. */
17624 		break;
17625 	    }
17626 	    link = link->next;
17627 	}
17628 	/*
17629 	* If no duplicate was found: add the base types's facet
17630 	* to the set.
17631 	*/
17632 	if (link == NULL) {
17633 	    link = (xmlSchemaFacetLinkPtr)
17634 		xmlMalloc(sizeof(xmlSchemaFacetLink));
17635 	    if (link == NULL) {
17636 		xmlSchemaPErrMemory(pctxt,
17637 		    "deriving facets, creating a facet link", NULL);
17638 		return (-1);
17639 	    }
17640 	    link->facet = cur->facet;
17641 	    link->next = NULL;
17642 	    if (last == NULL)
17643 		type->facetSet = link;
17644 	    else
17645 		last->next = link;
17646 	    last = link;
17647 	}
17648 
17649     }
17650 
17651     return (0);
17652 internal_error:
17653     PERROR_INT("xmlSchemaDeriveAndValidateFacets",
17654 	"an error occured");
17655     return (-1);
17656 }
17657 
17658 static int
xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)17659 xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
17660 					     xmlSchemaTypePtr type)
17661 {
17662     xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
17663     /*
17664     * The actual value is then formed by replacing any union type
17665     * definition in the �explicit members� with the members of their
17666     * {member type definitions}, in order.
17667     *
17668     * TODO: There's a bug entry at
17669     * "http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0287.html"
17670     * which indicates that we'll keep the union types the future.
17671     */
17672     link = type->memberTypes;
17673     while (link != NULL) {
17674 
17675 	if (WXS_IS_TYPE_NOT_FIXED(link->type))
17676 	    xmlSchemaTypeFixup(link->type, ACTXT_CAST pctxt);
17677 
17678 	if (WXS_IS_UNION(link->type)) {
17679 	    subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
17680 	    if (subLink != NULL) {
17681 		link->type = subLink->type;
17682 		if (subLink->next != NULL) {
17683 		    lastLink = link->next;
17684 		    subLink = subLink->next;
17685 		    prevLink = link;
17686 		    while (subLink != NULL) {
17687 			newLink = (xmlSchemaTypeLinkPtr)
17688 			    xmlMalloc(sizeof(xmlSchemaTypeLink));
17689 			if (newLink == NULL) {
17690 			    xmlSchemaPErrMemory(pctxt, "allocating a type link",
17691 				NULL);
17692 			    return (-1);
17693 			}
17694 			newLink->type = subLink->type;
17695 			prevLink->next = newLink;
17696 			prevLink = newLink;
17697 			newLink->next = lastLink;
17698 
17699 			subLink = subLink->next;
17700 		    }
17701 		}
17702 	    }
17703 	}
17704 	link = link->next;
17705     }
17706     return (0);
17707 }
17708 
17709 static void
xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)17710 xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
17711 {
17712     int has = 0, needVal = 0, normVal = 0;
17713 
17714     has	= (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
17715     if (has) {
17716 	needVal = (type->baseType->flags &
17717 	    XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
17718 	normVal = (type->baseType->flags &
17719 	    XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
17720     }
17721     if (type->facets != NULL) {
17722 	xmlSchemaFacetPtr fac;
17723 
17724 	for (fac = type->facets; fac != NULL; fac = fac->next) {
17725 	    switch (fac->type) {
17726 		case XML_SCHEMA_FACET_WHITESPACE:
17727 		    break;
17728 		case XML_SCHEMA_FACET_PATTERN:
17729 		    normVal = 1;
17730 		    has = 1;
17731 		    break;
17732 		case XML_SCHEMA_FACET_ENUMERATION:
17733 		    needVal = 1;
17734 		    normVal = 1;
17735 		    has = 1;
17736 		    break;
17737 		default:
17738 		    has = 1;
17739 		    break;
17740 	    }
17741 	}
17742     }
17743     if (normVal)
17744 	type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
17745     if (needVal)
17746 	type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17747     if (has)
17748 	type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
17749 
17750     if (has && (! needVal) && WXS_IS_ATOMIC(type)) {
17751 	xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
17752 	/*
17753 	* OPTIMIZE VAL TODO: Some facets need a computed value.
17754 	*/
17755 	if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
17756 	    (prim->builtInType != XML_SCHEMAS_STRING)) {
17757 	    type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17758 	}
17759     }
17760 }
17761 
17762 static int
xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)17763 xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
17764 {
17765 
17766 
17767     /*
17768     * Evaluate the whitespace-facet value.
17769     */
17770     if (WXS_IS_LIST(type)) {
17771 	type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17772 	return (0);
17773     } else if (WXS_IS_UNION(type))
17774 	return (0);
17775 
17776     if (type->facetSet != NULL) {
17777 	xmlSchemaFacetLinkPtr lin;
17778 
17779 	for (lin = type->facetSet; lin != NULL; lin = lin->next) {
17780 	    if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
17781 		switch (lin->facet->whitespace) {
17782 		case XML_SCHEMAS_FACET_PRESERVE:
17783 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17784 		    break;
17785 		case XML_SCHEMAS_FACET_REPLACE:
17786 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17787 		    break;
17788 		case XML_SCHEMAS_FACET_COLLAPSE:
17789 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17790 		    break;
17791 		default:
17792 		    return (-1);
17793 		}
17794 		return (0);
17795 	    }
17796 	}
17797     }
17798     /*
17799     * For all �atomic� datatypes other than string (and types �derived�
17800     * by �restriction� from it) the value of whiteSpace is fixed to
17801     * collapse
17802     */
17803     {
17804 	xmlSchemaTypePtr anc;
17805 
17806 	for (anc = type->baseType; anc != NULL &&
17807 		anc->builtInType != XML_SCHEMAS_ANYTYPE;
17808 		anc = anc->baseType) {
17809 
17810 	    if (anc->type == XML_SCHEMA_TYPE_BASIC) {
17811 		if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
17812 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17813 
17814 		} else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
17815 		    (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
17816 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17817 
17818 		} else
17819 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17820 		break;
17821 	    }
17822 	}
17823     }
17824     return (0);
17825 }
17826 
17827 static int
xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)17828 xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,
17829 			  xmlSchemaTypePtr type)
17830 {
17831     if (type->type != XML_SCHEMA_TYPE_SIMPLE)
17832 	return(0);
17833     if (! WXS_IS_TYPE_NOT_FIXED_1(type))
17834 	return(0);
17835     type->flags |= XML_SCHEMAS_TYPE_FIXUP_1;
17836 
17837     if (WXS_IS_LIST(type)) {
17838 	/*
17839 	* Corresponds to <simpleType><list>...
17840 	*/
17841 	if (type->subtypes == NULL) {
17842 	    /*
17843 	    * This one is really needed, so get out.
17844 	    */
17845 	    PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17846 		"list type has no item-type assigned");
17847 	    return(-1);
17848 	}
17849     } else if (WXS_IS_UNION(type)) {
17850 	/*
17851 	* Corresponds to <simpleType><union>...
17852 	*/
17853 	if (type->memberTypes == NULL) {
17854 	    /*
17855 	    * This one is really needed, so get out.
17856 	    */
17857 	    PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17858 		"union type has no member-types assigned");
17859 	    return(-1);
17860 	}
17861     } else {
17862 	/*
17863 	* Corresponds to <simpleType><restriction>...
17864 	*/
17865 	if (type->baseType == NULL) {
17866 	    PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17867 		"type has no base-type assigned");
17868 	    return(-1);
17869 	}
17870 	if (WXS_IS_TYPE_NOT_FIXED_1(type->baseType))
17871 	    if (xmlSchemaFixupSimpleTypeStageOne(pctxt, type->baseType) == -1)
17872 		return(-1);
17873 	/*
17874 	* Variety
17875 	* If the <restriction> alternative is chosen, then the
17876 	* {variety} of the {base type definition}.
17877 	*/
17878 	if (WXS_IS_ATOMIC(type->baseType))
17879 	    type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
17880 	else if (WXS_IS_LIST(type->baseType)) {
17881 	    type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
17882 	    /*
17883 	    * Inherit the itemType.
17884 	    */
17885 	    type->subtypes = type->baseType->subtypes;
17886 	} else if (WXS_IS_UNION(type->baseType)) {
17887 	    type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
17888 	    /*
17889 	    * NOTE that we won't assign the memberTypes of the base,
17890 	    * since this will make trouble when freeing them; we will
17891 	    * use a lookup function to access them instead.
17892 	    */
17893 	}
17894     }
17895     return(0);
17896 }
17897 
17898 #ifdef DEBUG_TYPE
17899 static void
xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)17900 xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt,
17901 		       xmlSchemaTypePtr type)
17902 {
17903     if (type->node != NULL) {
17904         xmlGenericError(xmlGenericErrorContext,
17905                         "Type of %s : %s:%d :", name,
17906                         type->node->doc->URL,
17907                         xmlGetLineNo(type->node));
17908     } else {
17909         xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
17910     }
17911     if ((WXS_IS_SIMPLE(type)) || (WXS_IS_COMPLEX(type))) {
17912 	switch (type->contentType) {
17913 	    case XML_SCHEMA_CONTENT_SIMPLE:
17914 		xmlGenericError(xmlGenericErrorContext, "simple\n");
17915 		break;
17916 	    case XML_SCHEMA_CONTENT_ELEMENTS:
17917 		xmlGenericError(xmlGenericErrorContext, "elements\n");
17918 		break;
17919 	    case XML_SCHEMA_CONTENT_UNKNOWN:
17920 		xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
17921 		break;
17922 	    case XML_SCHEMA_CONTENT_EMPTY:
17923 		xmlGenericError(xmlGenericErrorContext, "empty\n");
17924 		break;
17925 	    case XML_SCHEMA_CONTENT_MIXED:
17926 		if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
17927 		    type->subtypes))
17928 		    xmlGenericError(xmlGenericErrorContext,
17929 			"mixed as emptiable particle\n");
17930 		else
17931 		    xmlGenericError(xmlGenericErrorContext, "mixed\n");
17932 		break;
17933 		/* Removed, since not used. */
17934 		/*
17935 		case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
17936 		xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
17937 		break;
17938 		*/
17939 	    case XML_SCHEMA_CONTENT_BASIC:
17940 		xmlGenericError(xmlGenericErrorContext, "basic\n");
17941 		break;
17942 	    default:
17943 		xmlGenericError(xmlGenericErrorContext,
17944 		    "not registered !!!\n");
17945 		break;
17946 	}
17947     }
17948 }
17949 #endif
17950 
17951 /*
17952 * 3.14.6 Constraints on Simple Type Definition Schema Components
17953 */
17954 static int
xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)17955 xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,
17956 				 xmlSchemaTypePtr type)
17957 {
17958     int res, olderrs = pctxt->nberrors;
17959 
17960     if (type->type != XML_SCHEMA_TYPE_SIMPLE)
17961 	return(-1);
17962 
17963     if (! WXS_IS_TYPE_NOT_FIXED(type))
17964 	return(0);
17965 
17966     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
17967     type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
17968 
17969     if (type->baseType == NULL) {
17970 	PERROR_INT("xmlSchemaFixupSimpleTypeStageTwo",
17971 	    "missing baseType");
17972 	goto exit_failure;
17973     }
17974     if (WXS_IS_TYPE_NOT_FIXED(type->baseType))
17975 	xmlSchemaTypeFixup(type->baseType, ACTXT_CAST pctxt);
17976     /*
17977     * If a member type of a union is a union itself, we need to substitute
17978     * that member type for its member types.
17979     * NOTE that this might change in WXS 1.1; i.e. we will keep the union
17980     * types in WXS 1.1.
17981     */
17982     if ((type->memberTypes != NULL) &&
17983 	(xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1))
17984 	return(-1);
17985     /*
17986     * SPEC src-simple-type 1
17987     * "The corresponding simple type definition, if any, must satisfy
17988     * the conditions set out in Constraints on Simple Type Definition
17989     * Schema Components (�3.14.6)."
17990     */
17991     /*
17992     * Schema Component Constraint: Simple Type Definition Properties Correct
17993     * (st-props-correct)
17994     */
17995     res = xmlSchemaCheckSTPropsCorrect(pctxt, type);
17996     HFAILURE HERROR
17997     /*
17998     * Schema Component Constraint: Derivation Valid (Restriction, Simple)
17999     * (cos-st-restricts)
18000     */
18001     res = xmlSchemaCheckCOSSTRestricts(pctxt, type);
18002     HFAILURE HERROR
18003     /*
18004     * TODO: Removed the error report, since it got annoying to get an
18005     * extra error report, if anything failed until now.
18006     * Enable this if needed.
18007     *
18008     * xmlSchemaPErr(ctxt, type->node,
18009     *    XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
18010     *    "Simple type '%s' does not satisfy the constraints "
18011     *    "on simple type definitions.\n",
18012     *    type->name, NULL);
18013     */
18014     /*
18015     * Schema Component Constraint: Simple Type Restriction (Facets)
18016     * (st-restrict-facets)
18017     */
18018     res = xmlSchemaCheckFacetValues(type, pctxt);
18019     HFAILURE HERROR
18020     if ((type->facetSet != NULL) ||
18021 	(type->baseType->facetSet != NULL)) {
18022 	res = xmlSchemaDeriveAndValidateFacets(pctxt, type);
18023 	HFAILURE HERROR
18024     }
18025     /*
18026     * Whitespace value.
18027     */
18028     res = xmlSchemaTypeFixupWhitespace(type);
18029     HFAILURE HERROR
18030     xmlSchemaTypeFixupOptimFacets(type);
18031 
18032 exit_error:
18033 #ifdef DEBUG_TYPE
18034     xmlSchemaDebugFixedType(pctxt, type);
18035 #endif
18036     if (olderrs != pctxt->nberrors)
18037 	return(pctxt->err);
18038     return(0);
18039 
18040 exit_failure:
18041 #ifdef DEBUG_TYPE
18042     xmlSchemaDebugFixedType(pctxt, type);
18043 #endif
18044     return(-1);
18045 }
18046 
18047 static int
xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)18048 xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,
18049 			  xmlSchemaTypePtr type)
18050 {
18051     int res = 0, olderrs = pctxt->nberrors;
18052     xmlSchemaTypePtr baseType = type->baseType;
18053 
18054     if (! WXS_IS_TYPE_NOT_FIXED(type))
18055 	return(0);
18056     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18057     if (baseType == NULL) {
18058 	PERROR_INT("xmlSchemaFixupComplexType",
18059 	    "missing baseType");
18060 	goto exit_failure;
18061     }
18062     /*
18063     * Fixup the base type.
18064     */
18065     if (WXS_IS_TYPE_NOT_FIXED(baseType))
18066 	xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt);
18067     if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
18068 	/*
18069 	* Skip fixup if the base type is invalid.
18070 	* TODO: Generate a warning!
18071 	*/
18072 	return(0);
18073     }
18074     /*
18075     * This basically checks if the base type can be derived.
18076     */
18077     res = xmlSchemaCheckSRCCT(pctxt, type);
18078     HFAILURE HERROR
18079     /*
18080     * Fixup the content type.
18081     */
18082     if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
18083 	/*
18084 	* Corresponds to <complexType><simpleContent>...
18085 	*/
18086 	if ((WXS_IS_COMPLEX(baseType)) &&
18087 	    (baseType->contentTypeDef != NULL) &&
18088 	    (WXS_IS_RESTRICTION(type))) {
18089 	    xmlSchemaTypePtr contentBase, content;
18090 #ifdef ENABLE_NAMED_LOCALS
18091 	    char buf[30];
18092 	    const xmlChar *tmpname;
18093 #endif
18094 	    /*
18095 	    * SPEC (1) If <restriction> + base type is <complexType>,
18096 	    * "whose own {content type} is a simple type..."
18097 	    */
18098 	    if (type->contentTypeDef != NULL) {
18099 		/*
18100 		* SPEC (1.1) "the simple type definition corresponding to the
18101 		* <simpleType> among the [children] of <restriction> if there
18102 		* is one;"
18103 		* Note that this "<simpleType> among the [children]" was put
18104 		* into ->contentTypeDef during parsing.
18105 		*/
18106 		contentBase = type->contentTypeDef;
18107 		type->contentTypeDef = NULL;
18108 	    } else {
18109 		/*
18110 		* (1.2) "...otherwise (<restriction> has no <simpleType>
18111 		* among its [children]), the simple type definition which
18112 		* is the {content type} of the ... base type."
18113 		*/
18114 		contentBase = baseType->contentTypeDef;
18115 	    }
18116 	    /*
18117 	    * SPEC
18118 	    * "... a simple type definition which restricts the simple
18119 	    * type definition identified in clause 1.1 or clause 1.2
18120 	    * with a set of facet components"
18121 	    *
18122 	    * Create the anonymous simple type, which will be the content
18123 	    * type of the complex type.
18124 	    */
18125 #ifdef ENABLE_NAMED_LOCALS
18126 	    snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
18127 	    tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
18128 	    content = xmlSchemaAddType(pctxt, pctxt->schema,
18129 		XML_SCHEMA_TYPE_SIMPLE, tmpname, type->targetNamespace,
18130 		type->node, 0);
18131 #else
18132 	    content = xmlSchemaAddType(pctxt, pctxt->schema,
18133 		XML_SCHEMA_TYPE_SIMPLE, NULL, type->targetNamespace,
18134 		type->node, 0);
18135 #endif
18136 	    if (content == NULL)
18137 		goto exit_failure;
18138 	    /*
18139 	    * We will use the same node as for the <complexType>
18140 	    * to have it somehow anchored in the schema doc.
18141 	    */
18142 	    content->type = XML_SCHEMA_TYPE_SIMPLE;
18143 	    content->baseType = contentBase;
18144 	    /*
18145 	    * Move the facets, previously anchored on the
18146 	    * complexType during parsing.
18147 	    */
18148 	    content->facets = type->facets;
18149 	    type->facets = NULL;
18150 	    content->facetSet = type->facetSet;
18151 	    type->facetSet = NULL;
18152 
18153 	    type->contentTypeDef = content;
18154 	    if (WXS_IS_TYPE_NOT_FIXED(contentBase))
18155 		xmlSchemaTypeFixup(contentBase, ACTXT_CAST pctxt);
18156 	    /*
18157 	    * Fixup the newly created type. We don't need to check
18158 	    * for circularity here.
18159 	    */
18160 	    res = xmlSchemaFixupSimpleTypeStageOne(pctxt, content);
18161 	    HFAILURE HERROR
18162 	    res = xmlSchemaFixupSimpleTypeStageTwo(pctxt, content);
18163 	    HFAILURE HERROR
18164 
18165 	} else if ((WXS_IS_COMPLEX(baseType)) &&
18166 	    (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
18167 	    (WXS_IS_RESTRICTION(type))) {
18168 	    /*
18169 	    * SPEC (2) If <restriction> + base is a mixed <complexType> with
18170 	    * an emptiable particle, then a simple type definition which
18171 	    * restricts the <restriction>'s <simpleType> child.
18172 	    */
18173 	    if ((type->contentTypeDef == NULL) ||
18174 		(type->contentTypeDef->baseType == NULL)) {
18175 		/*
18176 		* TODO: Check if this ever happens.
18177 		*/
18178 		xmlSchemaPCustomErr(pctxt,
18179 		    XML_SCHEMAP_INTERNAL,
18180 		    WXS_BASIC_CAST type, NULL,
18181 		    "Internal error: xmlSchemaTypeFixup, "
18182 		    "complex type '%s': the <simpleContent><restriction> "
18183 		    "is missing a <simpleType> child, but was not catched "
18184 		    "by xmlSchemaCheckSRCCT()", type->name);
18185 		goto exit_failure;
18186 	    }
18187 	} else if ((WXS_IS_COMPLEX(baseType)) && WXS_IS_EXTENSION(type)) {
18188 	    /*
18189 	    * SPEC (3) If <extension> + base is <complexType> with
18190 	    * <simpleType> content, "...then the {content type} of that
18191 	    * complex type definition"
18192 	    */
18193 	    if (baseType->contentTypeDef == NULL) {
18194 		/*
18195 		* TODO: Check if this ever happens. xmlSchemaCheckSRCCT
18196 		* should have catched this already.
18197 		*/
18198 		xmlSchemaPCustomErr(pctxt,
18199 		    XML_SCHEMAP_INTERNAL,
18200 		    WXS_BASIC_CAST type, NULL,
18201 		    "Internal error: xmlSchemaTypeFixup, "
18202 		    "complex type '%s': the <extension>ed base type is "
18203 		    "a complex type with no simple content type",
18204 		    type->name);
18205 		goto exit_failure;
18206 	    }
18207 	    type->contentTypeDef = baseType->contentTypeDef;
18208 	} else if ((WXS_IS_SIMPLE(baseType)) && WXS_IS_EXTENSION(type)) {
18209 	    /*
18210 	    * SPEC (4) <extension> + base is <simpleType>
18211 	    * "... then that simple type definition"
18212 	    */
18213 	    type->contentTypeDef = baseType;
18214 	} else {
18215 	    /*
18216 	    * TODO: Check if this ever happens.
18217 	    */
18218 	    xmlSchemaPCustomErr(pctxt,
18219 		XML_SCHEMAP_INTERNAL,
18220 		WXS_BASIC_CAST type, NULL,
18221 		"Internal error: xmlSchemaTypeFixup, "
18222 		"complex type '%s' with <simpleContent>: unhandled "
18223 		"derivation case", type->name);
18224 	    goto exit_failure;
18225 	}
18226     } else {
18227 	int dummySequence = 0;
18228 	xmlSchemaParticlePtr particle =
18229 	    (xmlSchemaParticlePtr) type->subtypes;
18230 	/*
18231 	* Corresponds to <complexType><complexContent>...
18232 	*
18233 	* NOTE that the effective mixed was already set during parsing of
18234 	* <complexType> and <complexContent>; its flag value is
18235 	* XML_SCHEMAS_TYPE_MIXED.
18236 	*
18237 	* Compute the "effective content":
18238 	* (2.1.1) + (2.1.2) + (2.1.3)
18239 	*/
18240 	if ((particle == NULL) ||
18241 	    ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
18242 	    ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
18243 	    (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
18244 	    ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
18245 	    (particle->minOccurs == 0))) &&
18246 	    ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
18247 	    if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
18248 		/*
18249 		* SPEC (2.1.4) "If the �effective mixed� is true, then
18250 		* a particle whose properties are as follows:..."
18251 		*
18252 		* Empty sequence model group with
18253 		* minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
18254 		* NOTE that we sill assign it the <complexType> node to
18255 		* somehow anchor it in the doc.
18256 		*/
18257 		if ((particle == NULL) ||
18258 		    (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
18259 		    /*
18260 		    * Create the particle.
18261 		    */
18262 		    particle = xmlSchemaAddParticle(pctxt,
18263 			type->node, 1, 1);
18264 		    if (particle == NULL)
18265 			goto exit_failure;
18266 		    /*
18267 		    * Create the model group.
18268 		    */ /* URGENT TODO: avoid adding to pending items. */
18269 		    particle->children = (xmlSchemaTreeItemPtr)
18270 			xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18271 			XML_SCHEMA_TYPE_SEQUENCE, type->node);
18272 		    if (particle->children == NULL)
18273 			goto exit_failure;
18274 
18275 		    type->subtypes = (xmlSchemaTypePtr) particle;
18276 		}
18277 		dummySequence = 1;
18278 		type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18279 	    } else {
18280 		/*
18281 		* SPEC (2.1.5) "otherwise empty"
18282 		*/
18283 		type->contentType = XML_SCHEMA_CONTENT_EMPTY;
18284 	    }
18285 	} else {
18286 	    /*
18287 	    * SPEC (2.2) "otherwise the particle corresponding to the
18288 	    * <all>, <choice>, <group> or <sequence> among the
18289 	    * [children]."
18290 	    */
18291 	    type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18292 	}
18293 	/*
18294 	* Compute the "content type".
18295 	*/
18296 	if (WXS_IS_RESTRICTION(type)) {
18297 	    /*
18298 	    * SPEC (3.1) "If <restriction>..."
18299 	    * (3.1.1) + (3.1.2) */
18300 	    if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
18301 		if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18302 		    type->contentType = XML_SCHEMA_CONTENT_MIXED;
18303 	    }
18304 	} else {
18305 	    /*
18306 	    * SPEC (3.2) "If <extension>..."
18307 	    */
18308 	    if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18309 		/*
18310 		* SPEC (3.2.1)
18311 		* "If the �effective content� is empty, then the
18312 		*  {content type} of the [...] base ..."
18313 		*/
18314 		type->contentType = baseType->contentType;
18315 		type->subtypes = baseType->subtypes;
18316 		/*
18317 		* Fixes bug #347316:
18318 		* This is the case when the base type has a simple
18319 		* type definition as content.
18320 		*/
18321 		type->contentTypeDef = baseType->contentTypeDef;
18322 		/*
18323 		* NOTE that the effective mixed is ignored here.
18324 		*/
18325 	    } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18326 		/*
18327 		* SPEC (3.2.2)
18328 		*/
18329 		if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18330 		    type->contentType = XML_SCHEMA_CONTENT_MIXED;
18331 	    } else {
18332 		/*
18333 		* SPEC (3.2.3)
18334 		*/
18335 		if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18336 		    type->contentType = XML_SCHEMA_CONTENT_MIXED;
18337 		    /*
18338 		    * "A model group whose {compositor} is sequence and whose
18339 		    * {particles} are..."
18340 		    */
18341 		if ((WXS_TYPE_PARTICLE(type) != NULL) &&
18342 		    (WXS_TYPE_PARTICLE_TERM(type) != NULL) &&
18343 		    ((WXS_TYPE_PARTICLE_TERM(type))->type ==
18344 			XML_SCHEMA_TYPE_ALL))
18345 		{
18346 		    /*
18347 		    * SPEC cos-all-limited (1)
18348 		    */
18349 		    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18350 			/* TODO: error code */
18351 			XML_SCHEMAP_COS_ALL_LIMITED,
18352 			WXS_ITEM_NODE(type), NULL,
18353 			"The type has an 'all' model group in its "
18354 			"{content type} and thus cannot be derived from "
18355 			"a non-empty type, since this would produce a "
18356 			"'sequence' model group containing the 'all' "
18357 			"model group; 'all' model groups are not "
18358 			"allowed to appear inside other model groups",
18359 			NULL, NULL);
18360 
18361 		} else if ((WXS_TYPE_PARTICLE(baseType) != NULL) &&
18362 		    (WXS_TYPE_PARTICLE_TERM(baseType) != NULL) &&
18363 		    ((WXS_TYPE_PARTICLE_TERM(baseType))->type ==
18364 			XML_SCHEMA_TYPE_ALL))
18365 		{
18366 		    /*
18367 		    * SPEC cos-all-limited (1)
18368 		    */
18369 		    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18370 			/* TODO: error code */
18371 			XML_SCHEMAP_COS_ALL_LIMITED,
18372 			WXS_ITEM_NODE(type), NULL,
18373 			"A type cannot be derived by extension from a type "
18374 			"which has an 'all' model group in its "
18375 			"{content type}, since this would produce a "
18376 			"'sequence' model group containing the 'all' "
18377 			"model group; 'all' model groups are not "
18378 			"allowed to appear inside other model groups",
18379 			NULL, NULL);
18380 
18381 		} else if (! dummySequence) {
18382 		    xmlSchemaTreeItemPtr effectiveContent =
18383 			(xmlSchemaTreeItemPtr) type->subtypes;
18384 		    /*
18385 		    * Create the particle.
18386 		    */
18387 		    particle = xmlSchemaAddParticle(pctxt,
18388 			type->node, 1, 1);
18389 		    if (particle == NULL)
18390 			goto exit_failure;
18391 		    /*
18392 		    * Create the "sequence" model group.
18393 		    */
18394 		    particle->children = (xmlSchemaTreeItemPtr)
18395 			xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18396 			XML_SCHEMA_TYPE_SEQUENCE, type->node);
18397 		    if (particle->children == NULL)
18398 			goto exit_failure;
18399 		    WXS_TYPE_CONTENTTYPE(type) = (xmlSchemaTypePtr) particle;
18400 		    /*
18401 		    * SPEC "the particle of the {content type} of
18402 		    * the ... base ..."
18403 		    * Create a duplicate of the base type's particle
18404 		    * and assign its "term" to it.
18405 		    */
18406 		    particle->children->children =
18407 			(xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
18408 			type->node,
18409 			((xmlSchemaParticlePtr) type->subtypes)->minOccurs,
18410 			((xmlSchemaParticlePtr) type->subtypes)->maxOccurs);
18411 		    if (particle->children->children == NULL)
18412 			goto exit_failure;
18413 		    particle = (xmlSchemaParticlePtr)
18414 			particle->children->children;
18415 		    particle->children =
18416 			((xmlSchemaParticlePtr) baseType->subtypes)->children;
18417 		    /*
18418 		    * SPEC "followed by the �effective content�."
18419 		    */
18420 		    particle->next = effectiveContent;
18421 		    /*
18422 		    * This all will result in:
18423 		    * new-particle
18424 		    *   --> new-sequence(
18425 		    *         new-particle
18426 		    *           --> base-model,
18427 		    *         this-particle
18428 		    *	        --> this-model
18429 		    *	    )
18430 		    */
18431 		} else {
18432 		    /*
18433 		    * This is the case when there is already an empty
18434 		    * <sequence> with minOccurs==maxOccurs==1.
18435 		    * Just add the base types's content type.
18436 		    * NOTE that, although we miss to add an intermediate
18437 		    * <sequence>, this should produce no difference to
18438 		    * neither the regex compilation of the content model,
18439 		    * nor to the complex type contraints.
18440 		    */
18441 		    particle->children->children =
18442 			(xmlSchemaTreeItemPtr) baseType->subtypes;
18443 		}
18444 	    }
18445 	}
18446     }
18447     /*
18448     * Now fixup attribute uses:
18449     *   - expand attr. group references
18450     *     - intersect attribute wildcards
18451     *   - inherit attribute uses of the base type
18452     *   - inherit or union attr. wildcards if extending
18453     *   - apply attr. use prohibitions if restricting
18454     */
18455     res = xmlSchemaFixupTypeAttributeUses(pctxt, type);
18456     HFAILURE HERROR
18457     /*
18458     * Apply the complex type component constraints; this will not
18459     * check attributes, since this is done in
18460     * xmlSchemaFixupTypeAttributeUses().
18461     */
18462     res = xmlSchemaCheckCTComponent(pctxt, type);
18463     HFAILURE HERROR
18464 
18465 #ifdef DEBUG_TYPE
18466     xmlSchemaDebugFixedType(pctxt, type);
18467 #endif
18468     if (olderrs != pctxt->nberrors)
18469 	return(pctxt->err);
18470     else
18471 	return(0);
18472 
18473 exit_error:
18474     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18475 #ifdef DEBUG_TYPE
18476     xmlSchemaDebugFixedType(pctxt, type);
18477 #endif
18478     return(pctxt->err);
18479 
18480 exit_failure:
18481     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18482 #ifdef DEBUG_TYPE
18483     xmlSchemaDebugFixedType(pctxt, type);
18484 #endif
18485     return(-1);
18486 }
18487 
18488 
18489 /**
18490  * xmlSchemaTypeFixup:
18491  * @typeDecl:  the schema type definition
18492  * @ctxt:  the schema parser context
18493  *
18494  * Fixes the content model of the type.
18495  * URGENT TODO: We need an int result!
18496  */
18497 static int
xmlSchemaTypeFixup(xmlSchemaTypePtr type,xmlSchemaAbstractCtxtPtr actxt)18498 xmlSchemaTypeFixup(xmlSchemaTypePtr type,
18499                    xmlSchemaAbstractCtxtPtr actxt)
18500 {
18501     if (type == NULL)
18502         return(0);
18503     if (actxt->type != XML_SCHEMA_CTXT_PARSER) {
18504 	AERROR_INT("xmlSchemaTypeFixup",
18505 	    "this function needs a parser context");
18506 	return(-1);
18507     }
18508     if (! WXS_IS_TYPE_NOT_FIXED(type))
18509 	return(0);
18510     if (type->type == XML_SCHEMA_TYPE_COMPLEX)
18511 	return(xmlSchemaFixupComplexType(PCTXT_CAST actxt, type));
18512     else if (type->type == XML_SCHEMA_TYPE_SIMPLE)
18513 	return(xmlSchemaFixupSimpleTypeStageTwo(PCTXT_CAST actxt, type));
18514     return(0);
18515 }
18516 
18517 /**
18518  * xmlSchemaCheckFacet:
18519  * @facet:  the facet
18520  * @typeDecl:  the schema type definition
18521  * @pctxt:  the schema parser context or NULL
18522  * @name: the optional name of the type
18523  *
18524  * Checks and computes the values of facets.
18525  *
18526  * Returns 0 if valid, a positive error code if not valid and
18527  *         -1 in case of an internal or API error.
18528  */
18529 int
xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,xmlSchemaTypePtr typeDecl,xmlSchemaParserCtxtPtr pctxt,const xmlChar * name ATTRIBUTE_UNUSED)18530 xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
18531                     xmlSchemaTypePtr typeDecl,
18532                     xmlSchemaParserCtxtPtr pctxt,
18533 		    const xmlChar * name ATTRIBUTE_UNUSED)
18534 {
18535     int ret = 0, ctxtGiven;
18536 
18537     if ((facet == NULL) || (typeDecl == NULL))
18538         return(-1);
18539     /*
18540     * TODO: will the parser context be given if used from
18541     * the relaxNG module?
18542     */
18543     if (pctxt == NULL)
18544 	ctxtGiven = 0;
18545     else
18546 	ctxtGiven = 1;
18547 
18548     switch (facet->type) {
18549         case XML_SCHEMA_FACET_MININCLUSIVE:
18550         case XML_SCHEMA_FACET_MINEXCLUSIVE:
18551         case XML_SCHEMA_FACET_MAXINCLUSIVE:
18552         case XML_SCHEMA_FACET_MAXEXCLUSIVE:
18553 	case XML_SCHEMA_FACET_ENUMERATION: {
18554                 /*
18555                  * Okay we need to validate the value
18556                  * at that point.
18557                  */
18558 		xmlSchemaTypePtr base;
18559 
18560 		/* 4.3.5.5 Constraints on enumeration Schema Components
18561 		* Schema Component Constraint: enumeration valid restriction
18562 		* It is an �error� if any member of {value} is not in the
18563 		* �value space� of {base type definition}.
18564 		*
18565 		* minInclusive, maxInclusive, minExclusive, maxExclusive:
18566 		* The value �must� be in the
18567 		* �value space� of the �base type�.
18568 		*/
18569 		/*
18570 		* This function is intended to deliver a compiled value
18571 		* on the facet. In this implementation of XML Schemata the
18572 		* type holding a facet, won't be a built-in type.
18573 		* Thus to ensure that other API
18574 		* calls (relaxng) do work, if the given type is a built-in
18575 		* type, we will assume that the given built-in type *is
18576 		* already* the base type.
18577 		*/
18578 		if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
18579 		    base = typeDecl->baseType;
18580 		    if (base == NULL) {
18581 			PERROR_INT("xmlSchemaCheckFacet",
18582 			    "a type user derived type has no base type");
18583 			return (-1);
18584 		    }
18585 		} else
18586 		    base = typeDecl;
18587 
18588 		if (! ctxtGiven) {
18589 		    /*
18590 		    * A context is needed if called from RelaxNG.
18591 		    */
18592 		    pctxt = xmlSchemaNewParserCtxt("*");
18593 		    if (pctxt == NULL)
18594 			return (-1);
18595 		}
18596 		/*
18597 		* NOTE: This call does not check the content nodes,
18598 		* since they are not available:
18599 		* facet->node is just the node holding the facet
18600 		* definition, *not* the attribute holding the *value*
18601 		* of the facet.
18602 		*/
18603 		ret = xmlSchemaVCheckCVCSimpleType(
18604 		    ACTXT_CAST pctxt, facet->node, base,
18605 		    facet->value, &(facet->val), 1, 1, 0);
18606                 if (ret != 0) {
18607 		    if (ret < 0) {
18608 			/* No error message for RelaxNG. */
18609 			if (ctxtGiven) {
18610 			    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18611 				XML_SCHEMAP_INTERNAL, facet->node, NULL,
18612 				"Internal error: xmlSchemaCheckFacet, "
18613 				"failed to validate the value '%s' of the "
18614 				"facet '%s' against the base type",
18615 				facet->value, xmlSchemaFacetTypeToString(facet->type));
18616 			}
18617 			goto internal_error;
18618 		    }
18619 		    ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18620 		    /* No error message for RelaxNG. */
18621 		    if (ctxtGiven) {
18622 			xmlChar *str = NULL;
18623 
18624 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
18625 			    ret, facet->node, WXS_BASIC_CAST facet,
18626 			    "The value '%s' of the facet does not validate "
18627 			    "against the base type '%s'",
18628 			    facet->value,
18629 			    xmlSchemaFormatQName(&str,
18630 				base->targetNamespace, base->name));
18631 			FREE_AND_NULL(str);
18632 		    }
18633 		    goto exit;
18634                 } else if (facet->val == NULL) {
18635 		    if (ctxtGiven) {
18636 			PERROR_INT("xmlSchemaCheckFacet",
18637 			    "value was not computed");
18638 		    }
18639 		    TODO
18640 		}
18641                 break;
18642             }
18643         case XML_SCHEMA_FACET_PATTERN:
18644             facet->regexp = xmlRegexpCompile(facet->value);
18645             if (facet->regexp == NULL) {
18646 		ret = XML_SCHEMAP_REGEXP_INVALID;
18647 		/* No error message for RelaxNG. */
18648 		if (ctxtGiven) {
18649 		    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18650 			ret, facet->node, WXS_BASIC_CAST typeDecl,
18651 			"The value '%s' of the facet 'pattern' is not a "
18652 			"valid regular expression",
18653 			facet->value, NULL);
18654 		}
18655             }
18656             break;
18657         case XML_SCHEMA_FACET_TOTALDIGITS:
18658         case XML_SCHEMA_FACET_FRACTIONDIGITS:
18659         case XML_SCHEMA_FACET_LENGTH:
18660         case XML_SCHEMA_FACET_MAXLENGTH:
18661         case XML_SCHEMA_FACET_MINLENGTH:
18662 
18663 	    if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
18664 		ret = xmlSchemaValidatePredefinedType(
18665 		    xmlSchemaGetBuiltInType(XML_SCHEMAS_PINTEGER),
18666 		    facet->value, &(facet->val));
18667 	    } else {
18668 		ret = xmlSchemaValidatePredefinedType(
18669 		    xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
18670 		    facet->value, &(facet->val));
18671 	    }
18672 	    if (ret != 0) {
18673 		if (ret < 0) {
18674 		    /* No error message for RelaxNG. */
18675 		    if (ctxtGiven) {
18676 			PERROR_INT("xmlSchemaCheckFacet",
18677 			    "validating facet value");
18678 		    }
18679 		    goto internal_error;
18680 		}
18681 		ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18682 		/* No error message for RelaxNG. */
18683 		if (ctxtGiven) {
18684 		    /* error code */
18685 		    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
18686 			ret, facet->node, WXS_BASIC_CAST typeDecl,
18687 			"The value '%s' of the facet '%s' is not a valid '%s'",
18688 			facet->value,
18689 			xmlSchemaFacetTypeToString(facet->type),
18690 			(facet->type != XML_SCHEMA_FACET_TOTALDIGITS) ?
18691 			    BAD_CAST "nonNegativeInteger" :
18692 			    BAD_CAST "positiveInteger",
18693 			NULL);
18694 		}
18695 	    }
18696 	    break;
18697 
18698         case XML_SCHEMA_FACET_WHITESPACE:{
18699                 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
18700                     facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
18701                 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
18702                     facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
18703                 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
18704                     facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
18705                 } else {
18706 		    ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18707                     /* No error message for RelaxNG. */
18708 		    if (ctxtGiven) {
18709 			/* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
18710 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
18711 			    ret, facet->node, WXS_BASIC_CAST typeDecl,
18712 			    "The value '%s' of the facet 'whitespace' is not "
18713 			    "valid", facet->value, NULL);
18714                     }
18715                 }
18716             }
18717         default:
18718             break;
18719     }
18720 exit:
18721     if ((! ctxtGiven) && (pctxt != NULL))
18722 	xmlSchemaFreeParserCtxt(pctxt);
18723     return (ret);
18724 internal_error:
18725     if ((! ctxtGiven) && (pctxt != NULL))
18726 	xmlSchemaFreeParserCtxt(pctxt);
18727     return (-1);
18728 }
18729 
18730 /**
18731  * xmlSchemaCheckFacetValues:
18732  * @typeDecl:  the schema type definition
18733  * @ctxt:  the schema parser context
18734  *
18735  * Checks the default values types, especially for facets
18736  */
18737 static int
xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,xmlSchemaParserCtxtPtr pctxt)18738 xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
18739 			  xmlSchemaParserCtxtPtr pctxt)
18740 {
18741     int res, olderrs = pctxt->nberrors;
18742     const xmlChar *name = typeDecl->name;
18743     /*
18744     * NOTE: It is intended to use the facets list, instead
18745     * of facetSet.
18746     */
18747     if (typeDecl->facets != NULL) {
18748 	xmlSchemaFacetPtr facet = typeDecl->facets;
18749 
18750 	/*
18751 	* Temporarily assign the "schema" to the validation context
18752 	* of the parser context. This is needed for NOTATION validation.
18753 	*/
18754 	if (pctxt->vctxt == NULL) {
18755 	    if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1)
18756 		return(-1);
18757 	}
18758 	pctxt->vctxt->schema = pctxt->schema;
18759 	while (facet != NULL) {
18760 	    res = xmlSchemaCheckFacet(facet, typeDecl, pctxt, name);
18761 	    HFAILURE
18762 	    facet = facet->next;
18763 	}
18764 	pctxt->vctxt->schema = NULL;
18765     }
18766     if (olderrs != pctxt->nberrors)
18767 	return(pctxt->err);
18768     return(0);
18769 exit_failure:
18770     return(-1);
18771 }
18772 
18773 /**
18774  * xmlSchemaGetCircModelGrDefRef:
18775  * @ctxtMGroup: the searched model group
18776  * @selfMGroup: the second searched model group
18777  * @particle: the first particle
18778  *
18779  * This one is intended to be used by
18780  * xmlSchemaCheckGroupDefCircular only.
18781  *
18782  * Returns the particle with the circular model group definition reference,
18783  * otherwise NULL.
18784  */
18785 static xmlSchemaTreeItemPtr
xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,xmlSchemaTreeItemPtr particle)18786 xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
18787 			      xmlSchemaTreeItemPtr particle)
18788 {
18789     xmlSchemaTreeItemPtr circ = NULL;
18790     xmlSchemaTreeItemPtr term;
18791     xmlSchemaModelGroupDefPtr gdef;
18792 
18793     for (; particle != NULL; particle = particle->next) {
18794 	term = particle->children;
18795 	if (term == NULL)
18796 	    continue;
18797 	switch (term->type) {
18798 	    case XML_SCHEMA_TYPE_GROUP:
18799 		gdef = (xmlSchemaModelGroupDefPtr) term;
18800 		if (gdef == groupDef)
18801 		    return (particle);
18802 		/*
18803 		* Mark this model group definition to avoid infinite
18804 		* recursion on circular references not yet examined.
18805 		*/
18806 		if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
18807 		    continue;
18808 		if (gdef->children != NULL) {
18809 		    gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18810 		    circ = xmlSchemaGetCircModelGrDefRef(groupDef,
18811 			gdef->children->children);
18812 		    gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18813 		    if (circ != NULL)
18814 			return (circ);
18815 		}
18816 		break;
18817 	    case XML_SCHEMA_TYPE_SEQUENCE:
18818 	    case XML_SCHEMA_TYPE_CHOICE:
18819 	    case XML_SCHEMA_TYPE_ALL:
18820 		circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
18821 		if (circ != NULL)
18822 		    return (circ);
18823 		break;
18824 	    default:
18825 		break;
18826 	}
18827     }
18828     return (NULL);
18829 }
18830 
18831 /**
18832  * xmlSchemaCheckGroupDefCircular:
18833  * @item:  the model group definition
18834  * @ctxt:  the parser context
18835  * @name:  the name
18836  *
18837  * Checks for circular references to model group definitions.
18838  */
18839 static void
xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,xmlSchemaParserCtxtPtr ctxt)18840 xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
18841 			       xmlSchemaParserCtxtPtr ctxt)
18842 {
18843     /*
18844     * Schema Component Constraint: Model Group Correct
18845     * 2 Circular groups are disallowed. That is, within the {particles}
18846     * of a group there must not be at any depth a particle whose {term}
18847     * is the group itself.
18848     */
18849     if ((item == NULL) ||
18850 	(item->type != XML_SCHEMA_TYPE_GROUP) ||
18851 	(item->children == NULL))
18852 	return;
18853     {
18854 	xmlSchemaTreeItemPtr circ;
18855 
18856 	circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
18857 	if (circ != NULL) {
18858 	    xmlChar *str = NULL;
18859 	    /*
18860 	    * TODO: The error report is not adequate: this constraint
18861 	    * is defined for model groups but not definitions, but since
18862 	    * there cannot be any circular model groups without a model group
18863 	    * definition (if not using a construction API), we check those
18864 	    * defintions only.
18865 	    */
18866 	    xmlSchemaPCustomErr(ctxt,
18867 		XML_SCHEMAP_MG_PROPS_CORRECT_2,
18868 		NULL, WXS_ITEM_NODE(circ),
18869 		"Circular reference to the model group definition '%s' "
18870 		"defined", xmlSchemaFormatQName(&str,
18871 		    item->targetNamespace, item->name));
18872 	    FREE_AND_NULL(str)
18873 	    /*
18874 	    * NOTE: We will cut the reference to avoid further
18875 	    * confusion of the processor. This is a fatal error.
18876 	    */
18877 	    circ->children = NULL;
18878 	}
18879     }
18880 }
18881 
18882 /**
18883  * xmlSchemaModelGroupToModelGroupDefFixup:
18884  * @ctxt:  the parser context
18885  * @mg:  the model group
18886  *
18887  * Assigns the model group of model group definitions to the "term"
18888  * of the referencing particle.
18889  * In xmlSchemaResolveModelGroupParticleReferences the model group
18890  * definitions were assigned to the "term", since needed for the
18891  * circularity check.
18892  *
18893  * Schema Component Constraint:
18894  *     All Group Limited (cos-all-limited) (1.2)
18895  */
18896 static void
xmlSchemaModelGroupToModelGroupDefFixup(xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,xmlSchemaModelGroupPtr mg)18897 xmlSchemaModelGroupToModelGroupDefFixup(
18898     xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
18899     xmlSchemaModelGroupPtr mg)
18900 {
18901     xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
18902 
18903     while (particle != NULL) {
18904 	if ((WXS_PARTICLE_TERM(particle) == NULL) ||
18905 	    ((WXS_PARTICLE_TERM(particle))->type !=
18906 		XML_SCHEMA_TYPE_GROUP))
18907 	{
18908 	    particle = WXS_PTC_CAST particle->next;
18909 	    continue;
18910 	}
18911 	if (WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle)) == NULL) {
18912 	    /*
18913 	    * TODO: Remove the particle.
18914 	    */
18915 	    WXS_PARTICLE_TERM(particle) = NULL;
18916 	    particle = WXS_PTC_CAST particle->next;
18917 	    continue;
18918 	}
18919 	/*
18920 	* Assign the model group to the {term} of the particle.
18921 	*/
18922 	WXS_PARTICLE_TERM(particle) =
18923 	    WXS_TREE_CAST WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle));
18924 
18925 	particle = WXS_PTC_CAST particle->next;
18926     }
18927 }
18928 
18929 /**
18930  * xmlSchemaCheckAttrGroupCircularRecur:
18931  * @ctxtGr: the searched attribute group
18932  * @attr: the current attribute list to be processed
18933  *
18934  * This one is intended to be used by
18935  * xmlSchemaCheckAttrGroupCircular only.
18936  *
18937  * Returns the circular attribute grou reference, otherwise NULL.
18938  */
18939 static xmlSchemaQNameRefPtr
xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,xmlSchemaItemListPtr list)18940 xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,
18941 				     xmlSchemaItemListPtr list)
18942 {
18943     xmlSchemaAttributeGroupPtr gr;
18944     xmlSchemaQNameRefPtr ref, circ;
18945     int i;
18946     /*
18947     * We will search for an attribute group reference which
18948     * references the context attribute group.
18949     */
18950     for (i = 0; i < list->nbItems; i++) {
18951 	ref = list->items[i];
18952 	if ((ref->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
18953 	    (ref->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
18954 	    (ref->item != NULL))
18955 	{
18956 	    gr = WXS_ATTR_GROUP_CAST ref->item;
18957 	    if (gr == ctxtGr)
18958 		return(ref);
18959 	    if (gr->flags & XML_SCHEMAS_ATTRGROUP_MARKED)
18960 		continue;
18961 	    /*
18962 	    * Mark as visited to avoid infinite recursion on
18963 	    * circular references not yet examined.
18964 	    */
18965 	    if ((gr->attrUses) &&
18966 		(gr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS))
18967 	    {
18968 		gr->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
18969 		circ = xmlSchemaCheckAttrGroupCircularRecur(ctxtGr,
18970 		    (xmlSchemaItemListPtr) gr->attrUses);
18971 		gr->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
18972 		if (circ != NULL)
18973 		    return (circ);
18974 	    }
18975 
18976 	}
18977     }
18978     return (NULL);
18979 }
18980 
18981 /**
18982  * xmlSchemaCheckAttrGroupCircular:
18983  * attrGr:  the attribute group definition
18984  * @ctxt:  the parser context
18985  * @name:  the name
18986  *
18987  * Checks for circular references of attribute groups.
18988  */
18989 static int
xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,xmlSchemaParserCtxtPtr ctxt)18990 xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
18991 				xmlSchemaParserCtxtPtr ctxt)
18992 {
18993     /*
18994     * Schema Representation Constraint:
18995     * Attribute Group Definition Representation OK
18996     * 3 Circular group reference is disallowed outside <redefine>.
18997     * That is, unless this element information item's parent is
18998     * <redefine>, then among the [children], if any, there must
18999     * not be an <attributeGroup> with ref [attribute] which resolves
19000     * to the component corresponding to this <attributeGroup>. Indirect
19001     * circularity is also ruled out. That is, when QName resolution
19002     * (Schema Document) (�3.15.3) is applied to a �QName� arising from
19003     * any <attributeGroup>s with a ref [attribute] among the [children],
19004     * it must not be the case that a �QName� is encountered at any depth
19005     * which resolves to the component corresponding to this <attributeGroup>.
19006     */
19007     if (attrGr->attrUses == NULL)
19008 	return(0);
19009     else if ((attrGr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS) == 0)
19010 	return(0);
19011     else {
19012 	xmlSchemaQNameRefPtr circ;
19013 
19014 	circ = xmlSchemaCheckAttrGroupCircularRecur(attrGr,
19015 	    (xmlSchemaItemListPtr) attrGr->attrUses);
19016 	if (circ != NULL) {
19017 	    xmlChar *str = NULL;
19018 	    /*
19019 	    * TODO: Report the referenced attr group as QName.
19020 	    */
19021 	    xmlSchemaPCustomErr(ctxt,
19022 		XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
19023 		NULL, WXS_ITEM_NODE(WXS_BASIC_CAST circ),
19024 		"Circular reference to the attribute group '%s' "
19025 		"defined", xmlSchemaGetComponentQName(&str, attrGr));
19026 	    FREE_AND_NULL(str);
19027 	    /*
19028 	    * NOTE: We will cut the reference to avoid further
19029 	    * confusion of the processor.
19030 	    * BADSPEC TODO: The spec should define how to process in this case.
19031 	    */
19032 	    circ->item = NULL;
19033 	    return(ctxt->err);
19034 	}
19035     }
19036     return(0);
19037 }
19038 
19039 static int
19040 xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19041 				  xmlSchemaAttributeGroupPtr attrGr);
19042 
19043 /**
19044  * xmlSchemaExpandAttributeGroupRefs:
19045  * @pctxt: the parser context
19046  * @node: the node of the component holding the attribute uses
19047  * @completeWild: the intersected wildcard to be returned
19048  * @list: the attribute uses
19049  *
19050  * Substitutes contained attribute group references
19051  * for their attribute uses. Wilcards are intersected.
19052  * Attribute use prohibitions are removed from the list
19053  * and returned via the @prohibs list.
19054  * Pointlessness of attr. prohibs, if a matching attr. decl
19055  * is existent a well, are checked.
19056  */
19057 static int
xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBasicItemPtr item,xmlSchemaWildcardPtr * completeWild,xmlSchemaItemListPtr list,xmlSchemaItemListPtr prohibs)19058 xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
19059 				  xmlSchemaBasicItemPtr item,
19060 				  xmlSchemaWildcardPtr *completeWild,
19061 				  xmlSchemaItemListPtr list,
19062 				  xmlSchemaItemListPtr prohibs)
19063 {
19064     xmlSchemaAttributeGroupPtr gr;
19065     xmlSchemaAttributeUsePtr use;
19066     xmlSchemaItemListPtr sublist;
19067     int i, j;
19068     int created = (*completeWild == NULL) ? 0 : 1;
19069 
19070     if (prohibs)
19071 	prohibs->nbItems = 0;
19072 
19073     for (i = 0; i < list->nbItems; i++) {
19074 	use = list->items[i];
19075 
19076 	if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
19077 	    if (prohibs == NULL) {
19078 		PERROR_INT("xmlSchemaExpandAttributeGroupRefs",
19079 		    "unexpected attr prohibition found");
19080 		return(-1);
19081 	    }
19082 	    /*
19083 	    * Remove from attribute uses.
19084 	    */
19085 	    if (xmlSchemaItemListRemove(list, i) == -1)
19086 		return(-1);
19087 	    i--;
19088 	    /*
19089 	    * Note that duplicate prohibitions were already
19090 	    * handled at parsing time.
19091 	    */
19092 	    /*
19093 	    * Add to list of prohibitions.
19094 	    */
19095 	    xmlSchemaItemListAddSize(prohibs, 2, use);
19096 	    continue;
19097 	}
19098 	if ((use->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19099 	    ((WXS_QNAME_CAST use)->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP))
19100 	{
19101 	    if ((WXS_QNAME_CAST use)->item == NULL)
19102 		return(-1);
19103 	    gr = WXS_ATTR_GROUP_CAST (WXS_QNAME_CAST use)->item;
19104 	    /*
19105 	    * Expand the referenced attr. group.
19106 	    * TODO: remove this, this is done in a previous step, so
19107 	    * already done here.
19108 	    */
19109 	    if ((gr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
19110 		if (xmlSchemaAttributeGroupExpandRefs(pctxt, gr) == -1)
19111 		    return(-1);
19112 	    }
19113 	    /*
19114 	    * Build the 'complete' wildcard; i.e. intersect multiple
19115 	    * wildcards.
19116 	    */
19117 	    if (gr->attributeWildcard != NULL) {
19118 		if (*completeWild == NULL) {
19119 		    *completeWild = gr->attributeWildcard;
19120 		} else {
19121 		    if (! created) {
19122 			xmlSchemaWildcardPtr tmpWild;
19123 
19124 			 /*
19125 			* Copy the first encountered wildcard as context,
19126 			* except for the annotation.
19127 			*
19128 			* Although the complete wildcard might not correspond
19129 			* to any node in the schema, we will anchor it on
19130 			* the node of the owner component.
19131 			*/
19132 			tmpWild =  xmlSchemaAddWildcard(pctxt, pctxt->schema,
19133 			    XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
19134 			    WXS_ITEM_NODE(item));
19135 			if (tmpWild == NULL)
19136 			    return(-1);
19137 			if (xmlSchemaCloneWildcardNsConstraints(pctxt,
19138 			    tmpWild, *completeWild) == -1)
19139 			    return (-1);
19140 			tmpWild->processContents = (*completeWild)->processContents;
19141 			*completeWild = tmpWild;
19142 			created = 1;
19143 		    }
19144 
19145 		    if (xmlSchemaIntersectWildcards(pctxt, *completeWild,
19146 			gr->attributeWildcard) == -1)
19147 			return(-1);
19148 		}
19149 	    }
19150 	    /*
19151 	    * Just remove the reference if the referenced group does not
19152 	    * contain any attribute uses.
19153 	    */
19154 	    sublist = ((xmlSchemaItemListPtr) gr->attrUses);
19155 	    if ((sublist == NULL) || sublist->nbItems == 0) {
19156 		if (xmlSchemaItemListRemove(list, i) == -1)
19157 		    return(-1);
19158 		i--;
19159 		continue;
19160 	    }
19161 	    /*
19162 	    * Add the attribute uses.
19163 	    */
19164 	    list->items[i] = sublist->items[0];
19165 	    if (sublist->nbItems != 1) {
19166 		for (j = 1; j < sublist->nbItems; j++) {
19167 		    i++;
19168 		    if (xmlSchemaItemListInsert(list,
19169 			    sublist->items[j], i) == -1)
19170 			return(-1);
19171 		}
19172 	    }
19173 	}
19174 
19175     }
19176     /*
19177     * Handle pointless prohibitions of declared attributes.
19178     */
19179     if (prohibs && (prohibs->nbItems != 0) && (list->nbItems != 0)) {
19180 	xmlSchemaAttributeUseProhibPtr prohib;
19181 
19182 	for (i = prohibs->nbItems -1; i >= 0; i--) {
19183 	    prohib = prohibs->items[i];
19184 	    for (j = 0; j < list->nbItems; j++) {
19185 		use = list->items[j];
19186 
19187 		if ((prohib->name == WXS_ATTRUSE_DECL_NAME(use)) &&
19188 		    (prohib->targetNamespace == WXS_ATTRUSE_DECL_TNS(use)))
19189 		{
19190 		    xmlChar *str = NULL;
19191 
19192 		    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
19193 			XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
19194 			prohib->node, NULL,
19195 			"Skipping pointless attribute use prohibition "
19196 			"'%s', since a corresponding attribute use "
19197 			"exists already in the type definition",
19198 			xmlSchemaFormatQName(&str,
19199 			    prohib->targetNamespace, prohib->name),
19200 			NULL, NULL);
19201 		    FREE_AND_NULL(str);
19202 		    /*
19203 		    * Remove the prohibition.
19204 		    */
19205 		    if (xmlSchemaItemListRemove(prohibs, i) == -1)
19206 			return(-1);
19207 		    break;
19208 		}
19209 	    }
19210 	}
19211     }
19212     return(0);
19213 }
19214 
19215 /**
19216  * xmlSchemaAttributeGroupExpandRefs:
19217  * @pctxt:  the parser context
19218  * @attrGr:  the attribute group definition
19219  *
19220  * Computation of:
19221  * {attribute uses} property
19222  * {attribute wildcard} property
19223  *
19224  * Substitutes contained attribute group references
19225  * for their attribute uses. Wilcards are intersected.
19226  */
19227 static int
xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,xmlSchemaAttributeGroupPtr attrGr)19228 xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19229 				  xmlSchemaAttributeGroupPtr attrGr)
19230 {
19231     if ((attrGr->attrUses == NULL) ||
19232 	(attrGr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED))
19233 	return(0);
19234 
19235     attrGr->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
19236     if (xmlSchemaExpandAttributeGroupRefs(pctxt, WXS_BASIC_CAST attrGr,
19237 	&(attrGr->attributeWildcard), attrGr->attrUses, NULL) == -1)
19238 	return(-1);
19239     return(0);
19240 }
19241 
19242 /**
19243  * xmlSchemaAttributeGroupExpandRefs:
19244  * @pctxt:  the parser context
19245  * @attrGr:  the attribute group definition
19246  *
19247  * Substitutes contained attribute group references
19248  * for their attribute uses. Wilcards are intersected.
19249  *
19250  * Schema Component Constraint:
19251  *    Attribute Group Definition Properties Correct (ag-props-correct)
19252  */
19253 static int
xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,xmlSchemaAttributeGroupPtr attrGr)19254 xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19255 				  xmlSchemaAttributeGroupPtr attrGr)
19256 {
19257     /*
19258     * SPEC ag-props-correct
19259     * (1) "The values of the properties of an attribute group definition
19260     * must be as described in the property tableau in The Attribute
19261     * Group Definition Schema Component (�3.6.1), modulo the impact of
19262     * Missing Sub-components (�5.3);"
19263     */
19264 
19265     if ((attrGr->attrUses != NULL) &&
19266 	(WXS_LIST_CAST attrGr->attrUses)->nbItems > 1)
19267     {
19268 	xmlSchemaItemListPtr uses = WXS_LIST_CAST attrGr->attrUses;
19269 	xmlSchemaAttributeUsePtr use, tmp;
19270 	int i, j, hasId = 0;
19271 
19272 	for (i = uses->nbItems -1; i >= 0; i--) {
19273 	    use = uses->items[i];
19274 	    /*
19275 	    * SPEC ag-props-correct
19276 	    * (2) "Two distinct members of the {attribute uses} must not have
19277 	    * {attribute declaration}s both of whose {name}s match and whose
19278 	    * {target namespace}s are identical."
19279 	    */
19280 	    if (i > 0) {
19281 		for (j = i -1; j >= 0; j--) {
19282 		    tmp = uses->items[j];
19283 		    if ((WXS_ATTRUSE_DECL_NAME(use) ==
19284 			WXS_ATTRUSE_DECL_NAME(tmp)) &&
19285 			(WXS_ATTRUSE_DECL_TNS(use) ==
19286 			WXS_ATTRUSE_DECL_TNS(tmp)))
19287 		    {
19288 			xmlChar *str = NULL;
19289 
19290 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
19291 			    XML_SCHEMAP_AG_PROPS_CORRECT,
19292 			    attrGr->node, WXS_BASIC_CAST attrGr,
19293 			    "Duplicate %s",
19294 			    xmlSchemaGetComponentDesignation(&str, use),
19295 			    NULL);
19296 			FREE_AND_NULL(str);
19297 			/*
19298 			* Remove the duplicate.
19299 			*/
19300 			if (xmlSchemaItemListRemove(uses, i) == -1)
19301 			    return(-1);
19302 			goto next_use;
19303 		    }
19304 		}
19305 	    }
19306 	    /*
19307 	    * SPEC ag-props-correct
19308 	    * (3) "Two distinct members of the {attribute uses} must not have
19309 	    * {attribute declaration}s both of whose {type definition}s are or
19310 	    * are derived from ID."
19311 	    * TODO: Does 'derived' include member-types of unions?
19312 	    */
19313 	    if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
19314 		if (xmlSchemaIsDerivedFromBuiltInType(
19315 		    WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
19316 		{
19317 		    if (hasId) {
19318 			xmlChar *str = NULL;
19319 
19320 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
19321 			    XML_SCHEMAP_AG_PROPS_CORRECT,
19322 			    attrGr->node, WXS_BASIC_CAST attrGr,
19323 			    "There must not exist more than one attribute "
19324 			    "declaration of type 'xs:ID' "
19325 			    "(or derived from 'xs:ID'). The %s violates this "
19326 			    "constraint",
19327 			    xmlSchemaGetComponentDesignation(&str, use),
19328 			    NULL);
19329 			FREE_AND_NULL(str);
19330 			if (xmlSchemaItemListRemove(uses, i) == -1)
19331 			    return(-1);
19332 		    }
19333 		    hasId = 1;
19334 		}
19335 	    }
19336 next_use: {}
19337 	}
19338     }
19339     return(0);
19340 }
19341 
19342 /**
19343  * xmlSchemaResolveAttrGroupReferences:
19344  * @attrgrpDecl:  the schema attribute definition
19345  * @ctxt:  the schema parser context
19346  * @name:  the attribute name
19347  *
19348  * Resolves references to attribute group definitions.
19349  */
19350 static int
xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,xmlSchemaParserCtxtPtr ctxt)19351 xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,
19352 				    xmlSchemaParserCtxtPtr ctxt)
19353 {
19354     xmlSchemaAttributeGroupPtr group;
19355 
19356     if (ref->item != NULL)
19357         return(0);
19358     group = xmlSchemaGetAttributeGroup(ctxt->schema,
19359 	ref->name,
19360 	ref->targetNamespace);
19361     if (group == NULL) {
19362 	xmlSchemaPResCompAttrErr(ctxt,
19363 	    XML_SCHEMAP_SRC_RESOLVE,
19364 	    NULL, ref->node,
19365 	    "ref", ref->name, ref->targetNamespace,
19366 	    ref->itemType, NULL);
19367 	return(ctxt->err);
19368     }
19369     ref->item = WXS_BASIC_CAST group;
19370     return(0);
19371 }
19372 
19373 /**
19374  * xmlSchemaCheckAttrPropsCorrect:
19375  * @item:  an schema attribute declaration/use
19376  * @ctxt:  a schema parser context
19377  * @name:  the name of the attribute
19378  *
19379  *
19380  * Schema Component Constraint:
19381  *    Attribute Declaration Properties Correct (a-props-correct)
19382  *
19383  * Validates the value constraints of an attribute declaration/use.
19384  * NOTE that this needs the simle type definitions to be already
19385  *   builded and checked.
19386  */
19387 static int
xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,xmlSchemaAttributePtr attr)19388 xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19389 			       xmlSchemaAttributePtr attr)
19390 {
19391 
19392     /*
19393     * SPEC a-props-correct (1)
19394     * "The values of the properties of an attribute declaration must
19395     * be as described in the property tableau in The Attribute
19396     * Declaration Schema Component (�3.2.1), modulo the impact of
19397     * Missing Sub-components (�5.3)."
19398     */
19399 
19400     if (WXS_ATTR_TYPEDEF(attr) == NULL)
19401 	return(0);
19402 
19403     if (attr->defValue != NULL) {
19404 	int ret;
19405 
19406 	/*
19407 	* SPEC a-props-correct (3)
19408 	* "If the {type definition} is or is derived from ID then there
19409 	* must not be a {value constraint}."
19410 	*/
19411 	if (xmlSchemaIsDerivedFromBuiltInType(
19412 	    WXS_ATTR_TYPEDEF(attr), XML_SCHEMAS_ID))
19413 	{
19414 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
19415 		XML_SCHEMAP_A_PROPS_CORRECT_3,
19416 		NULL, WXS_BASIC_CAST attr,
19417 		"Value constraints are not allowed if the type definition "
19418 		"is or is derived from xs:ID",
19419 		NULL, NULL);
19420 	    return(pctxt->err);
19421 	}
19422 	/*
19423 	* SPEC a-props-correct (2)
19424 	* "if there is a {value constraint}, the canonical lexical
19425 	* representation of its value must be �valid� with respect
19426 	* to the {type definition} as defined in String Valid (�3.14.4)."
19427 	* TODO: Don't care about the *cononical* stuff here, this requirement
19428 	* will be removed in WXS 1.1 anyway.
19429 	*/
19430 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt,
19431 	    attr->node, WXS_ATTR_TYPEDEF(attr),
19432 	    attr->defValue, &(attr->defVal),
19433 	    1, 1, 0);
19434 	if (ret != 0) {
19435 	    if (ret < 0) {
19436 		PERROR_INT("xmlSchemaCheckAttrPropsCorrect",
19437 		    "calling xmlSchemaVCheckCVCSimpleType()");
19438 		return(-1);
19439 	    }
19440 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
19441 		XML_SCHEMAP_A_PROPS_CORRECT_2,
19442 		NULL, WXS_BASIC_CAST attr,
19443 		"The value of the value constraint is not valid",
19444 		NULL, NULL);
19445 	    return(pctxt->err);
19446 	}
19447     }
19448 
19449     return(0);
19450 }
19451 
19452 static xmlSchemaElementPtr
xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,xmlSchemaElementPtr ancestor)19453 xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
19454 				 xmlSchemaElementPtr ancestor)
19455 {
19456     xmlSchemaElementPtr ret;
19457 
19458     if (WXS_SUBST_HEAD(ancestor) == NULL)
19459 	return (NULL);
19460     if (WXS_SUBST_HEAD(ancestor) == elemDecl)
19461 	return (ancestor);
19462 
19463     if (WXS_SUBST_HEAD(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
19464 	return (NULL);
19465     WXS_SUBST_HEAD(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
19466     ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
19467 	WXS_SUBST_HEAD(ancestor));
19468     WXS_SUBST_HEAD(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
19469 
19470     return (ret);
19471 }
19472 
19473 /**
19474  * xmlSchemaCheckElemPropsCorrect:
19475  * @ctxt:  a schema parser context
19476  * @decl: the element declaration
19477  * @name:  the name of the attribute
19478  *
19479  * Schema Component Constraint:
19480  * Element Declaration Properties Correct (e-props-correct)
19481  *
19482  * STATUS:
19483  *   missing: (6)
19484  */
19485 static int
xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,xmlSchemaElementPtr elemDecl)19486 xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19487 			       xmlSchemaElementPtr elemDecl)
19488 {
19489     int ret = 0;
19490     xmlSchemaTypePtr typeDef = WXS_ELEM_TYPEDEF(elemDecl);
19491     /*
19492     * SPEC (1) "The values of the properties of an element declaration
19493     * must be as described in the property tableau in The Element
19494     * Declaration Schema Component (�3.3.1), modulo the impact of Missing
19495     * Sub-components (�5.3)."
19496     */
19497     if (WXS_SUBST_HEAD(elemDecl) != NULL) {
19498 	xmlSchemaElementPtr head = WXS_SUBST_HEAD(elemDecl), circ;
19499 
19500 	xmlSchemaCheckElementDeclComponent(head, pctxt);
19501 	/*
19502 	* SPEC (3) "If there is a non-�absent� {substitution group
19503 	* affiliation}, then {scope} must be global."
19504 	*/
19505 	if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
19506 	    xmlSchemaPCustomErr(pctxt,
19507 		XML_SCHEMAP_E_PROPS_CORRECT_3,
19508 		WXS_BASIC_CAST elemDecl, NULL,
19509 		"Only global element declarations can have a "
19510 		"substitution group affiliation", NULL);
19511 	    ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
19512 	}
19513 	/*
19514 	* TODO: SPEC (6) "Circular substitution groups are disallowed.
19515 	* That is, it must not be possible to return to an element declaration
19516 	* by repeatedly following the {substitution group affiliation}
19517 	* property."
19518 	*/
19519 	if (head == elemDecl)
19520 	    circ = head;
19521 	else if (WXS_SUBST_HEAD(head) != NULL)
19522 	    circ = xmlSchemaCheckSubstGroupCircular(head, head);
19523 	else
19524 	    circ = NULL;
19525 	if (circ != NULL) {
19526 	    xmlChar *strA = NULL, *strB = NULL;
19527 
19528 	    xmlSchemaPCustomErrExt(pctxt,
19529 		XML_SCHEMAP_E_PROPS_CORRECT_6,
19530 		WXS_BASIC_CAST circ, NULL,
19531 		"The element declaration '%s' defines a circular "
19532 		"substitution group to element declaration '%s'",
19533 		xmlSchemaGetComponentQName(&strA, circ),
19534 		xmlSchemaGetComponentQName(&strB, head),
19535 		NULL);
19536 	    FREE_AND_NULL(strA)
19537 	    FREE_AND_NULL(strB)
19538 	    ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
19539 	}
19540 	/*
19541 	* SPEC (4) "If there is a {substitution group affiliation},
19542 	* the {type definition}
19543 	* of the element declaration must be validly derived from the {type
19544 	* definition} of the {substitution group affiliation}, given the value
19545 	* of the {substitution group exclusions} of the {substitution group
19546 	* affiliation}, as defined in Type Derivation OK (Complex) (�3.4.6)
19547 	* (if the {type definition} is complex) or as defined in
19548 	* Type Derivation OK (Simple) (�3.14.6) (if the {type definition} is
19549 	* simple)."
19550 	*
19551 	* NOTE: {substitution group exclusions} means the values of the
19552 	* attribute "final".
19553 	*/
19554 
19555 	if (typeDef != WXS_ELEM_TYPEDEF(WXS_SUBST_HEAD(elemDecl))) {
19556 	    int set = 0;
19557 
19558 	    if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
19559 		set |= SUBSET_EXTENSION;
19560 	    if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
19561 		set |= SUBSET_RESTRICTION;
19562 
19563 	    if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST pctxt, typeDef,
19564 		WXS_ELEM_TYPEDEF(head), set) != 0) {
19565 		xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
19566 
19567 		ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
19568 		xmlSchemaPCustomErrExt(pctxt,
19569 		    XML_SCHEMAP_E_PROPS_CORRECT_4,
19570 		    WXS_BASIC_CAST elemDecl, NULL,
19571 		    "The type definition '%s' was "
19572 		    "either rejected by the substitution group "
19573 		    "affiliation '%s', or not validly derived from its type "
19574 		    "definition '%s'",
19575 		    xmlSchemaGetComponentQName(&strA, typeDef),
19576 		    xmlSchemaGetComponentQName(&strB, head),
19577 		    xmlSchemaGetComponentQName(&strC, WXS_ELEM_TYPEDEF(head)));
19578 		FREE_AND_NULL(strA)
19579 		FREE_AND_NULL(strB)
19580 		FREE_AND_NULL(strC)
19581 	    }
19582 	}
19583     }
19584     /*
19585     * SPEC (5) "If the {type definition} or {type definition}'s
19586     * {content type}
19587     * is or is derived from ID then there must not be a {value constraint}.
19588     * Note: The use of ID as a type definition for elements goes beyond
19589     * XML 1.0, and should be avoided if backwards compatibility is desired"
19590     */
19591     if ((elemDecl->value != NULL) &&
19592 	((WXS_IS_SIMPLE(typeDef) &&
19593 	  xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
19594 	 (WXS_IS_COMPLEX(typeDef) &&
19595 	  WXS_HAS_SIMPLE_CONTENT(typeDef) &&
19596 	  xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
19597 	    XML_SCHEMAS_ID)))) {
19598 
19599 	ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
19600 	xmlSchemaPCustomErr(pctxt,
19601 	    XML_SCHEMAP_E_PROPS_CORRECT_5,
19602 	    WXS_BASIC_CAST elemDecl, NULL,
19603 	    "The type definition (or type definition's content type) is or "
19604 	    "is derived from ID; value constraints are not allowed in "
19605 	    "conjunction with such a type definition", NULL);
19606     } else if (elemDecl->value != NULL) {
19607 	int vcret;
19608 	xmlNodePtr node = NULL;
19609 
19610 	/*
19611 	* SPEC (2) "If there is a {value constraint}, the canonical lexical
19612 	* representation of its value must be �valid� with respect to the
19613 	* {type definition} as defined in Element Default Valid (Immediate)
19614 	* (�3.3.6)."
19615 	*/
19616 	if (typeDef == NULL) {
19617 	    xmlSchemaPErr(pctxt, elemDecl->node,
19618 		XML_SCHEMAP_INTERNAL,
19619 		"Internal error: xmlSchemaCheckElemPropsCorrect, "
19620 		"type is missing... skipping validation of "
19621 		"the value constraint", NULL, NULL);
19622 	    return (-1);
19623 	}
19624 	if (elemDecl->node != NULL) {
19625 	    if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
19626 		node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19627 		    BAD_CAST "fixed");
19628 	    else
19629 		node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19630 		    BAD_CAST "default");
19631 	}
19632 	vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
19633 	    typeDef, elemDecl->value, &(elemDecl->defVal));
19634 	if (vcret != 0) {
19635 	    if (vcret < 0) {
19636 		PERROR_INT("xmlSchemaElemCheckValConstr",
19637 		    "failed to validate the value constraint of an "
19638 		    "element declaration");
19639 		return (-1);
19640 	    }
19641 	    return (vcret);
19642 	}
19643     }
19644 
19645     return (ret);
19646 }
19647 
19648 /**
19649  * xmlSchemaCheckElemSubstGroup:
19650  * @ctxt:  a schema parser context
19651  * @decl: the element declaration
19652  * @name:  the name of the attribute
19653  *
19654  * Schema Component Constraint:
19655  * Substitution Group (cos-equiv-class)
19656  *
19657  * In Libxml2 the subst. groups will be precomputed, in terms of that
19658  * a list will be built for each subst. group head, holding all direct
19659  * referents to this head.
19660  * NOTE that this function needs:
19661  *   1. circular subst. groups to be checked beforehand
19662  *   2. the declaration's type to be derived from the head's type
19663  *
19664  * STATUS:
19665  *
19666  */
19667 static void
xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,xmlSchemaElementPtr elemDecl)19668 xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
19669 			     xmlSchemaElementPtr elemDecl)
19670 {
19671     if ((WXS_SUBST_HEAD(elemDecl) == NULL) ||
19672 	/* SPEC (1) "Its {abstract} is false." */
19673 	(elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
19674 	return;
19675     {
19676 	xmlSchemaElementPtr head;
19677 	xmlSchemaTypePtr headType, type;
19678 	int set, methSet;
19679 	/*
19680 	* SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
19681 	* {disallowed substitutions} as the blocking constraint, as defined in
19682 	* Substitution Group OK (Transitive) (�3.3.6)."
19683 	*/
19684 	for (head = WXS_SUBST_HEAD(elemDecl); head != NULL;
19685 	    head = WXS_SUBST_HEAD(head)) {
19686 	    set = 0;
19687 	    methSet = 0;
19688 	    /*
19689 	    * The blocking constraints.
19690 	    */
19691 	    if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
19692 		continue;
19693 	    headType = head->subtypes;
19694 	    type = elemDecl->subtypes;
19695 	    if (headType == type)
19696 		goto add_member;
19697 	    if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
19698 		set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19699 	    if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
19700 		set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19701 	    /*
19702 	    * SPEC: Substitution Group OK (Transitive) (2.3)
19703 	    * "The set of all {derivation method}s involved in the
19704 	    * derivation of D's {type definition} from C's {type definition}
19705 	    * does not intersect with the union of the blocking constraint,
19706 	    * C's {prohibited substitutions} (if C is complex, otherwise the
19707 	    * empty set) and the {prohibited substitutions} (respectively the
19708 	    * empty set) of any intermediate {type definition}s in the
19709 	    * derivation of D's {type definition} from C's {type definition}."
19710 	    */
19711 	    /*
19712 	    * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
19713 	    * subst.head axis, the methSet does not need to be computed for
19714 	    * the full depth over and over.
19715 	    */
19716 	    /*
19717 	    * The set of all {derivation method}s involved in the derivation
19718 	    */
19719 	    while ((type != NULL) && (type != headType)) {
19720 		if ((WXS_IS_EXTENSION(type)) &&
19721 		    ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19722 		    methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19723 
19724 		if (WXS_IS_RESTRICTION(type) &&
19725 		    ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19726 		    methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19727 
19728 		type = type->baseType;
19729 	    }
19730 	    /*
19731 	    * The {prohibited substitutions} of all intermediate types +
19732 	    * the head's type.
19733 	    */
19734 	    type = elemDecl->subtypes->baseType;
19735 	    while (type != NULL) {
19736 		if (WXS_IS_COMPLEX(type)) {
19737 		    if ((type->flags &
19738 			    XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19739 			((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
19740 		    set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19741 		    if ((type->flags &
19742 			    XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19743 			((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19744 		    set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19745 		} else
19746 		    break;
19747 		if (type == headType)
19748 		    break;
19749 		type = type->baseType;
19750 	    }
19751 	    if ((set != 0) &&
19752 		(((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19753 		(methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
19754 		((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19755 		(methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
19756 		continue;
19757 	    }
19758 add_member:
19759 	    xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
19760 	    if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
19761 		head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
19762 	}
19763     }
19764 }
19765 
19766 #ifdef WXS_ELEM_DECL_CONS_ENABLED /* enable when finished */
19767 /**
19768  * xmlSchemaCheckElementDeclComponent
19769  * @pctxt: the schema parser context
19770  * @ctxtComponent: the context component (an element declaration)
19771  * @ctxtParticle: the first particle of the context component
19772  * @searchParticle: the element declaration particle to be analysed
19773  *
19774  * Schema Component Constraint: Element Declarations Consistent
19775  */
19776 static int
xmlSchemaCheckElementDeclConsistent(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBasicItemPtr ctxtComponent,xmlSchemaParticlePtr ctxtParticle,xmlSchemaParticlePtr searchParticle,xmlSchemaParticlePtr curParticle,int search)19777 xmlSchemaCheckElementDeclConsistent(xmlSchemaParserCtxtPtr pctxt,
19778 				    xmlSchemaBasicItemPtr ctxtComponent,
19779 				    xmlSchemaParticlePtr ctxtParticle,
19780 				    xmlSchemaParticlePtr searchParticle,
19781 				    xmlSchemaParticlePtr curParticle,
19782 				    int search)
19783 {
19784     return(0);
19785 
19786     int ret = 0;
19787     xmlSchemaParticlePtr cur = curParticle;
19788     if (curParticle == NULL) {
19789 	return(0);
19790     }
19791     if (WXS_PARTICLE_TERM(curParticle) == NULL) {
19792 	/*
19793 	* Just return in this case. A missing "term" of the particle
19794 	* might arise due to an invalid "term" component.
19795 	*/
19796 	return(0);
19797     }
19798     while (cur != NULL) {
19799 	switch (WXS_PARTICLE_TERM(cur)->type) {
19800 	    case XML_SCHEMA_TYPE_ANY:
19801 		break;
19802 	    case XML_SCHEMA_TYPE_ELEMENT:
19803 		if (search == 0) {
19804 		    ret = xmlSchemaCheckElementDeclConsistent(pctxt,
19805 			ctxtComponent, ctxtParticle, cur, ctxtParticle, 1);
19806 		    if (ret != 0)
19807 			return(ret);
19808 		} else {
19809 		    xmlSchemaElementPtr elem =
19810 			WXS_ELEM_CAST(WXS_PARTICLE_TERM(cur));
19811 		    /*
19812 		    * SPEC Element Declarations Consistent:
19813 		    * "If the {particles} contains, either directly,
19814 		    * indirectly (that is, within the {particles} of a
19815 		    * contained model group, recursively) or �implicitly�
19816 		    * two or more element declaration particles with
19817 		    * the same {name} and {target namespace}, then
19818 		    * all their type definitions must be the same
19819 		    * top-level definition [...]"
19820 		    */
19821 		    if (xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->name,
19822 			    WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->name) &&
19823 			xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
19824 			    WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->targetNamespace))
19825 		    {
19826 			xmlChar *strA = NULL, *strB = NULL;
19827 
19828 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
19829 			    /* TODO: error code */
19830 			    XML_SCHEMAP_COS_NONAMBIG,
19831 			    WXS_ITEM_NODE(cur), NULL,
19832 			    "In the content model of %s, there are multiple "
19833 			    "element declarations for '%s' with different "
19834 			    "type definitions",
19835 			    xmlSchemaGetComponentDesignation(&strA,
19836 				ctxtComponent),
19837 			    xmlSchemaFormatQName(&strB,
19838 				WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
19839 				WXS_PARTICLE_TERM_AS_ELEM(cur)->name));
19840 			FREE_AND_NULL(strA);
19841 			FREE_AND_NULL(strB);
19842 			return(XML_SCHEMAP_COS_NONAMBIG);
19843 		    }
19844 		}
19845 		break;
19846 	    case XML_SCHEMA_TYPE_SEQUENCE: {
19847 		break;
19848 		}
19849 	    case XML_SCHEMA_TYPE_CHOICE:{
19850 		/*
19851 		xmlSchemaTreeItemPtr sub;
19852 
19853 		sub = WXS_PARTICLE_TERM(particle)->children;  (xmlSchemaParticlePtr)
19854 		while (sub != NULL) {
19855 		    ret = xmlSchemaCheckElementDeclConsistent(pctxt, ctxtComponent,
19856 			ctxtParticle, ctxtElem);
19857 		    if (ret != 0)
19858 			return(ret);
19859 		    sub = sub->next;
19860 		}
19861 		*/
19862 		break;
19863 		}
19864 	    case XML_SCHEMA_TYPE_ALL:
19865 		break;
19866 	    case XML_SCHEMA_TYPE_GROUP:
19867 		break;
19868 	    default:
19869 		xmlSchemaInternalErr2(ACTXT_CAST pctxt,
19870 		    "xmlSchemaCheckElementDeclConsistent",
19871 		    "found unexpected term of type '%s' in content model",
19872 		    WXS_ITEM_TYPE_NAME(WXS_PARTICLE_TERM(cur)), NULL);
19873 		return(-1);
19874 	}
19875 	cur = (xmlSchemaParticlePtr) cur->next;
19876     }
19877 
19878 exit:
19879     return(ret);
19880 }
19881 #endif
19882 
19883 /**
19884  * xmlSchemaCheckElementDeclComponent
19885  * @item:  an schema element declaration/particle
19886  * @ctxt:  a schema parser context
19887  * @name:  the name of the attribute
19888  *
19889  * Validates the value constraints of an element declaration.
19890  * Adds substitution group members.
19891  */
19892 static void
xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,xmlSchemaParserCtxtPtr ctxt)19893 xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
19894 				   xmlSchemaParserCtxtPtr ctxt)
19895 {
19896     if (elemDecl == NULL)
19897 	return;
19898     if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
19899 	return;
19900     elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
19901     if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0) {
19902 	/*
19903 	* Adds substitution group members.
19904 	*/
19905 	xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
19906     }
19907 }
19908 
19909 /**
19910  * xmlSchemaResolveModelGroupParticleReferences:
19911  * @particle:  a particle component
19912  * @ctxt:  a parser context
19913  *
19914  * Resolves references of a model group's {particles} to
19915  * model group definitions and to element declarations.
19916  */
19917 static void
xmlSchemaResolveModelGroupParticleReferences(xmlSchemaParserCtxtPtr ctxt,xmlSchemaModelGroupPtr mg)19918 xmlSchemaResolveModelGroupParticleReferences(
19919     xmlSchemaParserCtxtPtr ctxt,
19920     xmlSchemaModelGroupPtr mg)
19921 {
19922     xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
19923     xmlSchemaQNameRefPtr ref;
19924     xmlSchemaBasicItemPtr refItem;
19925 
19926     /*
19927     * URGENT TODO: Test this.
19928     */
19929     while (particle != NULL) {
19930 	if ((WXS_PARTICLE_TERM(particle) == NULL) ||
19931 	    ((WXS_PARTICLE_TERM(particle))->type !=
19932 		XML_SCHEMA_EXTRA_QNAMEREF))
19933 	{
19934 	    goto next_particle;
19935 	}
19936 	ref = WXS_QNAME_CAST WXS_PARTICLE_TERM(particle);
19937 	/*
19938 	* Resolve the reference.
19939 	* NULL the {term} by default.
19940 	*/
19941 	particle->children = NULL;
19942 
19943 	refItem = xmlSchemaGetNamedComponent(ctxt->schema,
19944 	    ref->itemType, ref->name, ref->targetNamespace);
19945 	if (refItem == NULL) {
19946 	    xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
19947 		NULL, WXS_ITEM_NODE(particle), "ref", ref->name,
19948 		ref->targetNamespace, ref->itemType, NULL);
19949 	    /* TODO: remove the particle. */
19950 	    goto next_particle;
19951 	}
19952 	if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
19953 	    if (WXS_MODELGROUPDEF_MODEL(refItem) == NULL)
19954 		/* TODO: remove the particle. */
19955 		goto next_particle;
19956 	    /*
19957 	    * NOTE that we will assign the model group definition
19958 	    * itself to the "term" of the particle. This will ease
19959 	    * the check for circular model group definitions. After
19960 	    * that the "term" will be assigned the model group of the
19961 	    * model group definition.
19962 	    */
19963 	    if ((WXS_MODELGROUPDEF_MODEL(refItem))->type ==
19964 		    XML_SCHEMA_TYPE_ALL) {
19965 		/*
19966 		* SPEC cos-all-limited (1)
19967 		* SPEC cos-all-limited (1.2)
19968 		* "It appears only as the value of one or both of the
19969 		* following properties:"
19970 		* (1.1) "the {model group} property of a model group
19971 		*        definition."
19972 		* (1.2) "the {term} property of a particle [... of] the "
19973 		* {content type} of a complex type definition."
19974 		*/
19975 		xmlSchemaCustomErr(ACTXT_CAST ctxt,
19976 		    /* TODO: error code */
19977 		    XML_SCHEMAP_COS_ALL_LIMITED,
19978 		    WXS_ITEM_NODE(particle), NULL,
19979 		    "A model group definition is referenced, but "
19980 		    "it contains an 'all' model group, which "
19981 		    "cannot be contained by model groups",
19982 		    NULL, NULL);
19983 		/* TODO: remove the particle. */
19984 		goto next_particle;
19985 	    }
19986 	    particle->children = (xmlSchemaTreeItemPtr) refItem;
19987 	} else {
19988 	    /*
19989 	    * TODO: Are referenced element declarations the only
19990 	    * other components we expect here?
19991 	    */
19992 	    particle->children = (xmlSchemaTreeItemPtr) refItem;
19993 	}
19994 next_particle:
19995 	particle = WXS_PTC_CAST particle->next;
19996     }
19997 }
19998 
19999 static int
xmlSchemaAreValuesEqual(xmlSchemaValPtr x,xmlSchemaValPtr y)20000 xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
20001 		       xmlSchemaValPtr y)
20002 {
20003     xmlSchemaTypePtr tx, ty, ptx, pty;
20004     int ret;
20005 
20006     while (x != NULL) {
20007 	/* Same types. */
20008 	tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
20009 	ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
20010 	ptx = xmlSchemaGetPrimitiveType(tx);
20011 	pty = xmlSchemaGetPrimitiveType(ty);
20012 	/*
20013 	* (1) if a datatype T' is �derived� by �restriction� from an
20014 	* atomic datatype T then the �value space� of T' is a subset of
20015 	* the �value space� of T. */
20016 	/*
20017 	* (2) if datatypes T' and T'' are �derived� by �restriction�
20018 	* from a common atomic ancestor T then the �value space�s of T'
20019 	* and T'' may overlap.
20020 	*/
20021 	if (ptx != pty)
20022 	    return(0);
20023 	/*
20024 	* We assume computed values to be normalized, so do a fast
20025 	* string comparison for string based types.
20026 	*/
20027 	if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
20028 	    WXS_IS_ANY_SIMPLE_TYPE(ptx)) {
20029 	    if (! xmlStrEqual(
20030 		xmlSchemaValueGetAsString(x),
20031 		xmlSchemaValueGetAsString(y)))
20032 		return (0);
20033 	} else {
20034 	    ret = xmlSchemaCompareValuesWhtsp(
20035 		x, XML_SCHEMA_WHITESPACE_PRESERVE,
20036 		y, XML_SCHEMA_WHITESPACE_PRESERVE);
20037 	    if (ret == -2)
20038 		return(-1);
20039 	    if (ret != 0)
20040 		return(0);
20041 	}
20042 	/*
20043 	* Lists.
20044 	*/
20045 	x = xmlSchemaValueGetNext(x);
20046 	if (x != NULL) {
20047 	    y = xmlSchemaValueGetNext(y);
20048 	    if (y == NULL)
20049 		return (0);
20050 	} else if (xmlSchemaValueGetNext(y) != NULL)
20051 	    return (0);
20052 	else
20053 	    return (1);
20054     }
20055     return (0);
20056 }
20057 
20058 /**
20059  * xmlSchemaResolveAttrUseReferences:
20060  * @item:  an attribute use
20061  * @ctxt:  a parser context
20062  *
20063  * Resolves the referenced attribute declaration.
20064  */
20065 static int
xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,xmlSchemaParserCtxtPtr ctxt)20066 xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,
20067 				  xmlSchemaParserCtxtPtr ctxt)
20068 {
20069     if ((ctxt == NULL) || (ause == NULL))
20070 	return(-1);
20071     if ((ause->attrDecl == NULL) ||
20072 	(ause->attrDecl->type != XML_SCHEMA_EXTRA_QNAMEREF))
20073 	return(0);
20074 
20075     {
20076 	xmlSchemaQNameRefPtr ref = WXS_QNAME_CAST ause->attrDecl;
20077 
20078 	/*
20079 	* TODO: Evaluate, what errors could occur if the declaration is not
20080 	* found.
20081 	*/
20082 	ause->attrDecl = xmlSchemaGetAttributeDecl(ctxt->schema,
20083 	    ref->name, ref->targetNamespace);
20084         if (ause->attrDecl == NULL) {
20085 	    xmlSchemaPResCompAttrErr(ctxt,
20086 	    	XML_SCHEMAP_SRC_RESOLVE,
20087 		WXS_BASIC_CAST ause, ause->node,
20088 		"ref", ref->name, ref->targetNamespace,
20089 		XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20090             return(ctxt->err);;
20091         }
20092     }
20093     return(0);
20094 }
20095 
20096 /**
20097  * xmlSchemaCheckAttrUsePropsCorrect:
20098  * @ctxt:  a parser context
20099  * @use:  an attribute use
20100  *
20101  * Schema Component Constraint:
20102  * Attribute Use Correct (au-props-correct)
20103  *
20104  */
20105 static int
xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,xmlSchemaAttributeUsePtr use)20106 xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,
20107 			     xmlSchemaAttributeUsePtr use)
20108 {
20109     if ((ctxt == NULL) || (use == NULL))
20110 	return(-1);
20111     if ((use->defValue == NULL) || (WXS_ATTRUSE_DECL(use) == NULL) ||
20112 	((WXS_ATTRUSE_DECL(use))->type != XML_SCHEMA_TYPE_ATTRIBUTE))
20113 	return(0);
20114 
20115     /*
20116     * SPEC au-props-correct (1)
20117     * "The values of the properties of an attribute use must be as
20118     * described in the property tableau in The Attribute Use Schema
20119     * Component (�3.5.1), modulo the impact of Missing
20120     * Sub-components (�5.3)."
20121     */
20122 
20123     if (((WXS_ATTRUSE_DECL(use))->defValue != NULL) &&
20124 	((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMAS_ATTR_FIXED) &&
20125         ((use->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20126     {
20127 	xmlSchemaPCustomErr(ctxt,
20128 	    XML_SCHEMAP_AU_PROPS_CORRECT_2,
20129 	    WXS_BASIC_CAST use, NULL,
20130 	    "The attribute declaration has a 'fixed' value constraint "
20131 	    ", thus the attribute use must also have a 'fixed' value "
20132 	    "constraint",
20133 	    NULL);
20134 	return(ctxt->err);
20135     }
20136     /*
20137     * Compute and check the value constraint's value.
20138     */
20139     if ((use->defVal != NULL) && (WXS_ATTRUSE_TYPEDEF(use) != NULL)) {
20140 	int ret;
20141 	/*
20142 	* TODO: The spec seems to be missing a check of the
20143 	* value constraint of the attribute use. We will do it here.
20144 	*/
20145 	/*
20146 	* SPEC a-props-correct (3)
20147 	*/
20148 	if (xmlSchemaIsDerivedFromBuiltInType(
20149 	    WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
20150 	{
20151 	    xmlSchemaCustomErr(ACTXT_CAST ctxt,
20152 		XML_SCHEMAP_AU_PROPS_CORRECT,
20153 		NULL, WXS_BASIC_CAST use,
20154 		"Value constraints are not allowed if the type definition "
20155 		"is or is derived from xs:ID",
20156 		NULL, NULL);
20157 	    return(ctxt->err);
20158 	}
20159 
20160 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST ctxt,
20161 	    use->node, WXS_ATTRUSE_TYPEDEF(use),
20162 	    use->defValue, &(use->defVal),
20163 	    1, 1, 0);
20164 	if (ret != 0) {
20165 	    if (ret < 0) {
20166 		PERROR_INT2("xmlSchemaCheckAttrUsePropsCorrect",
20167 		    "calling xmlSchemaVCheckCVCSimpleType()");
20168 		return(-1);
20169 	    }
20170 	    xmlSchemaCustomErr(ACTXT_CAST ctxt,
20171 		XML_SCHEMAP_AU_PROPS_CORRECT,
20172 		NULL, WXS_BASIC_CAST use,
20173 		"The value of the value constraint is not valid",
20174 		NULL, NULL);
20175 	    return(ctxt->err);
20176 	}
20177     }
20178     /*
20179     * SPEC au-props-correct (2)
20180     * "If the {attribute declaration} has a fixed
20181     * {value constraint}, then if the attribute use itself has a
20182     * {value constraint}, it must also be fixed and its value must match
20183     * that of the {attribute declaration}'s {value constraint}."
20184     */
20185     if (((WXS_ATTRUSE_DECL(use))->defVal != NULL) &&
20186 	(((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20187     {
20188 	if (! xmlSchemaAreValuesEqual(use->defVal,
20189 		(WXS_ATTRUSE_DECL(use))->defVal))
20190 	{
20191 	    xmlSchemaPCustomErr(ctxt,
20192 		XML_SCHEMAP_AU_PROPS_CORRECT_2,
20193 		WXS_BASIC_CAST use, NULL,
20194 		"The 'fixed' value constraint of the attribute use "
20195 		"must match the attribute declaration's value "
20196 		"constraint '%s'",
20197 		(WXS_ATTRUSE_DECL(use))->defValue);
20198 	}
20199 	return(ctxt->err);
20200     }
20201     return(0);
20202 }
20203 
20204 
20205 
20206 
20207 /**
20208  * xmlSchemaResolveAttrTypeReferences:
20209  * @item:  an attribute declaration
20210  * @ctxt:  a parser context
20211  *
20212  * Resolves the referenced type definition component.
20213  */
20214 static int
xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,xmlSchemaParserCtxtPtr ctxt)20215 xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,
20216 				   xmlSchemaParserCtxtPtr ctxt)
20217 {
20218     /*
20219     * The simple type definition corresponding to the <simpleType> element
20220     * information item in the [children], if present, otherwise the simple
20221     * type definition �resolved� to by the �actual value� of the type
20222     * [attribute], if present, otherwise the �simple ur-type definition�.
20223     */
20224     if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
20225 	return(0);
20226     item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
20227     if (item->subtypes != NULL)
20228         return(0);
20229     if (item->typeName != NULL) {
20230         xmlSchemaTypePtr type;
20231 
20232 	type = xmlSchemaGetType(ctxt->schema, item->typeName,
20233 	    item->typeNs);
20234 	if ((type == NULL) || (! WXS_IS_SIMPLE(type))) {
20235 	    xmlSchemaPResCompAttrErr(ctxt,
20236 		XML_SCHEMAP_SRC_RESOLVE,
20237 		WXS_BASIC_CAST item, item->node,
20238 		"type", item->typeName, item->typeNs,
20239 		XML_SCHEMA_TYPE_SIMPLE, NULL);
20240 	    return(ctxt->err);
20241 	} else
20242 	    item->subtypes = type;
20243 
20244     } else {
20245 	/*
20246 	* The type defaults to the xs:anySimpleType.
20247 	*/
20248 	item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
20249     }
20250     return(0);
20251 }
20252 
20253 /**
20254  * xmlSchemaResolveIDCKeyReferences:
20255  * @idc:  the identity-constraint definition
20256  * @ctxt:  the schema parser context
20257  * @name:  the attribute name
20258  *
20259  * Resolve keyRef references to key/unique IDCs.
20260  * Schema Component Constraint:
20261  *   Identity-constraint Definition Properties Correct (c-props-correct)
20262  */
20263 static int
xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,xmlSchemaParserCtxtPtr pctxt)20264 xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,
20265 			  xmlSchemaParserCtxtPtr pctxt)
20266 {
20267     if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
20268         return(0);
20269     if (idc->ref->name != NULL) {
20270 	idc->ref->item = (xmlSchemaBasicItemPtr)
20271 	    xmlSchemaGetIDC(pctxt->schema, idc->ref->name,
20272 		idc->ref->targetNamespace);
20273         if (idc->ref->item == NULL) {
20274 	    /*
20275 	    * TODO: It is actually not an error to fail to resolve
20276 	    * at this stage. BUT we need to be that strict!
20277 	    */
20278 	    xmlSchemaPResCompAttrErr(pctxt,
20279 		XML_SCHEMAP_SRC_RESOLVE,
20280 		WXS_BASIC_CAST idc, idc->node,
20281 		"refer", idc->ref->name,
20282 		idc->ref->targetNamespace,
20283 		XML_SCHEMA_TYPE_IDC_KEY, NULL);
20284             return(pctxt->err);
20285 	} else if (idc->ref->item->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20286 	    /*
20287 	    * SPEC c-props-correct (1)
20288 	    */
20289 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20290 		XML_SCHEMAP_C_PROPS_CORRECT,
20291 		NULL, WXS_BASIC_CAST idc,
20292 		"The keyref references a keyref",
20293 		NULL, NULL);
20294 	    idc->ref->item = NULL;
20295 	    return(pctxt->err);
20296 	} else {
20297 	    if (idc->nbFields !=
20298 		((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
20299 		xmlChar *str = NULL;
20300 		xmlSchemaIDCPtr refer;
20301 
20302 		refer = (xmlSchemaIDCPtr) idc->ref->item;
20303 		/*
20304 		* SPEC c-props-correct(2)
20305 		* "If the {identity-constraint category} is keyref,
20306 		* the cardinality of the {fields} must equal that of
20307 		* the {fields} of the {referenced key}.
20308 		*/
20309 		xmlSchemaCustomErr(ACTXT_CAST pctxt,
20310 		    XML_SCHEMAP_C_PROPS_CORRECT,
20311 		    NULL, WXS_BASIC_CAST idc,
20312 		    "The cardinality of the keyref differs from the "
20313 		    "cardinality of the referenced key/unique '%s'",
20314 		    xmlSchemaFormatQName(&str, refer->targetNamespace,
20315 			refer->name),
20316 		    NULL);
20317 		FREE_AND_NULL(str)
20318 		return(pctxt->err);
20319 	    }
20320 	}
20321     }
20322     return(0);
20323 }
20324 
20325 static int
xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,xmlSchemaParserCtxtPtr pctxt)20326 xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,
20327 				       xmlSchemaParserCtxtPtr pctxt)
20328 {
20329     if (xmlSchemaGetAttributeDecl(pctxt->schema, prohib->name,
20330 	prohib->targetNamespace) == NULL) {
20331 
20332 	xmlSchemaPResCompAttrErr(pctxt,
20333 	    XML_SCHEMAP_SRC_RESOLVE,
20334 	    NULL, prohib->node,
20335 	    "ref", prohib->name, prohib->targetNamespace,
20336 	    XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20337 	return(XML_SCHEMAP_SRC_RESOLVE);
20338     }
20339     return(0);
20340 }
20341 
20342 #define WXS_REDEFINED_TYPE(c) \
20343 (((xmlSchemaTypePtr) item)->flags & XML_SCHEMAS_TYPE_REDEFINED)
20344 
20345 #define WXS_REDEFINED_MODEL_GROUP_DEF(c) \
20346 (((xmlSchemaModelGroupDefPtr) item)->flags & XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20347 
20348 #define WXS_REDEFINED_ATTR_GROUP(c) \
20349 (((xmlSchemaAttributeGroupPtr) item)->flags & XML_SCHEMAS_ATTRGROUP_REDEFINED)
20350 
20351 static int
xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)20352 xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)
20353 {
20354     int err = 0;
20355     xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20356     xmlSchemaBasicItemPtr prev, item;
20357     int wasRedefined;
20358 
20359     if (redef == NULL)
20360 	return(0);
20361 
20362     do {
20363 	item = redef->item;
20364 	/*
20365 	* First try to locate the redefined component in the
20366 	* schema graph starting with the redefined schema.
20367 	* NOTE: According to this schema bug entry:
20368 	*   http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005OctDec/0019.html
20369 	*   it's not clear if the referenced component needs to originate
20370 	*   from the <redefine>d schema _document_ or the schema; the latter
20371 	*   would include all imported and included sub-schemas of the
20372 	*   <redefine>d schema. Currenlty we latter approach is used.
20373 	*   SUPPLEMENT: It seems that the WG moves towards the latter
20374 	*   approach, so we are doing it right.
20375 	*
20376 	*/
20377 	prev = xmlSchemaFindRedefCompInGraph(
20378 	    redef->targetBucket, item->type,
20379 	    redef->refName, redef->refTargetNs);
20380 	if (prev == NULL) {
20381 	    xmlChar *str = NULL;
20382 	    xmlNodePtr node;
20383 
20384 	    /*
20385 	    * SPEC src-redefine:
20386 	    * (6.2.1) "The �actual value� of its own name attribute plus
20387 	    * target namespace must successfully �resolve� to a model
20388 	    * group definition in I."
20389 	    * (7.2.1) "The �actual value� of its own name attribute plus
20390 	    * target namespace must successfully �resolve� to an attribute
20391 	    * group definition in I."
20392 
20393 	    *
20394 	    * Note that, if we are redefining with the use of references
20395 	    * to components, the spec assumes the src-resolve to be used;
20396 	    * but this won't assure that we search only *inside* the
20397 	    * redefined schema.
20398 	    */
20399 	    if (redef->reference)
20400 		node = WXS_ITEM_NODE(redef->reference);
20401 	    else
20402 		node = WXS_ITEM_NODE(item);
20403 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20404 		/*
20405 		* TODO: error code.
20406 		* Probably XML_SCHEMAP_SRC_RESOLVE, if this is using the
20407 		* reference kind.
20408 		*/
20409 		XML_SCHEMAP_SRC_REDEFINE, node, NULL,
20410 		"The %s '%s' to be redefined could not be found in "
20411 		"the redefined schema",
20412 		WXS_ITEM_TYPE_NAME(item),
20413 		xmlSchemaFormatQName(&str, redef->refTargetNs,
20414 		    redef->refName));
20415 	    FREE_AND_NULL(str);
20416 	    err = pctxt->err;
20417 	    redef = redef->next;
20418 	    continue;
20419 	}
20420 	/*
20421 	* TODO: Obtaining and setting the redefinition state is really
20422 	* clumsy.
20423 	*/
20424 	wasRedefined = 0;
20425 	switch (item->type) {
20426 	    case XML_SCHEMA_TYPE_COMPLEX:
20427 	    case XML_SCHEMA_TYPE_SIMPLE:
20428 		if ((WXS_TYPE_CAST prev)->flags &
20429 		    XML_SCHEMAS_TYPE_REDEFINED)
20430 		{
20431 		    wasRedefined = 1;
20432 		    break;
20433 		}
20434 		/* Mark it as redefined. */
20435 		(WXS_TYPE_CAST prev)->flags |= XML_SCHEMAS_TYPE_REDEFINED;
20436 		/*
20437 		* Assign the redefined type to the
20438 		* base type of the redefining type.
20439 		* TODO: How
20440 		*/
20441 		((xmlSchemaTypePtr) item)->baseType =
20442 		    (xmlSchemaTypePtr) prev;
20443 		break;
20444 	    case XML_SCHEMA_TYPE_GROUP:
20445 		if ((WXS_MODEL_GROUPDEF_CAST prev)->flags &
20446 		    XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20447 		{
20448 		    wasRedefined = 1;
20449 		    break;
20450 		}
20451 		/* Mark it as redefined. */
20452 		(WXS_MODEL_GROUPDEF_CAST prev)->flags |=
20453 		    XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED;
20454 		if (redef->reference != NULL) {
20455 		    /*
20456 		    * Overwrite the QName-reference with the
20457 		    * referenced model group def.
20458 		    */
20459 		    (WXS_PTC_CAST redef->reference)->children =
20460 			WXS_TREE_CAST prev;
20461 		}
20462 		redef->target = prev;
20463 		break;
20464 	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20465 		if ((WXS_ATTR_GROUP_CAST prev)->flags &
20466 		    XML_SCHEMAS_ATTRGROUP_REDEFINED)
20467 		{
20468 		    wasRedefined = 1;
20469 		    break;
20470 		}
20471 		(WXS_ATTR_GROUP_CAST prev)->flags |=
20472 		    XML_SCHEMAS_ATTRGROUP_REDEFINED;
20473 		if (redef->reference != NULL) {
20474 		    /*
20475 		    * Assign the redefined attribute group to the
20476 		    * QName-reference component.
20477 		    * This is the easy case, since we will just
20478 		    * expand the redefined group.
20479 		    */
20480 		    (WXS_QNAME_CAST redef->reference)->item = prev;
20481 		    redef->target = NULL;
20482 		} else {
20483 		    /*
20484 		    * This is the complicated case: we need
20485 		    * to apply src-redefine (7.2.2) at a later
20486 		    * stage, i.e. when attribute group references
20487 		    * have beed expanded and simple types have
20488 		    * beed fixed.
20489 		    */
20490 		    redef->target = prev;
20491 		}
20492 		break;
20493 	    default:
20494 		PERROR_INT("xmlSchemaResolveRedefReferences",
20495 		    "Unexpected redefined component type");
20496 		return(-1);
20497 	}
20498 	if (wasRedefined) {
20499 	    xmlChar *str = NULL;
20500 	    xmlNodePtr node;
20501 
20502 	    if (redef->reference)
20503 		node = WXS_ITEM_NODE(redef->reference);
20504 	    else
20505 		node = WXS_ITEM_NODE(redef->item);
20506 
20507 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20508 		/* TODO: error code. */
20509 		XML_SCHEMAP_SRC_REDEFINE,
20510 		node, NULL,
20511 		"The referenced %s was already redefined. Multiple "
20512 		"redefinition of the same component is not supported",
20513 		xmlSchemaGetComponentDesignation(&str, prev),
20514 		NULL);
20515 	    FREE_AND_NULL(str)
20516 	    err = pctxt->err;
20517 	    redef = redef->next;
20518 	    continue;
20519 	}
20520 	redef = redef->next;
20521     } while (redef != NULL);
20522 
20523     return(err);
20524 }
20525 
20526 static int
xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)20527 xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)
20528 {
20529     int err = 0;
20530     xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20531     xmlSchemaBasicItemPtr item;
20532 
20533     if (redef == NULL)
20534 	return(0);
20535 
20536     do {
20537 	if (redef->target == NULL) {
20538 	    redef = redef->next;
20539 	    continue;
20540 	}
20541 	item = redef->item;
20542 
20543 	switch (item->type) {
20544 	    case XML_SCHEMA_TYPE_SIMPLE:
20545 	    case XML_SCHEMA_TYPE_COMPLEX:
20546 		/*
20547 		* Since the spec wants the {name} of the redefined
20548 		* type to be 'absent', we'll NULL it.
20549 		*/
20550 		(WXS_TYPE_CAST redef->target)->name = NULL;
20551 
20552 		/*
20553 		* TODO: Seems like there's nothing more to do. The normal
20554 		* inheritance mechanism is used. But not 100% sure.
20555 		*/
20556 		break;
20557 	    case XML_SCHEMA_TYPE_GROUP:
20558 		/*
20559 		* URGENT TODO:
20560 		* SPEC src-redefine:
20561 		* (6.2.2) "The {model group} of the model group definition
20562 		* which corresponds to it per XML Representation of Model
20563 		* Group Definition Schema Components (�3.7.2) must be a
20564 		* �valid restriction� of the {model group} of that model
20565 		* group definition in I, as defined in Particle Valid
20566 		* (Restriction) (�3.9.6)."
20567 		*/
20568 		break;
20569 	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20570 		/*
20571 		* SPEC src-redefine:
20572 		* (7.2.2) "The {attribute uses} and {attribute wildcard} of
20573 		* the attribute group definition which corresponds to it
20574 		* per XML Representation of Attribute Group Definition Schema
20575 		* Components (�3.6.2) must be �valid restrictions� of the
20576 		* {attribute uses} and {attribute wildcard} of that attribute
20577 		* group definition in I, as defined in clause 2, clause 3 and
20578 		* clause 4 of Derivation Valid (Restriction, Complex)
20579 		* (�3.4.6) (where references to the base type definition are
20580 		* understood as references to the attribute group definition
20581 		* in I)."
20582 		*/
20583 		err = xmlSchemaCheckDerivationOKRestriction2to4(pctxt,
20584 		    XML_SCHEMA_ACTION_REDEFINE,
20585 		    item, redef->target,
20586 		    (WXS_ATTR_GROUP_CAST item)->attrUses,
20587 		    (WXS_ATTR_GROUP_CAST redef->target)->attrUses,
20588 		    (WXS_ATTR_GROUP_CAST item)->attributeWildcard,
20589 		    (WXS_ATTR_GROUP_CAST redef->target)->attributeWildcard);
20590 		if (err == -1)
20591 		    return(-1);
20592 		break;
20593 	    default:
20594 		break;
20595 	}
20596 	redef = redef->next;
20597     } while (redef != NULL);
20598     return(0);
20599 }
20600 
20601 
20602 static int
xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBucketPtr bucket)20603 xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,
20604 		       xmlSchemaBucketPtr bucket)
20605 {
20606     xmlSchemaBasicItemPtr item;
20607     int err;
20608     xmlHashTablePtr *table;
20609     const xmlChar *name;
20610     int i;
20611 
20612 #define WXS_GET_GLOBAL_HASH(c, slot) { \
20613     if (WXS_IS_BUCKET_IMPMAIN((c)->type)) \
20614 	table = &(WXS_IMPBUCKET((c))->schema->slot); \
20615     else \
20616 	table = &(WXS_INCBUCKET((c))->ownerImport->schema->slot); }
20617 
20618     /*
20619     * Add global components to the schema's hash tables.
20620     * This is the place where duplicate components will be
20621     * detected.
20622     * TODO: I think normally we should support imports of the
20623     *   same namespace from multiple locations. We don't do currently,
20624     *   but if we do then according to:
20625     *   http://www.w3.org/Bugs/Public/show_bug.cgi?id=2224
20626     *   we would need, if imported directly, to import redefined
20627     *   components as well to be able to catch clashing components.
20628     *   (I hope I'll still know what this means after some months :-()
20629     */
20630     if (bucket == NULL)
20631 	return(-1);
20632     if (bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED)
20633 	return(0);
20634     bucket->flags |= XML_SCHEMA_BUCKET_COMPS_ADDED;
20635 
20636     for (i = 0; i < bucket->globals->nbItems; i++) {
20637 	item = bucket->globals->items[i];
20638 	table = NULL;
20639 	switch (item->type) {
20640 	    case XML_SCHEMA_TYPE_COMPLEX:
20641 	    case XML_SCHEMA_TYPE_SIMPLE:
20642 		if (WXS_REDEFINED_TYPE(item))
20643 		    continue;
20644 		name = (WXS_TYPE_CAST item)->name;
20645 		WXS_GET_GLOBAL_HASH(bucket, typeDecl)
20646 		break;
20647 	    case XML_SCHEMA_TYPE_ELEMENT:
20648 		name = (WXS_ELEM_CAST item)->name;
20649 		WXS_GET_GLOBAL_HASH(bucket, elemDecl)
20650 		break;
20651 	    case XML_SCHEMA_TYPE_ATTRIBUTE:
20652 		name = (WXS_ATTR_CAST item)->name;
20653 		WXS_GET_GLOBAL_HASH(bucket, attrDecl)
20654 		break;
20655 	    case XML_SCHEMA_TYPE_GROUP:
20656 		if (WXS_REDEFINED_MODEL_GROUP_DEF(item))
20657 		    continue;
20658 		name = (WXS_MODEL_GROUPDEF_CAST item)->name;
20659 		WXS_GET_GLOBAL_HASH(bucket, groupDecl)
20660 		break;
20661 	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20662 		if (WXS_REDEFINED_ATTR_GROUP(item))
20663 		    continue;
20664 		name = (WXS_ATTR_GROUP_CAST item)->name;
20665 		WXS_GET_GLOBAL_HASH(bucket, attrgrpDecl)
20666 		break;
20667 	    case XML_SCHEMA_TYPE_IDC_KEY:
20668 	    case XML_SCHEMA_TYPE_IDC_UNIQUE:
20669 	    case XML_SCHEMA_TYPE_IDC_KEYREF:
20670 		name = (WXS_IDC_CAST item)->name;
20671 		WXS_GET_GLOBAL_HASH(bucket, idcDef)
20672 		break;
20673 	    case XML_SCHEMA_TYPE_NOTATION:
20674 		name = ((xmlSchemaNotationPtr) item)->name;
20675 		WXS_GET_GLOBAL_HASH(bucket, notaDecl)
20676 		break;
20677 	    default:
20678 		PERROR_INT("xmlSchemaAddComponents",
20679 		    "Unexpected global component type");
20680 		continue;
20681 	}
20682 	if (*table == NULL) {
20683 	    *table = xmlHashCreateDict(10, pctxt->dict);
20684 	    if (*table == NULL) {
20685 		PERROR_INT("xmlSchemaAddComponents",
20686 		    "failed to create a component hash table");
20687 		return(-1);
20688 	    }
20689 	}
20690 	err = xmlHashAddEntry(*table, name, item);
20691 	if (err != 0) {
20692 	    xmlChar *str = NULL;
20693 
20694 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20695 		XML_SCHEMAP_REDEFINED_TYPE,
20696 		WXS_ITEM_NODE(item),
20697 		WXS_BASIC_CAST item,
20698 		"A global %s '%s' does already exist",
20699 		WXS_ITEM_TYPE_NAME(item),
20700 		xmlSchemaGetComponentQName(&str, item));
20701 	    FREE_AND_NULL(str);
20702 	}
20703     }
20704     /*
20705     * Process imported/included schemas.
20706     */
20707     if (bucket->relations != NULL) {
20708 	xmlSchemaSchemaRelationPtr rel = bucket->relations;
20709 	do {
20710 	    if ((rel->bucket != NULL) &&
20711 		((rel->bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED) == 0)) {
20712 		if (xmlSchemaAddComponents(pctxt, rel->bucket) == -1)
20713 		    return(-1);
20714 	    }
20715 	    rel = rel->next;
20716 	} while (rel != NULL);
20717     }
20718     return(0);
20719 }
20720 
20721 static int
xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBucketPtr rootBucket)20722 xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt,
20723 			 xmlSchemaBucketPtr rootBucket)
20724 {
20725     xmlSchemaConstructionCtxtPtr con = pctxt->constructor;
20726     xmlSchemaTreeItemPtr item, *items;
20727     int nbItems, i, ret = 0;
20728     xmlSchemaBucketPtr oldbucket = con->bucket;
20729     xmlSchemaElementPtr elemDecl;
20730 
20731 #define FIXHFAILURE if (pctxt->err == XML_SCHEMAP_INTERNAL) goto exit_failure;
20732 
20733     if ((con->pending == NULL) ||
20734 	(con->pending->nbItems == 0))
20735 	return(0);
20736 
20737     /*
20738     * Since xmlSchemaFixupComplexType() will create new particles
20739     * (local components), and those particle components need a bucket
20740     * on the constructor, we'll assure here that the constructor has
20741     * a bucket.
20742     * TODO: Think about storing locals _only_ on the main bucket.
20743     */
20744     if (con->bucket == NULL)
20745 	con->bucket = rootBucket;
20746 
20747     /* TODO:
20748     * SPEC (src-redefine):
20749     * (6.2) "If it has no such self-reference, then all of the
20750     * following must be true:"
20751 
20752     * (6.2.2) The {model group} of the model group definition which
20753     * corresponds to it per XML Representation of Model Group
20754     * Definition Schema Components (�3.7.2) must be a �valid
20755     * restriction� of the {model group} of that model group definition
20756     * in I, as defined in Particle Valid (Restriction) (�3.9.6)."
20757     */
20758     xmlSchemaCheckSRCRedefineFirst(pctxt);
20759 
20760     /*
20761     * Add global components to the schemata's hash tables.
20762     */
20763     xmlSchemaAddComponents(pctxt, rootBucket);
20764 
20765     pctxt->ctxtType = NULL;
20766     items = (xmlSchemaTreeItemPtr *) con->pending->items;
20767     nbItems = con->pending->nbItems;
20768     /*
20769     * Now that we have parsed *all* the schema document(s) and converted
20770     * them to schema components, we can resolve references, apply component
20771     * constraints, create the FSA from the content model, etc.
20772     */
20773     /*
20774     * Resolve references of..
20775     *
20776     * 1. element declarations:
20777     *   - the type definition
20778     *   - the substitution group affiliation
20779     * 2. simple/complex types:
20780     *   - the base type definition
20781     *   - the memberTypes of union types
20782     *   - the itemType of list types
20783     * 3. attributes declarations and attribute uses:
20784     *   - the type definition
20785     *   - if an attribute use, then the attribute declaration
20786     * 4. attribute group references:
20787     *   - the attribute group definition
20788     * 5. particles:
20789     *   - the term of the particle (e.g. a model group)
20790     * 6. IDC key-references:
20791     *   - the referenced IDC 'key' or 'unique' definition
20792     * 7. Attribute prohibitions which had a "ref" attribute.
20793     */
20794     for (i = 0; i < nbItems; i++) {
20795 	item = items[i];
20796 	switch (item->type) {
20797 	    case XML_SCHEMA_TYPE_ELEMENT:
20798 		xmlSchemaResolveElementReferences(
20799 		    (xmlSchemaElementPtr) item, pctxt);
20800 		FIXHFAILURE;
20801 		break;
20802 	    case XML_SCHEMA_TYPE_COMPLEX:
20803 	    case XML_SCHEMA_TYPE_SIMPLE:
20804 		xmlSchemaResolveTypeReferences(
20805 		    (xmlSchemaTypePtr) item, pctxt);
20806 		FIXHFAILURE;
20807 		break;
20808 	    case XML_SCHEMA_TYPE_ATTRIBUTE:
20809 		xmlSchemaResolveAttrTypeReferences(
20810 		    (xmlSchemaAttributePtr) item, pctxt);
20811 		FIXHFAILURE;
20812 		break;
20813 	    case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
20814 		xmlSchemaResolveAttrUseReferences(
20815 		    (xmlSchemaAttributeUsePtr) item, pctxt);
20816 		FIXHFAILURE;
20817 		break;
20818 	    case XML_SCHEMA_EXTRA_QNAMEREF:
20819 		if ((WXS_QNAME_CAST item)->itemType ==
20820 		    XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
20821 		{
20822 		    xmlSchemaResolveAttrGroupReferences(
20823 			WXS_QNAME_CAST item, pctxt);
20824 		}
20825 		FIXHFAILURE;
20826 		break;
20827 	    case XML_SCHEMA_TYPE_SEQUENCE:
20828 	    case XML_SCHEMA_TYPE_CHOICE:
20829 	    case XML_SCHEMA_TYPE_ALL:
20830 		xmlSchemaResolveModelGroupParticleReferences(pctxt,
20831 		    WXS_MODEL_GROUP_CAST item);
20832 		FIXHFAILURE;
20833 		break;
20834 	    case XML_SCHEMA_TYPE_IDC_KEY:
20835 	    case XML_SCHEMA_TYPE_IDC_UNIQUE:
20836 	    case XML_SCHEMA_TYPE_IDC_KEYREF:
20837 		xmlSchemaResolveIDCKeyReferences(
20838 		    (xmlSchemaIDCPtr) item, pctxt);
20839 		FIXHFAILURE;
20840 		break;
20841 	    case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
20842 		/*
20843 		* Handle attribue prohibition which had a
20844 		* "ref" attribute.
20845 		*/
20846 		xmlSchemaResolveAttrUseProhibReferences(
20847 		    WXS_ATTR_PROHIB_CAST item, pctxt);
20848 		FIXHFAILURE;
20849 		break;
20850 	    default:
20851 		break;
20852 	}
20853     }
20854     if (pctxt->nberrors != 0)
20855 	goto exit_error;
20856 
20857     /*
20858     * Now that all references are resolved we
20859     * can check for circularity of...
20860     * 1. the base axis of type definitions
20861     * 2. nested model group definitions
20862     * 3. nested attribute group definitions
20863     * TODO: check for circual substitution groups.
20864     */
20865     for (i = 0; i < nbItems; i++) {
20866 	item = items[i];
20867 	/*
20868 	* Let's better stop on the first error here.
20869 	*/
20870 	switch (item->type) {
20871 	    case XML_SCHEMA_TYPE_COMPLEX:
20872 	    case XML_SCHEMA_TYPE_SIMPLE:
20873 		xmlSchemaCheckTypeDefCircular(
20874 		    (xmlSchemaTypePtr) item, pctxt);
20875 		FIXHFAILURE;
20876 		if (pctxt->nberrors != 0)
20877 		    goto exit_error;
20878 		break;
20879 	    case XML_SCHEMA_TYPE_GROUP:
20880 		xmlSchemaCheckGroupDefCircular(
20881 		    (xmlSchemaModelGroupDefPtr) item, pctxt);
20882 		FIXHFAILURE;
20883 		if (pctxt->nberrors != 0)
20884 		    goto exit_error;
20885 		break;
20886 	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20887 		xmlSchemaCheckAttrGroupCircular(
20888 		    (xmlSchemaAttributeGroupPtr) item, pctxt);
20889 		FIXHFAILURE;
20890 		if (pctxt->nberrors != 0)
20891 		    goto exit_error;
20892 		break;
20893 	    default:
20894 		break;
20895 	}
20896     }
20897     if (pctxt->nberrors != 0)
20898 	goto exit_error;
20899     /*
20900     * Model group definition references:
20901     * Such a reference is reflected by a particle at the component
20902     * level. Until now the 'term' of such particles pointed
20903     * to the model group definition; this was done, in order to
20904     * ease circularity checks. Now we need to set the 'term' of
20905     * such particles to the model group of the model group definition.
20906     */
20907     for (i = 0; i < nbItems; i++) {
20908 	item = items[i];
20909 	switch (item->type) {
20910 	    case XML_SCHEMA_TYPE_SEQUENCE:
20911 	    case XML_SCHEMA_TYPE_CHOICE:
20912 		xmlSchemaModelGroupToModelGroupDefFixup(pctxt,
20913 		    WXS_MODEL_GROUP_CAST item);
20914 		break;
20915 	    default:
20916 		break;
20917 	}
20918     }
20919     if (pctxt->nberrors != 0)
20920 	goto exit_error;
20921     /*
20922     * Expand attribute group references of attribute group definitions.
20923     */
20924     for (i = 0; i < nbItems; i++) {
20925 	item = items[i];
20926 	switch (item->type) {
20927             case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20928 		if ((! WXS_ATTR_GROUP_EXPANDED(item)) &&
20929 		    WXS_ATTR_GROUP_HAS_REFS(item))
20930 		{
20931 		    xmlSchemaAttributeGroupExpandRefs(pctxt,
20932 			WXS_ATTR_GROUP_CAST item);
20933 		    FIXHFAILURE;
20934 		}
20935 		break;
20936 	    default:
20937 		break;
20938 	}
20939     }
20940     if (pctxt->nberrors != 0)
20941 	goto exit_error;
20942     /*
20943     * First compute the variety of simple types. This is needed as
20944     * a seperate step, since otherwise we won't be able to detect
20945     * circular union types in all cases.
20946     */
20947     for (i = 0; i < nbItems; i++) {
20948 	item = items[i];
20949 	switch (item->type) {
20950             case XML_SCHEMA_TYPE_SIMPLE:
20951 		if (WXS_IS_TYPE_NOT_FIXED_1((xmlSchemaTypePtr) item)) {
20952 		    xmlSchemaFixupSimpleTypeStageOne(pctxt,
20953 			(xmlSchemaTypePtr) item);
20954 		    FIXHFAILURE;
20955 		}
20956 		break;
20957 	    default:
20958 		break;
20959 	}
20960     }
20961     if (pctxt->nberrors != 0)
20962 	goto exit_error;
20963     /*
20964     * Detect circular union types. Note that this needs the variety to
20965     * be already computed.
20966     */
20967     for (i = 0; i < nbItems; i++) {
20968 	item = items[i];
20969 	switch (item->type) {
20970             case XML_SCHEMA_TYPE_SIMPLE:
20971 		if (((xmlSchemaTypePtr) item)->memberTypes != NULL) {
20972 		    xmlSchemaCheckUnionTypeDefCircular(pctxt,
20973 			(xmlSchemaTypePtr) item);
20974 		    FIXHFAILURE;
20975 		}
20976 		break;
20977 	    default:
20978 		break;
20979 	}
20980     }
20981     if (pctxt->nberrors != 0)
20982 	goto exit_error;
20983 
20984     /*
20985     * Do the complete type fixup for simple types.
20986     */
20987     for (i = 0; i < nbItems; i++) {
20988 	item = items[i];
20989 	switch (item->type) {
20990             case XML_SCHEMA_TYPE_SIMPLE:
20991 		if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
20992 		    xmlSchemaFixupSimpleTypeStageTwo(pctxt, WXS_TYPE_CAST item);
20993 		    FIXHFAILURE;
20994 		}
20995 		break;
20996 	    default:
20997 		break;
20998 	}
20999     }
21000     if (pctxt->nberrors != 0)
21001 	goto exit_error;
21002     /*
21003     * At this point we need build and check all simple types.
21004     */
21005     /*
21006     * Apply contraints for attribute declarations.
21007     */
21008     for (i = 0; i < nbItems; i++) {
21009 	item = items[i];
21010 	switch (item->type) {
21011 	    case XML_SCHEMA_TYPE_ATTRIBUTE:
21012 		xmlSchemaCheckAttrPropsCorrect(pctxt, WXS_ATTR_CAST item);
21013 		FIXHFAILURE;
21014 		break;
21015 	    default:
21016 		break;
21017 	}
21018     }
21019     if (pctxt->nberrors != 0)
21020 	goto exit_error;
21021     /*
21022     * Apply constraints for attribute uses.
21023     */
21024     for (i = 0; i < nbItems; i++) {
21025 	item = items[i];
21026 	switch (item->type) {
21027 	    case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
21028 		if (((xmlSchemaAttributeUsePtr)item)->defValue != NULL) {
21029 		    xmlSchemaCheckAttrUsePropsCorrect(pctxt,
21030 			WXS_ATTR_USE_CAST item);
21031 		    FIXHFAILURE;
21032 		}
21033 		break;
21034 	    default:
21035 		break;
21036 	}
21037     }
21038     if (pctxt->nberrors != 0)
21039 	goto exit_error;
21040 
21041     /*
21042     * Apply constraints for attribute group definitions.
21043     */
21044     for (i = 0; i < nbItems; i++) {
21045 	item = items[i];
21046 	switch (item->type) {
21047 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21048 	    if (( (WXS_ATTR_GROUP_CAST item)->attrUses != NULL) &&
21049 		( (WXS_LIST_CAST (WXS_ATTR_GROUP_CAST item)->attrUses)->nbItems > 1))
21050 	    {
21051 		xmlSchemaCheckAGPropsCorrect(pctxt, WXS_ATTR_GROUP_CAST item);
21052 		FIXHFAILURE;
21053 	    }
21054 	    break;
21055 	default:
21056 	    break;
21057 	}
21058     }
21059     if (pctxt->nberrors != 0)
21060 	goto exit_error;
21061 
21062     /*
21063     * Apply constraints for redefinitions.
21064     */
21065     if (WXS_CONSTRUCTOR(pctxt)->redefs != NULL)
21066 	xmlSchemaCheckSRCRedefineSecond(pctxt);
21067     if (pctxt->nberrors != 0)
21068 	goto exit_error;
21069 
21070     /*
21071     * Complex types are builded and checked.
21072     */
21073     for (i = 0; i < nbItems; i++) {
21074 	item = con->pending->items[i];
21075 	switch (item->type) {
21076 	    case XML_SCHEMA_TYPE_COMPLEX:
21077 		if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21078 		    xmlSchemaFixupComplexType(pctxt, WXS_TYPE_CAST item);
21079 		    FIXHFAILURE;
21080 		}
21081 		break;
21082 	    default:
21083 		break;
21084 	}
21085     }
21086     if (pctxt->nberrors != 0)
21087 	goto exit_error;
21088 
21089     /*
21090     * The list could have changed, since xmlSchemaFixupComplexType()
21091     * will create particles and model groups in some cases.
21092     */
21093     items = (xmlSchemaTreeItemPtr *) con->pending->items;
21094     nbItems = con->pending->nbItems;
21095 
21096     /*
21097     * Apply some constraints for element declarations.
21098     */
21099     for (i = 0; i < nbItems; i++) {
21100 	item = items[i];
21101 	switch (item->type) {
21102 	    case XML_SCHEMA_TYPE_ELEMENT:
21103 		elemDecl = (xmlSchemaElementPtr) item;
21104 
21105 		if ((elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED) == 0)
21106 		{
21107 		    xmlSchemaCheckElementDeclComponent(
21108 			(xmlSchemaElementPtr) elemDecl, pctxt);
21109 		    FIXHFAILURE;
21110 		}
21111 
21112 #ifdef WXS_ELEM_DECL_CONS_ENABLED
21113 		/*
21114 		* Schema Component Constraint: Element Declarations Consistent
21115 		* Apply this constraint to local types of element declarations.
21116 		*/
21117 		if ((WXS_ELEM_TYPEDEF(elemDecl) != NULL) &&
21118 		    (WXS_IS_COMPLEX(WXS_ELEM_TYPEDEF(elemDecl))) &&
21119 		    (WXS_TYPE_IS_LOCAL(WXS_ELEM_TYPEDEF(elemDecl))))
21120 		{
21121 		    xmlSchemaCheckElementDeclConsistent(pctxt,
21122 			WXS_BASIC_CAST elemDecl,
21123 			WXS_TYPE_PARTICLE(WXS_ELEM_TYPEDEF(elemDecl)),
21124 			NULL, NULL, 0);
21125 		}
21126 #endif
21127 		break;
21128 	    default:
21129 		break;
21130 	}
21131     }
21132     if (pctxt->nberrors != 0)
21133 	goto exit_error;
21134 
21135     /*
21136     * Finally we can build the automaton from the content model of
21137     * complex types.
21138     */
21139 
21140     for (i = 0; i < nbItems; i++) {
21141 	item = items[i];
21142 	switch (item->type) {
21143 	    case XML_SCHEMA_TYPE_COMPLEX:
21144 		xmlSchemaBuildContentModel((xmlSchemaTypePtr) item, pctxt);
21145 		/* FIXHFAILURE; */
21146 		break;
21147 	    default:
21148 		break;
21149 	}
21150     }
21151     if (pctxt->nberrors != 0)
21152 	goto exit_error;
21153     /*
21154     * URGENT TODO: cos-element-consistent
21155     */
21156     goto exit;
21157 
21158 exit_error:
21159     ret = pctxt->err;
21160     goto exit;
21161 
21162 exit_failure:
21163     ret = -1;
21164 
21165 exit:
21166     /*
21167     * Reset the constructor. This is needed for XSI acquisition, since
21168     * those items will be processed over and over again for every XSI
21169     * if not cleared here.
21170     */
21171     con->bucket = oldbucket;
21172     con->pending->nbItems = 0;
21173     if (con->substGroups != NULL) {
21174 	xmlHashFree(con->substGroups,
21175 	    (xmlHashDeallocator) xmlSchemaSubstGroupFree);
21176 	con->substGroups = NULL;
21177     }
21178     if (con->redefs != NULL) {
21179 	xmlSchemaRedefListFree(con->redefs);
21180 	con->redefs = NULL;
21181     }
21182     return(ret);
21183 }
21184 /**
21185  * xmlSchemaParse:
21186  * @ctxt:  a schema validation context
21187  *
21188  * parse a schema definition resource and build an internal
21189  * XML Shema struture which can be used to validate instances.
21190  *
21191  * Returns the internal XML Schema structure built from the resource or
21192  *         NULL in case of error
21193  */
21194 xmlSchemaPtr
xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)21195 xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
21196 {
21197     xmlSchemaPtr mainSchema = NULL;
21198     xmlSchemaBucketPtr bucket = NULL;
21199     int res;
21200 
21201     /*
21202     * This one is used if the schema to be parsed was specified via
21203     * the API; i.e. not automatically by the validated instance document.
21204     */
21205 
21206     xmlSchemaInitTypes();
21207 
21208     if (ctxt == NULL)
21209         return (NULL);
21210 
21211     /* TODO: Init the context. Is this all we need?*/
21212     ctxt->nberrors = 0;
21213     ctxt->err = 0;
21214     ctxt->counter = 0;
21215 
21216     /* Create the *main* schema. */
21217     mainSchema = xmlSchemaNewSchema(ctxt);
21218     if (mainSchema == NULL)
21219 	goto exit_failure;
21220     /*
21221     * Create the schema constructor.
21222     */
21223     if (ctxt->constructor == NULL) {
21224 	ctxt->constructor = xmlSchemaConstructionCtxtCreate(ctxt->dict);
21225 	if (ctxt->constructor == NULL)
21226 	    return(NULL);
21227 	/* Take ownership of the constructor to be able to free it. */
21228 	ctxt->ownsConstructor = 1;
21229     }
21230     ctxt->constructor->mainSchema = mainSchema;
21231     /*
21232     * Locate and add the schema document.
21233     */
21234     res = xmlSchemaAddSchemaDoc(ctxt, XML_SCHEMA_SCHEMA_MAIN,
21235 	ctxt->URL, ctxt->doc, ctxt->buffer, ctxt->size, NULL,
21236 	NULL, NULL, &bucket);
21237     if (res == -1)
21238 	goto exit_failure;
21239     if (res != 0)
21240 	goto exit;
21241 
21242     if (bucket == NULL) {
21243 	/* TODO: Error code, actually we failed to *locate* the schema. */
21244 	if (ctxt->URL)
21245 	    xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21246 		NULL, NULL,
21247 		"Failed to locate the main schema resource at '%s'",
21248 		ctxt->URL, NULL);
21249 	else
21250 	    xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21251 		NULL, NULL,
21252 		"Failed to locate the main schema resource",
21253 		    NULL, NULL);
21254 	goto exit;
21255     }
21256     /* Then do the parsing for good. */
21257     if (xmlSchemaParseNewDocWithContext(ctxt, mainSchema, bucket) == -1)
21258 	goto exit_failure;
21259     if (ctxt->nberrors != 0)
21260 	goto exit;
21261 
21262     mainSchema->doc = bucket->doc;
21263     mainSchema->preserve = ctxt->preserve;
21264 
21265     ctxt->schema = mainSchema;
21266 
21267     if (xmlSchemaFixupComponents(ctxt, WXS_CONSTRUCTOR(ctxt)->mainBucket) == -1)
21268 	goto exit_failure;
21269 
21270     /*
21271     * TODO: This is not nice, since we cannot distinguish from the
21272     * result if there was an internal error or not.
21273     */
21274 exit:
21275     if (ctxt->nberrors != 0) {
21276 	if (mainSchema) {
21277 	    xmlSchemaFree(mainSchema);
21278 	    mainSchema = NULL;
21279 	}
21280 	if (ctxt->constructor) {
21281 	    xmlSchemaConstructionCtxtFree(ctxt->constructor);
21282 	    ctxt->constructor = NULL;
21283 	    ctxt->ownsConstructor = 0;
21284 	}
21285     }
21286     ctxt->schema = NULL;
21287     return(mainSchema);
21288 exit_failure:
21289     /*
21290     * Quite verbose, but should catch internal errors, which were
21291     * not communitated.
21292     */
21293     if (mainSchema) {
21294         xmlSchemaFree(mainSchema);
21295 	mainSchema = NULL;
21296     }
21297     if (ctxt->constructor) {
21298 	xmlSchemaConstructionCtxtFree(ctxt->constructor);
21299 	ctxt->constructor = NULL;
21300 	ctxt->ownsConstructor = 0;
21301     }
21302     PERROR_INT2("xmlSchemaParse",
21303 	"An internal error occured");
21304     ctxt->schema = NULL;
21305     return(NULL);
21306 }
21307 
21308 /**
21309  * xmlSchemaSetParserErrors:
21310  * @ctxt:  a schema validation context
21311  * @err:  the error callback
21312  * @warn:  the warning callback
21313  * @ctx:  contextual data for the callbacks
21314  *
21315  * Set the callback functions used to handle errors for a validation context
21316  */
21317 void
xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,xmlSchemaValidityErrorFunc err,xmlSchemaValidityWarningFunc warn,void * ctx)21318 xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21319                          xmlSchemaValidityErrorFunc err,
21320                          xmlSchemaValidityWarningFunc warn, void *ctx)
21321 {
21322     if (ctxt == NULL)
21323         return;
21324     ctxt->error = err;
21325     ctxt->warning = warn;
21326     ctxt->errCtxt = ctx;
21327     if (ctxt->vctxt != NULL)
21328 	xmlSchemaSetValidErrors(ctxt->vctxt, err, warn, ctx);
21329 }
21330 
21331 /**
21332  * xmlSchemaSetParserStructuredErrors:
21333  * @ctxt:  a schema parser context
21334  * @serror:  the structured error function
21335  * @ctx: the functions context
21336  *
21337  * Set the structured error callback
21338  */
21339 void
xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,xmlStructuredErrorFunc serror,void * ctx)21340 xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,
21341 				   xmlStructuredErrorFunc serror,
21342 				   void *ctx)
21343 {
21344     if (ctxt == NULL)
21345 	return;
21346     ctxt->serror = serror;
21347     ctxt->errCtxt = ctx;
21348     if (ctxt->vctxt != NULL)
21349 	xmlSchemaSetValidStructuredErrors(ctxt->vctxt, serror, ctx);
21350 }
21351 
21352 /**
21353  * xmlSchemaGetParserErrors:
21354  * @ctxt:  a XMl-Schema parser context
21355  * @err: the error callback result
21356  * @warn: the warning callback result
21357  * @ctx: contextual data for the callbacks result
21358  *
21359  * Get the callback information used to handle errors for a parser context
21360  *
21361  * Returns -1 in case of failure, 0 otherwise
21362  */
21363 int
xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,xmlSchemaValidityErrorFunc * err,xmlSchemaValidityWarningFunc * warn,void ** ctx)21364 xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21365 			 xmlSchemaValidityErrorFunc * err,
21366 			 xmlSchemaValidityWarningFunc * warn, void **ctx)
21367 {
21368 	if (ctxt == NULL)
21369 		return(-1);
21370 	if (err != NULL)
21371 		*err = ctxt->error;
21372 	if (warn != NULL)
21373 		*warn = ctxt->warning;
21374 	if (ctx != NULL)
21375 		*ctx = ctxt->errCtxt;
21376 	return(0);
21377 }
21378 
21379 /**
21380  * xmlSchemaFacetTypeToString:
21381  * @type:  the facet type
21382  *
21383  * Convert the xmlSchemaTypeType to a char string.
21384  *
21385  * Returns the char string representation of the facet type if the
21386  *     type is a facet and an "Internal Error" string otherwise.
21387  */
21388 static const xmlChar *
xmlSchemaFacetTypeToString(xmlSchemaTypeType type)21389 xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
21390 {
21391     switch (type) {
21392         case XML_SCHEMA_FACET_PATTERN:
21393             return (BAD_CAST "pattern");
21394         case XML_SCHEMA_FACET_MAXEXCLUSIVE:
21395             return (BAD_CAST "maxExclusive");
21396         case XML_SCHEMA_FACET_MAXINCLUSIVE:
21397             return (BAD_CAST "maxInclusive");
21398         case XML_SCHEMA_FACET_MINEXCLUSIVE:
21399             return (BAD_CAST "minExclusive");
21400         case XML_SCHEMA_FACET_MININCLUSIVE:
21401             return (BAD_CAST "minInclusive");
21402         case XML_SCHEMA_FACET_WHITESPACE:
21403             return (BAD_CAST "whiteSpace");
21404         case XML_SCHEMA_FACET_ENUMERATION:
21405             return (BAD_CAST "enumeration");
21406         case XML_SCHEMA_FACET_LENGTH:
21407             return (BAD_CAST "length");
21408         case XML_SCHEMA_FACET_MAXLENGTH:
21409             return (BAD_CAST "maxLength");
21410         case XML_SCHEMA_FACET_MINLENGTH:
21411             return (BAD_CAST "minLength");
21412         case XML_SCHEMA_FACET_TOTALDIGITS:
21413             return (BAD_CAST "totalDigits");
21414         case XML_SCHEMA_FACET_FRACTIONDIGITS:
21415             return (BAD_CAST "fractionDigits");
21416         default:
21417             break;
21418     }
21419     return (BAD_CAST "Internal Error");
21420 }
21421 
21422 static xmlSchemaWhitespaceValueType
xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)21423 xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
21424 {
21425     /*
21426     * The normalization type can be changed only for types which are derived
21427     * from xsd:string.
21428     */
21429     if (type->type == XML_SCHEMA_TYPE_BASIC) {
21430 	/*
21431 	* Note that we assume a whitespace of preserve for anySimpleType.
21432 	*/
21433 	if ((type->builtInType == XML_SCHEMAS_STRING) ||
21434 	    (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
21435 	    return(XML_SCHEMA_WHITESPACE_PRESERVE);
21436 	else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
21437 	    return(XML_SCHEMA_WHITESPACE_REPLACE);
21438 	else {
21439 	    /*
21440 	    * For all �atomic� datatypes other than string (and types �derived�
21441 	    * by �restriction� from it) the value of whiteSpace is fixed to
21442 	    * collapse
21443 	    * Note that this includes built-in list datatypes.
21444 	    */
21445 	    return(XML_SCHEMA_WHITESPACE_COLLAPSE);
21446 	}
21447     } else if (WXS_IS_LIST(type)) {
21448 	/*
21449 	* For list types the facet "whiteSpace" is fixed to "collapse".
21450 	*/
21451 	return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21452     } else if (WXS_IS_UNION(type)) {
21453 	return (XML_SCHEMA_WHITESPACE_UNKNOWN);
21454     } else if (WXS_IS_ATOMIC(type)) {
21455 	if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
21456 	    return (XML_SCHEMA_WHITESPACE_PRESERVE);
21457 	else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
21458 	    return (XML_SCHEMA_WHITESPACE_REPLACE);
21459 	else
21460 	    return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21461     }
21462     return (-1);
21463 }
21464 
21465 /************************************************************************
21466  * 									*
21467  * 			Simple type validation				*
21468  * 									*
21469  ************************************************************************/
21470 
21471 
21472 /************************************************************************
21473  * 									*
21474  * 			DOM Validation code				*
21475  * 									*
21476  ************************************************************************/
21477 
21478 /**
21479  * xmlSchemaAssembleByLocation:
21480  * @pctxt:  a schema parser context
21481  * @vctxt:  a schema validation context
21482  * @schema: the existing schema
21483  * @node: the node that fired the assembling
21484  * @nsName: the namespace name of the new schema
21485  * @location: the location of the schema
21486  *
21487  * Expands an existing schema by an additional schema.
21488  *
21489  * Returns 0 if the new schema is correct, a positive error code
21490  * number otherwise and -1 in case of an internal or API error.
21491  */
21492 static int
xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,xmlSchemaPtr schema,xmlNodePtr node,const xmlChar * nsName,const xmlChar * location)21493 xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
21494 			    xmlSchemaPtr schema,
21495 			    xmlNodePtr node,
21496 			    const xmlChar *nsName,
21497 			    const xmlChar *location)
21498 {
21499     int ret = 0;
21500     xmlSchemaParserCtxtPtr pctxt;
21501     xmlSchemaBucketPtr bucket = NULL;
21502 
21503     if ((vctxt == NULL) || (schema == NULL))
21504 	return (-1);
21505 
21506     if (vctxt->pctxt == NULL) {
21507 	VERROR_INT("xmlSchemaAssembleByLocation",
21508 	    "no parser context available");
21509 	return(-1);
21510     }
21511     pctxt = vctxt->pctxt;
21512     if (pctxt->constructor == NULL) {
21513 	PERROR_INT("xmlSchemaAssembleByLocation",
21514 	    "no constructor");
21515 	return(-1);
21516     }
21517     /*
21518     * Acquire the schema document.
21519     */
21520     location = xmlSchemaBuildAbsoluteURI(pctxt->dict,
21521 	location, node);
21522     /*
21523     * Note that we pass XML_SCHEMA_SCHEMA_IMPORT here;
21524     * the process will automatically change this to
21525     * XML_SCHEMA_SCHEMA_MAIN if it is the first schema document.
21526     */
21527     ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
21528 	location, NULL, NULL, 0, node, NULL, nsName,
21529 	&bucket);
21530     if (ret != 0)
21531 	return(ret);
21532     if (bucket == NULL) {
21533 	/*
21534 	* Generate a warning that the document could not be located.
21535 	*/
21536 	xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21537 	    node, NULL,
21538 	    "The document at location '%s' could not be acquired",
21539 	    location, NULL, NULL);
21540 	return(ret);
21541     }
21542     /*
21543     * The first located schema will be handled as if all other
21544     * schemas imported by XSI were imported by this first schema.
21545     */
21546     if ((bucket != NULL) &&
21547 	(WXS_CONSTRUCTOR(pctxt)->bucket == NULL))
21548 	WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
21549     /*
21550     * TODO: Is this handled like an import? I.e. is it not an error
21551     * if the schema cannot be located?
21552     */
21553     if ((bucket == NULL) || (! CAN_PARSE_SCHEMA(bucket)))
21554 	return(0);
21555     /*
21556     * We will reuse the parser context for every schema imported
21557     * directly via XSI. So reset the context.
21558     */
21559     pctxt->nberrors = 0;
21560     pctxt->err = 0;
21561     pctxt->doc = bucket->doc;
21562 
21563     ret = xmlSchemaParseNewDocWithContext(pctxt, schema, bucket);
21564     if (ret == -1) {
21565 	pctxt->doc = NULL;
21566 	goto exit_failure;
21567     }
21568     /* Paranoid error channelling. */
21569     if ((ret == 0) && (pctxt->nberrors != 0))
21570 	ret = pctxt->err;
21571     if (pctxt->nberrors == 0) {
21572 	/*
21573 	* Only bother to fixup pending components, if there was
21574 	* no error yet.
21575 	* For every XSI acquired schema (and its sub-schemata) we will
21576 	* fixup the components.
21577 	*/
21578 	xmlSchemaFixupComponents(pctxt, bucket);
21579 	ret = pctxt->err;
21580 	/*
21581 	* Not nice, but we need somehow to channel the schema parser
21582 	* error to the validation context.
21583 	*/
21584 	if ((ret != 0) && (vctxt->err == 0))
21585 	    vctxt->err = ret;
21586 	vctxt->nberrors += pctxt->nberrors;
21587     } else {
21588 	/* Add to validation error sum. */
21589 	vctxt->nberrors += pctxt->nberrors;
21590     }
21591     pctxt->doc = NULL;
21592     return(ret);
21593 exit_failure:
21594     pctxt->doc = NULL;
21595     return (-1);
21596 }
21597 
21598 static xmlSchemaAttrInfoPtr
xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,int metaType)21599 xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
21600 			 int metaType)
21601 {
21602     if (vctxt->nbAttrInfos == 0)
21603 	return (NULL);
21604     {
21605 	int i;
21606 	xmlSchemaAttrInfoPtr iattr;
21607 
21608 	for (i = 0; i < vctxt->nbAttrInfos; i++) {
21609 	    iattr = vctxt->attrInfos[i];
21610 	    if (iattr->metaType == metaType)
21611 		return (iattr);
21612 	}
21613 
21614     }
21615     return (NULL);
21616 }
21617 
21618 /**
21619  * xmlSchemaAssembleByXSI:
21620  * @vctxt:  a schema validation context
21621  *
21622  * Expands an existing schema by an additional schema using
21623  * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
21624  * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
21625  * must be set to 1.
21626  *
21627  * Returns 0 if the new schema is correct, a positive error code
21628  * number otherwise and -1 in case of an internal or API error.
21629  */
21630 static int
xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)21631 xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
21632 {
21633     const xmlChar *cur, *end;
21634     const xmlChar *nsname = NULL, *location;
21635     int count = 0;
21636     int ret = 0;
21637     xmlSchemaAttrInfoPtr iattr;
21638 
21639     /*
21640     * Parse the value; we will assume an even number of values
21641     * to be given (this is how Xerces and XSV work).
21642     *
21643     * URGENT TODO: !! This needs to work for both
21644     * @noNamespaceSchemaLocation AND @schemaLocation on the same
21645     * element !!
21646     */
21647     iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21648 	XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
21649     if (iattr == NULL)
21650 	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21651 	XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
21652     if (iattr == NULL)
21653 	return (0);
21654     cur = iattr->value;
21655     do {
21656 	/*
21657 	* TODO: Move the string parsing mechanism away from here.
21658 	*/
21659 	if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
21660 	    /*
21661 	    * Get the namespace name.
21662 	    */
21663 	    while (IS_BLANK_CH(*cur))
21664 		cur++;
21665 	    end = cur;
21666 	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21667 		end++;
21668 	    if (end == cur)
21669 		break;
21670 	    count++; /* TODO: Don't use the schema's dict. */
21671 	    nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21672 	    cur = end;
21673 	}
21674 	/*
21675 	* Get the URI.
21676 	*/
21677 	while (IS_BLANK_CH(*cur))
21678 	    cur++;
21679 	end = cur;
21680 	while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21681 	    end++;
21682 	if (end == cur) {
21683 	    if (iattr->metaType ==
21684 		XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC)
21685 	    {
21686 		/*
21687 		* If using @schemaLocation then tuples are expected.
21688 		* I.e. the namespace name *and* the document's URI.
21689 		*/
21690 		xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21691 		    iattr->node, NULL,
21692 		    "The value must consist of tuples: the target namespace "
21693 		    "name and the document's URI", NULL, NULL, NULL);
21694 	    }
21695 	    break;
21696 	}
21697 	count++; /* TODO: Don't use the schema's dict. */
21698 	location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21699 	cur = end;
21700 	ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
21701 	    iattr->node, nsname, location);
21702 	if (ret == -1) {
21703 	    VERROR_INT("xmlSchemaAssembleByXSI",
21704 		"assembling schemata");
21705 	    return (-1);
21706 	}
21707     } while (*cur != 0);
21708     return (ret);
21709 }
21710 
21711 static const xmlChar *
xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,const xmlChar * prefix)21712 xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
21713 			 const xmlChar *prefix)
21714 {
21715     if (vctxt->sax != NULL) {
21716 	int i, j;
21717 	xmlSchemaNodeInfoPtr inode;
21718 
21719 	for (i = vctxt->depth; i >= 0; i--) {
21720 	    if (vctxt->elemInfos[i]->nbNsBindings != 0) {
21721 		inode = vctxt->elemInfos[i];
21722 		for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
21723 		    if (((prefix == NULL) &&
21724 			    (inode->nsBindings[j] == NULL)) ||
21725 			((prefix != NULL) && xmlStrEqual(prefix,
21726 			    inode->nsBindings[j]))) {
21727 
21728 			/*
21729 			* Note that the namespace bindings are already
21730 			* in a string dict.
21731 			*/
21732 			return (inode->nsBindings[j+1]);
21733 		    }
21734 		}
21735 	    }
21736 	}
21737 	return (NULL);
21738 #ifdef LIBXML_READER_ENABLED
21739     } else if (vctxt->reader != NULL) {
21740 	xmlChar *nsName;
21741 
21742 	nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
21743 	if (nsName != NULL) {
21744 	    const xmlChar *ret;
21745 
21746 	    ret = xmlDictLookup(vctxt->dict, nsName, -1);
21747 	    xmlFree(nsName);
21748 	    return (ret);
21749 	} else
21750 	    return (NULL);
21751 #endif
21752     } else {
21753 	xmlNsPtr ns;
21754 
21755 	if ((vctxt->inode->node == NULL) ||
21756 	    (vctxt->inode->node->doc == NULL)) {
21757 	    VERROR_INT("xmlSchemaLookupNamespace",
21758 		"no node or node's doc avaliable");
21759 	    return (NULL);
21760 	}
21761 	ns = xmlSearchNs(vctxt->inode->node->doc,
21762 	    vctxt->inode->node, prefix);
21763 	if (ns != NULL)
21764 	    return (ns->href);
21765 	return (NULL);
21766     }
21767 }
21768 
21769 /*
21770 * This one works on the schema of the validation context.
21771 */
21772 static int
xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,xmlSchemaPtr schema,xmlNodePtr node,const xmlChar * value,xmlSchemaValPtr * val,int valNeeded)21773 xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
21774 			  xmlSchemaPtr schema,
21775 			  xmlNodePtr node,
21776 			  const xmlChar *value,
21777 			  xmlSchemaValPtr *val,
21778 			  int valNeeded)
21779 {
21780     int ret;
21781 
21782     if (vctxt && (vctxt->schema == NULL)) {
21783 	VERROR_INT("xmlSchemaValidateNotation",
21784 	    "a schema is needed on the validation context");
21785 	return (-1);
21786     }
21787     ret = xmlValidateQName(value, 1);
21788     if (ret != 0)
21789 	return (ret);
21790     {
21791 	xmlChar *localName = NULL;
21792 	xmlChar *prefix = NULL;
21793 
21794 	localName = xmlSplitQName2(value, &prefix);
21795 	if (prefix != NULL) {
21796 	    const xmlChar *nsName = NULL;
21797 
21798 	    if (vctxt != NULL)
21799 		nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
21800 	    else if (node != NULL) {
21801 		xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
21802 		if (ns != NULL)
21803 		    nsName = ns->href;
21804 	    } else {
21805 		xmlFree(prefix);
21806 		xmlFree(localName);
21807 		return (1);
21808 	    }
21809 	    if (nsName == NULL) {
21810 		xmlFree(prefix);
21811 		xmlFree(localName);
21812 		return (1);
21813 	    }
21814 	    if (xmlSchemaGetNotation(schema, localName, nsName) != NULL) {
21815 		if ((valNeeded) && (val != NULL)) {
21816 		    (*val) = xmlSchemaNewNOTATIONValue(xmlStrdup(localName),
21817 						       xmlStrdup(nsName));
21818 		    if (*val == NULL)
21819 			ret = -1;
21820 		}
21821 	    } else
21822 		ret = 1;
21823 	    xmlFree(prefix);
21824 	    xmlFree(localName);
21825 	} else {
21826 	    if (xmlSchemaGetNotation(schema, value, NULL) != NULL) {
21827 		if (valNeeded && (val != NULL)) {
21828 		    (*val) = xmlSchemaNewNOTATIONValue(
21829 			BAD_CAST xmlStrdup(value), NULL);
21830 		    if (*val == NULL)
21831 			ret = -1;
21832 		}
21833 	    } else
21834 		return (1);
21835 	}
21836     }
21837     return (ret);
21838 }
21839 
21840 static int
xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,const xmlChar * lname,const xmlChar * nsname)21841 xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,
21842 		       const xmlChar* lname,
21843 		       const xmlChar* nsname)
21844 {
21845     int i;
21846 
21847     lname = xmlDictLookup(vctxt->dict, lname, -1);
21848     if (lname == NULL)
21849 	return(-1);
21850     if (nsname != NULL) {
21851 	nsname = xmlDictLookup(vctxt->dict, nsname, -1);
21852 	if (nsname == NULL)
21853 	    return(-1);
21854     }
21855     for (i = 0; i < vctxt->nodeQNames->nbItems; i += 2) {
21856 	if ((vctxt->nodeQNames->items [i] == lname) &&
21857 	    (vctxt->nodeQNames->items[i +1] == nsname))
21858 	    /* Already there */
21859 	    return(i);
21860     }
21861     /* Add new entry. */
21862     i = vctxt->nodeQNames->nbItems;
21863     xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) lname);
21864     xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) nsname);
21865     return(i);
21866 }
21867 
21868 /************************************************************************
21869  * 									*
21870  *  Validation of identity-constraints (IDC)                            *
21871  * 									*
21872  ************************************************************************/
21873 
21874 /**
21875  * xmlSchemaAugmentIDC:
21876  * @idcDef: the IDC definition
21877  *
21878  * Creates an augmented IDC definition item.
21879  *
21880  * Returns the item, or NULL on internal errors.
21881  */
21882 static void
xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,xmlSchemaValidCtxtPtr vctxt)21883 xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
21884 		    xmlSchemaValidCtxtPtr vctxt)
21885 {
21886     xmlSchemaIDCAugPtr aidc;
21887 
21888     aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
21889     if (aidc == NULL) {
21890 	xmlSchemaVErrMemory(vctxt,
21891 	    "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
21892 	    NULL);
21893 	return;
21894     }
21895     aidc->keyrefDepth = -1;
21896     aidc->def = idcDef;
21897     aidc->next = NULL;
21898     if (vctxt->aidcs == NULL)
21899 	vctxt->aidcs = aidc;
21900     else {
21901 	aidc->next = vctxt->aidcs;
21902 	vctxt->aidcs = aidc;
21903     }
21904     /*
21905     * Save if we have keyrefs at all.
21906     */
21907     if ((vctxt->hasKeyrefs == 0) &&
21908 	(idcDef->type == XML_SCHEMA_TYPE_IDC_KEYREF))
21909 	vctxt->hasKeyrefs = 1;
21910 }
21911 
21912 /**
21913  * xmlSchemaAugmentImportedIDC:
21914  * @imported: the imported schema
21915  *
21916  * Creates an augmented IDC definition for the imported schema.
21917  */
21918 static void
xmlSchemaAugmentImportedIDC(xmlSchemaImportPtr imported,xmlSchemaValidCtxtPtr vctxt)21919 xmlSchemaAugmentImportedIDC(xmlSchemaImportPtr imported, xmlSchemaValidCtxtPtr vctxt) {
21920     if (imported->schema->idcDef != NULL) {
21921 	    xmlHashScan(imported->schema->idcDef ,
21922 	    (xmlHashScanner) xmlSchemaAugmentIDC, vctxt);
21923     }
21924 }
21925 
21926 /**
21927  * xmlSchemaIDCNewBinding:
21928  * @idcDef: the IDC definition of this binding
21929  *
21930  * Creates a new IDC binding.
21931  *
21932  * Returns the new IDC binding, NULL on internal errors.
21933  */
21934 static xmlSchemaPSVIIDCBindingPtr
xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)21935 xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
21936 {
21937     xmlSchemaPSVIIDCBindingPtr ret;
21938 
21939     ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
21940 	    sizeof(xmlSchemaPSVIIDCBinding));
21941     if (ret == NULL) {
21942 	xmlSchemaVErrMemory(NULL,
21943 	    "allocating a PSVI IDC binding item", NULL);
21944 	return (NULL);
21945     }
21946     memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
21947     ret->definition = idcDef;
21948     return (ret);
21949 }
21950 
21951 /**
21952  * xmlSchemaIDCStoreNodeTableItem:
21953  * @vctxt: the WXS validation context
21954  * @item: the IDC node table item
21955  *
21956  * The validation context is used to store IDC node table items.
21957  * They are stored to avoid copying them if IDC node-tables are merged
21958  * with corresponding parent IDC node-tables (bubbling).
21959  *
21960  * Returns 0 if succeeded, -1 on internal errors.
21961  */
21962 static int
xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,xmlSchemaPSVIIDCNodePtr item)21963 xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
21964 			       xmlSchemaPSVIIDCNodePtr item)
21965 {
21966     /*
21967     * Add to gobal list.
21968     */
21969     if (vctxt->idcNodes == NULL) {
21970 	vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
21971 	    xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
21972 	if (vctxt->idcNodes == NULL) {
21973 	    xmlSchemaVErrMemory(vctxt,
21974 		"allocating the IDC node table item list", NULL);
21975 	    return (-1);
21976 	}
21977 	vctxt->sizeIdcNodes = 20;
21978     } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
21979 	vctxt->sizeIdcNodes *= 2;
21980 	vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
21981 	    xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
21982 	    sizeof(xmlSchemaPSVIIDCNodePtr));
21983 	if (vctxt->idcNodes == NULL) {
21984 	    xmlSchemaVErrMemory(vctxt,
21985 		"re-allocating the IDC node table item list", NULL);
21986 	    return (-1);
21987 	}
21988     }
21989     vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
21990 
21991     return (0);
21992 }
21993 
21994 /**
21995  * xmlSchemaIDCStoreKey:
21996  * @vctxt: the WXS validation context
21997  * @item: the IDC key
21998  *
21999  * The validation context is used to store an IDC key.
22000  *
22001  * Returns 0 if succeeded, -1 on internal errors.
22002  */
22003 static int
xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,xmlSchemaPSVIIDCKeyPtr key)22004 xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
22005 		     xmlSchemaPSVIIDCKeyPtr key)
22006 {
22007     /*
22008     * Add to gobal list.
22009     */
22010     if (vctxt->idcKeys == NULL) {
22011 	vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22012 	    xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
22013 	if (vctxt->idcKeys == NULL) {
22014 	    xmlSchemaVErrMemory(vctxt,
22015 		"allocating the IDC key storage list", NULL);
22016 	    return (-1);
22017 	}
22018 	vctxt->sizeIdcKeys = 40;
22019     } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
22020 	vctxt->sizeIdcKeys *= 2;
22021 	vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22022 	    xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
22023 	    sizeof(xmlSchemaPSVIIDCKeyPtr));
22024 	if (vctxt->idcKeys == NULL) {
22025 	    xmlSchemaVErrMemory(vctxt,
22026 		"re-allocating the IDC key storage list", NULL);
22027 	    return (-1);
22028 	}
22029     }
22030     vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
22031 
22032     return (0);
22033 }
22034 
22035 /**
22036  * xmlSchemaIDCAppendNodeTableItem:
22037  * @bind: the IDC binding
22038  * @ntItem: the node-table item
22039  *
22040  * Appends the IDC node-table item to the binding.
22041  *
22042  * Returns 0 on success and -1 on internal errors.
22043  */
22044 static int
xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,xmlSchemaPSVIIDCNodePtr ntItem)22045 xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
22046 				xmlSchemaPSVIIDCNodePtr ntItem)
22047 {
22048     if (bind->nodeTable == NULL) {
22049 	bind->sizeNodes = 10;
22050 	bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22051 	    xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
22052 	if (bind->nodeTable == NULL) {
22053 	    xmlSchemaVErrMemory(NULL,
22054 		"allocating an array of IDC node-table items", NULL);
22055 	    return(-1);
22056 	}
22057     } else if (bind->sizeNodes <= bind->nbNodes) {
22058 	bind->sizeNodes *= 2;
22059 	bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22060 	    xmlRealloc(bind->nodeTable, bind->sizeNodes *
22061 		sizeof(xmlSchemaPSVIIDCNodePtr));
22062 	if (bind->nodeTable == NULL) {
22063 	    xmlSchemaVErrMemory(NULL,
22064 		"re-allocating an array of IDC node-table items", NULL);
22065 	    return(-1);
22066 	}
22067     }
22068     bind->nodeTable[bind->nbNodes++] = ntItem;
22069     return(0);
22070 }
22071 
22072 /**
22073  * xmlSchemaIDCAcquireBinding:
22074  * @vctxt: the WXS validation context
22075  * @matcher: the IDC matcher
22076  *
22077  * Looks up an PSVI IDC binding, for the IDC definition and
22078  * of the given matcher. If none found, a new one is created
22079  * and added to the IDC table.
22080  *
22081  * Returns an IDC binding or NULL on internal errors.
22082  */
22083 static xmlSchemaPSVIIDCBindingPtr
xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,xmlSchemaIDCMatcherPtr matcher)22084 xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,
22085 			  xmlSchemaIDCMatcherPtr matcher)
22086 {
22087     xmlSchemaNodeInfoPtr ielem;
22088 
22089     ielem = vctxt->elemInfos[matcher->depth];
22090 
22091     if (ielem->idcTable == NULL) {
22092 	ielem->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
22093 	if (ielem->idcTable == NULL)
22094 	    return (NULL);
22095 	return(ielem->idcTable);
22096     } else {
22097 	xmlSchemaPSVIIDCBindingPtr bind = NULL;
22098 
22099 	bind = ielem->idcTable;
22100 	do {
22101 	    if (bind->definition == matcher->aidc->def)
22102 		return(bind);
22103 	    if (bind->next == NULL) {
22104 		bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
22105 		if (bind->next == NULL)
22106 		    return (NULL);
22107 		return(bind->next);
22108 	    }
22109 	    bind = bind->next;
22110 	} while (bind != NULL);
22111     }
22112     return (NULL);
22113 }
22114 
22115 static xmlSchemaItemListPtr
xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,xmlSchemaIDCMatcherPtr matcher)22116 xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
22117 			     xmlSchemaIDCMatcherPtr matcher)
22118 {
22119     if (matcher->targets == NULL)
22120 	matcher->targets = xmlSchemaItemListCreate();
22121     return(matcher->targets);
22122 }
22123 
22124 /**
22125  * xmlSchemaIDCFreeKey:
22126  * @key: the IDC key
22127  *
22128  * Frees an IDC key together with its compiled value.
22129  */
22130 static void
xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)22131 xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
22132 {
22133     if (key->val != NULL)
22134 	xmlSchemaFreeValue(key->val);
22135     xmlFree(key);
22136 }
22137 
22138 /**
22139  * xmlSchemaIDCFreeBinding:
22140  *
22141  * Frees an IDC binding. Note that the node table-items
22142  * are not freed.
22143  */
22144 static void
xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)22145 xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
22146 {
22147     if (bind->nodeTable != NULL)
22148 	xmlFree(bind->nodeTable);
22149     if (bind->dupls != NULL)
22150 	xmlSchemaItemListFree(bind->dupls);
22151     xmlFree(bind);
22152 }
22153 
22154 /**
22155  * xmlSchemaIDCFreeIDCTable:
22156  * @bind: the first IDC binding in the list
22157  *
22158  * Frees an IDC table, i.e. all the IDC bindings in the list.
22159  */
22160 static void
xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)22161 xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
22162 {
22163     xmlSchemaPSVIIDCBindingPtr prev;
22164 
22165     while (bind != NULL) {
22166 	prev = bind;
22167 	bind = bind->next;
22168 	xmlSchemaIDCFreeBinding(prev);
22169     }
22170 }
22171 
22172 /**
22173  * xmlSchemaIDCFreeMatcherList:
22174  * @matcher: the first IDC matcher in the list
22175  *
22176  * Frees a list of IDC matchers.
22177  */
22178 static void
xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)22179 xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
22180 {
22181     xmlSchemaIDCMatcherPtr next;
22182 
22183     while (matcher != NULL) {
22184 	next = matcher->next;
22185 	if (matcher->keySeqs != NULL) {
22186 	    int i;
22187 	    for (i = 0; i < matcher->sizeKeySeqs; i++)
22188 		if (matcher->keySeqs[i] != NULL)
22189 		    xmlFree(matcher->keySeqs[i]);
22190 	    xmlFree(matcher->keySeqs);
22191 	}
22192 	if (matcher->targets != NULL) {
22193 	    if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22194 		int i;
22195 		xmlSchemaPSVIIDCNodePtr idcNode;
22196 		/*
22197 		* Node-table items for keyrefs are not stored globally
22198 		* to the validation context, since they are not bubbled.
22199 		* We need to free them here.
22200 		*/
22201 		for (i = 0; i < matcher->targets->nbItems; i++) {
22202 		    idcNode =
22203 			(xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22204 		    xmlFree(idcNode->keys);
22205 		    xmlFree(idcNode);
22206 		}
22207 	    }
22208 	    xmlSchemaItemListFree(matcher->targets);
22209 	}
22210 	xmlFree(matcher);
22211 	matcher = next;
22212     }
22213 }
22214 
22215 /**
22216  * xmlSchemaIDCReleaseMatcherList:
22217  * @vctxt: the WXS validation context
22218  * @matcher: the first IDC matcher in the list
22219  *
22220  * Caches a list of IDC matchers for reuse.
22221  */
22222 static void
xmlSchemaIDCReleaseMatcherList(xmlSchemaValidCtxtPtr vctxt,xmlSchemaIDCMatcherPtr matcher)22223 xmlSchemaIDCReleaseMatcherList(xmlSchemaValidCtxtPtr vctxt,
22224 			       xmlSchemaIDCMatcherPtr matcher)
22225 {
22226     xmlSchemaIDCMatcherPtr next;
22227 
22228     while (matcher != NULL) {
22229 	next = matcher->next;
22230 	if (matcher->keySeqs != NULL) {
22231 	    int i;
22232 	    /*
22233 	    * Don't free the array, but only the content.
22234 	    */
22235 	    for (i = 0; i < matcher->sizeKeySeqs; i++)
22236 		if (matcher->keySeqs[i] != NULL) {
22237 		    xmlFree(matcher->keySeqs[i]);
22238 		    matcher->keySeqs[i] = NULL;
22239 		}
22240 	}
22241 	if (matcher->targets) {
22242 	    if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22243 		int i;
22244 		xmlSchemaPSVIIDCNodePtr idcNode;
22245 		/*
22246 		* Node-table items for keyrefs are not stored globally
22247 		* to the validation context, since they are not bubbled.
22248 		* We need to free them here.
22249 		*/
22250 		for (i = 0; i < matcher->targets->nbItems; i++) {
22251 		    idcNode =
22252 			(xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22253 		    xmlFree(idcNode->keys);
22254 		    xmlFree(idcNode);
22255 		}
22256 	    }
22257 	    xmlSchemaItemListFree(matcher->targets);
22258 	    matcher->targets = NULL;
22259 	}
22260 	matcher->next = NULL;
22261 	/*
22262 	* Cache the matcher.
22263 	*/
22264 	if (vctxt->idcMatcherCache != NULL)
22265 	    matcher->nextCached = vctxt->idcMatcherCache;
22266 	vctxt->idcMatcherCache = matcher;
22267 
22268 	matcher = next;
22269     }
22270 }
22271 
22272 /**
22273  * xmlSchemaIDCAddStateObject:
22274  * @vctxt: the WXS validation context
22275  * @matcher: the IDC matcher
22276  * @sel: the XPath information
22277  * @parent: the parent "selector" state object if any
22278  * @type: "selector" or "field"
22279  *
22280  * Creates/reuses and activates state objects for the given
22281  * XPath information; if the XPath expression consists of unions,
22282  * multiple state objects are created for every unioned expression.
22283  *
22284  * Returns 0 on success and -1 on internal errors.
22285  */
22286 static int
xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,xmlSchemaIDCMatcherPtr matcher,xmlSchemaIDCSelectPtr sel,int type)22287 xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
22288 			xmlSchemaIDCMatcherPtr matcher,
22289 			xmlSchemaIDCSelectPtr sel,
22290 			int type)
22291 {
22292     xmlSchemaIDCStateObjPtr sto;
22293 
22294     /*
22295     * Reuse the state objects from the pool.
22296     */
22297     if (vctxt->xpathStatePool != NULL) {
22298 	sto = vctxt->xpathStatePool;
22299 	vctxt->xpathStatePool = sto->next;
22300 	sto->next = NULL;
22301     } else {
22302 	/*
22303 	* Create a new state object.
22304 	*/
22305 	sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
22306 	if (sto == NULL) {
22307 	    xmlSchemaVErrMemory(NULL,
22308 		"allocating an IDC state object", NULL);
22309 	    return (-1);
22310 	}
22311 	memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
22312     }
22313     /*
22314     * Add to global list.
22315     */
22316     if (vctxt->xpathStates != NULL)
22317 	sto->next = vctxt->xpathStates;
22318     vctxt->xpathStates = sto;
22319 
22320     /*
22321     * Free the old xpath validation context.
22322     */
22323     if (sto->xpathCtxt != NULL)
22324 	xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
22325 
22326     /*
22327     * Create a new XPath (pattern) validation context.
22328     */
22329     sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
22330 	(xmlPatternPtr) sel->xpathComp);
22331     if (sto->xpathCtxt == NULL) {
22332 	VERROR_INT("xmlSchemaIDCAddStateObject",
22333 	    "failed to create an XPath validation context");
22334 	return (-1);
22335     }
22336     sto->type = type;
22337     sto->depth = vctxt->depth;
22338     sto->matcher = matcher;
22339     sto->sel = sel;
22340     sto->nbHistory = 0;
22341 
22342 #ifdef DEBUG_IDC
22343     xmlGenericError(xmlGenericErrorContext, "IDC:   STO push '%s'\n",
22344 	sto->sel->xpath);
22345 #endif
22346     return (0);
22347 }
22348 
22349 /**
22350  * xmlSchemaXPathEvaluate:
22351  * @vctxt: the WXS validation context
22352  * @nodeType: the nodeType of the current node
22353  *
22354  * Evaluates all active XPath state objects.
22355  *
22356  * Returns the number of IC "field" state objects which resolved to
22357  * this node, 0 if none resolved and -1 on internal errors.
22358  */
22359 static int
xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,xmlElementType nodeType)22360 xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
22361 		       xmlElementType nodeType)
22362 {
22363     xmlSchemaIDCStateObjPtr sto, head = NULL, first;
22364     int res, resolved = 0, depth = vctxt->depth;
22365 
22366     if (vctxt->xpathStates == NULL)
22367 	return (0);
22368 
22369     if (nodeType == XML_ATTRIBUTE_NODE)
22370 	depth++;
22371 #ifdef DEBUG_IDC
22372     {
22373 	xmlChar *str = NULL;
22374 	xmlGenericError(xmlGenericErrorContext,
22375 	    "IDC: EVAL on %s, depth %d, type %d\n",
22376 	    xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22377 		vctxt->inode->localName), depth, nodeType);
22378 	FREE_AND_NULL(str)
22379     }
22380 #endif
22381     /*
22382     * Process all active XPath state objects.
22383     */
22384     first = vctxt->xpathStates;
22385     sto = first;
22386     while (sto != head) {
22387 #ifdef DEBUG_IDC
22388 	if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
22389 	    xmlGenericError(xmlGenericErrorContext, "IDC:   ['%s'] selector '%s'\n",
22390 		sto->matcher->aidc->def->name, sto->sel->xpath);
22391 	else
22392 	    xmlGenericError(xmlGenericErrorContext, "IDC:   ['%s'] field '%s'\n",
22393 		sto->matcher->aidc->def->name, sto->sel->xpath);
22394 #endif
22395 	if (nodeType == XML_ELEMENT_NODE)
22396 	    res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
22397 		vctxt->inode->localName, vctxt->inode->nsName);
22398 	else
22399 	    res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
22400 		vctxt->inode->localName, vctxt->inode->nsName);
22401 
22402 	if (res == -1) {
22403 	    VERROR_INT("xmlSchemaXPathEvaluate",
22404 		"calling xmlStreamPush()");
22405 	    return (-1);
22406 	}
22407 	if (res == 0)
22408 	    goto next_sto;
22409 	/*
22410 	* Full match.
22411 	*/
22412 #ifdef DEBUG_IDC
22413 	xmlGenericError(xmlGenericErrorContext, "IDC:     "
22414 	    "MATCH\n");
22415 #endif
22416 	/*
22417 	* Register a match in the state object history.
22418 	*/
22419 	if (sto->history == NULL) {
22420 	    sto->history = (int *) xmlMalloc(5 * sizeof(int));
22421 	    if (sto->history == NULL) {
22422 		xmlSchemaVErrMemory(NULL,
22423 		    "allocating the state object history", NULL);
22424 		return(-1);
22425 	    }
22426 	    sto->sizeHistory = 5;
22427 	} else if (sto->sizeHistory <= sto->nbHistory) {
22428 	    sto->sizeHistory *= 2;
22429 	    sto->history = (int *) xmlRealloc(sto->history,
22430 		sto->sizeHistory * sizeof(int));
22431 	    if (sto->history == NULL) {
22432 		xmlSchemaVErrMemory(NULL,
22433 		    "re-allocating the state object history", NULL);
22434 		return(-1);
22435 	    }
22436 	}
22437 	sto->history[sto->nbHistory++] = depth;
22438 
22439 #ifdef DEBUG_IDC
22440 	xmlGenericError(xmlGenericErrorContext, "IDC:       push match '%d'\n",
22441 	    vctxt->depth);
22442 #endif
22443 
22444 	if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22445 	    xmlSchemaIDCSelectPtr sel;
22446 	    /*
22447 	    * Activate state objects for the IDC fields of
22448 	    * the IDC selector.
22449 	    */
22450 #ifdef DEBUG_IDC
22451 	    xmlGenericError(xmlGenericErrorContext, "IDC:     "
22452 		"activating field states\n");
22453 #endif
22454 	    sel = sto->matcher->aidc->def->fields;
22455 	    while (sel != NULL) {
22456 		if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
22457 		    sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
22458 		    return (-1);
22459 		sel = sel->next;
22460 	    }
22461 	} else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22462 	    /*
22463 	    * An IDC key node was found by the IDC field.
22464 	    */
22465 #ifdef DEBUG_IDC
22466 	    xmlGenericError(xmlGenericErrorContext,
22467 		"IDC:     key found\n");
22468 #endif
22469 	    /*
22470 	    * Notify that the character value of this node is
22471 	    * needed.
22472 	    */
22473 	    if (resolved == 0) {
22474 		if ((vctxt->inode->flags &
22475 		    XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
22476 		vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
22477 	    }
22478 	    resolved++;
22479 	}
22480 next_sto:
22481 	if (sto->next == NULL) {
22482 	    /*
22483 	    * Evaluate field state objects created on this node as well.
22484 	    */
22485 	    head = first;
22486 	    sto = vctxt->xpathStates;
22487 	} else
22488 	    sto = sto->next;
22489     }
22490     return (resolved);
22491 }
22492 
22493 static const xmlChar *
xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,xmlChar ** buf,xmlSchemaPSVIIDCKeyPtr * seq,int count)22494 xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
22495 			      xmlChar **buf,
22496 			      xmlSchemaPSVIIDCKeyPtr *seq,
22497 			      int count)
22498 {
22499     int i, res;
22500     xmlChar *value = NULL;
22501 
22502     *buf = xmlStrdup(BAD_CAST "[");
22503     for (i = 0; i < count; i++) {
22504 	*buf = xmlStrcat(*buf, BAD_CAST "'");
22505 	res = xmlSchemaGetCanonValueWhtspExt(seq[i]->val,
22506 	    xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type),
22507 	    &value);
22508 	if (res == 0)
22509 	    *buf = xmlStrcat(*buf, BAD_CAST value);
22510 	else {
22511 	    VERROR_INT("xmlSchemaFormatIDCKeySequence",
22512 		"failed to compute a canonical value");
22513 	    *buf = xmlStrcat(*buf, BAD_CAST "???");
22514 	}
22515 	if (i < count -1)
22516 	    *buf = xmlStrcat(*buf, BAD_CAST "', ");
22517 	else
22518 	    *buf = xmlStrcat(*buf, BAD_CAST "'");
22519 	if (value != NULL) {
22520 	    xmlFree(value);
22521 	    value = NULL;
22522 	}
22523     }
22524     *buf = xmlStrcat(*buf, BAD_CAST "]");
22525 
22526     return (BAD_CAST *buf);
22527 }
22528 
22529 /**
22530  * xmlSchemaXPathPop:
22531  * @vctxt: the WXS validation context
22532  *
22533  * Pops all XPath states.
22534  *
22535  * Returns 0 on success and -1 on internal errors.
22536  */
22537 static int
xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)22538 xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)
22539 {
22540     xmlSchemaIDCStateObjPtr sto;
22541     int res;
22542 
22543     if (vctxt->xpathStates == NULL)
22544 	return(0);
22545     sto = vctxt->xpathStates;
22546     do {
22547 	res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22548 	if (res == -1)
22549 	    return (-1);
22550 	sto = sto->next;
22551     } while (sto != NULL);
22552     return(0);
22553 }
22554 
22555 /**
22556  * xmlSchemaXPathProcessHistory:
22557  * @vctxt: the WXS validation context
22558  * @type: the simple/complex type of the current node if any at all
22559  * @val: the precompiled value
22560  *
22561  * Processes and pops the history items of the IDC state objects.
22562  * IDC key-sequences are validated/created on IDC bindings.
22563  *
22564  * Returns 0 on success and -1 on internal errors.
22565  */
22566 static int
xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,int depth)22567 xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
22568 			     int depth)
22569 {
22570     xmlSchemaIDCStateObjPtr sto, nextsto;
22571     int res, matchDepth;
22572     xmlSchemaPSVIIDCKeyPtr key = NULL;
22573     xmlSchemaTypePtr type = vctxt->inode->typeDef, simpleType = NULL;
22574 
22575     if (vctxt->xpathStates == NULL)
22576 	return (0);
22577     sto = vctxt->xpathStates;
22578 
22579 #ifdef DEBUG_IDC
22580     {
22581 	xmlChar *str = NULL;
22582 	xmlGenericError(xmlGenericErrorContext,
22583 	    "IDC: BACK on %s, depth %d\n",
22584 	    xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22585 		vctxt->inode->localName), vctxt->depth);
22586 	FREE_AND_NULL(str)
22587     }
22588 #endif
22589     /*
22590     * Evaluate the state objects.
22591     */
22592     while (sto != NULL) {
22593 	res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22594 	if (res == -1) {
22595 	    VERROR_INT("xmlSchemaXPathProcessHistory",
22596 		"calling xmlStreamPop()");
22597 	    return (-1);
22598 	}
22599 #ifdef DEBUG_IDC
22600 	xmlGenericError(xmlGenericErrorContext, "IDC:   stream pop '%s'\n",
22601 	    sto->sel->xpath);
22602 #endif
22603 	if (sto->nbHistory == 0)
22604 	    goto deregister_check;
22605 
22606 	matchDepth = sto->history[sto->nbHistory -1];
22607 
22608 	/*
22609 	* Only matches at the current depth are of interest.
22610 	*/
22611 	if (matchDepth != depth) {
22612 	    sto = sto->next;
22613 	    continue;
22614 	}
22615 	if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22616 	    /*
22617 	    * NOTE: According to
22618 	    *   http://www.w3.org/Bugs/Public/show_bug.cgi?id=2198
22619 	    *   ... the simple-content of complex types is also allowed.
22620 	    */
22621 
22622 	    if (WXS_IS_COMPLEX(type)) {
22623 		if (WXS_HAS_SIMPLE_CONTENT(type)) {
22624 		    /*
22625 		    * Sanity check for complex types with simple content.
22626 		    */
22627 		    simpleType = type->contentTypeDef;
22628 		    if (simpleType == NULL) {
22629 			VERROR_INT("xmlSchemaXPathProcessHistory",
22630 			    "field resolves to a CT with simple content "
22631 			    "but the CT is missing the ST definition");
22632 			return (-1);
22633 		    }
22634 		} else
22635 		    simpleType = NULL;
22636 	    } else
22637 		simpleType = type;
22638 	    if (simpleType == NULL) {
22639 		xmlChar *str = NULL;
22640 
22641 		/*
22642 		* Not qualified if the field resolves to a node of non
22643 		* simple type.
22644 		*/
22645 		xmlSchemaCustomErr(ACTXT_CAST vctxt,
22646 		    XML_SCHEMAV_CVC_IDC, NULL,
22647 		    WXS_BASIC_CAST sto->matcher->aidc->def,
22648 		    "The XPath '%s' of a field of %s does evaluate to a node of "
22649 		    "non-simple type",
22650 		    sto->sel->xpath,
22651 		    xmlSchemaGetIDCDesignation(&str, sto->matcher->aidc->def));
22652 		FREE_AND_NULL(str);
22653 		sto->nbHistory--;
22654 		goto deregister_check;
22655 	    }
22656 
22657 	    if ((key == NULL) && (vctxt->inode->val == NULL)) {
22658 		/*
22659 		* Failed to provide the normalized value; maybe
22660 		* the value was invalid.
22661 		*/
22662 		VERROR(XML_SCHEMAV_CVC_IDC,
22663 		    WXS_BASIC_CAST sto->matcher->aidc->def,
22664 		    "Warning: No precomputed value available, the value "
22665 		    "was either invalid or something strange happend");
22666 		sto->nbHistory--;
22667 		goto deregister_check;
22668 	    } else {
22669 		xmlSchemaIDCMatcherPtr matcher = sto->matcher;
22670 		xmlSchemaPSVIIDCKeyPtr *keySeq;
22671 		int pos, idx;
22672 
22673 		/*
22674 		* The key will be anchored on the matcher's list of
22675 		* key-sequences. The position in this list is determined
22676 		* by the target node's depth relative to the matcher's
22677 		* depth of creation (i.e. the depth of the scope element).
22678 		*
22679 		* Element        Depth    Pos   List-entries
22680 		* <scope>          0              NULL
22681 		*   <bar>          1              NULL
22682 		*     <target/>    2       2      target
22683 		*   <bar>
22684                 * </scope>
22685 		*
22686 		* The size of the list is only dependant on the depth of
22687 		* the tree.
22688 		* An entry will be NULLed in selector_leave, i.e. when
22689 		* we hit the target's
22690 		*/
22691 		pos = sto->depth - matcher->depth;
22692 		idx = sto->sel->index;
22693 
22694 		/*
22695 		* Create/grow the array of key-sequences.
22696 		*/
22697 		if (matcher->keySeqs == NULL) {
22698 		    if (pos > 9)
22699 			matcher->sizeKeySeqs = pos * 2;
22700 		    else
22701 			matcher->sizeKeySeqs = 10;
22702 		    matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22703 			xmlMalloc(matcher->sizeKeySeqs *
22704 			sizeof(xmlSchemaPSVIIDCKeyPtr *));
22705 		    if (matcher->keySeqs == NULL) {
22706 			xmlSchemaVErrMemory(NULL,
22707 			    "allocating an array of key-sequences",
22708 			    NULL);
22709 			return(-1);
22710 		    }
22711 		    memset(matcher->keySeqs, 0,
22712 			matcher->sizeKeySeqs *
22713 			sizeof(xmlSchemaPSVIIDCKeyPtr *));
22714 		} else if (pos >= matcher->sizeKeySeqs) {
22715 		    int i = matcher->sizeKeySeqs;
22716 
22717 		    matcher->sizeKeySeqs *= 2;
22718 		    matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22719 			xmlRealloc(matcher->keySeqs,
22720 			matcher->sizeKeySeqs *
22721 			sizeof(xmlSchemaPSVIIDCKeyPtr *));
22722 		    if (matcher->keySeqs == NULL) {
22723 			xmlSchemaVErrMemory(NULL,
22724 			    "reallocating an array of key-sequences",
22725 			    NULL);
22726 			return (-1);
22727 		    }
22728 		    /*
22729 		    * The array needs to be NULLed.
22730 		    * TODO: Use memset?
22731 		    */
22732 		    for (; i < matcher->sizeKeySeqs; i++)
22733 			matcher->keySeqs[i] = NULL;
22734 		}
22735 
22736 		/*
22737 		* Get/create the key-sequence.
22738 		*/
22739 		keySeq = matcher->keySeqs[pos];
22740 		if (keySeq == NULL) {
22741 		    goto create_sequence;
22742 		} else if (keySeq[idx] != NULL) {
22743 		    xmlChar *str = NULL;
22744 		    /*
22745 		    * cvc-identity-constraint:
22746 		    * 3 For each node in the �target node set� all
22747 		    * of the {fields}, with that node as the context
22748 		    * node, evaluate to either an empty node-set or
22749 		    * a node-set with exactly one member, which must
22750 		    * have a simple type.
22751 		    *
22752 		    * The key was already set; report an error.
22753 		    */
22754 		    xmlSchemaCustomErr(ACTXT_CAST vctxt,
22755 			XML_SCHEMAV_CVC_IDC, NULL,
22756 			WXS_BASIC_CAST matcher->aidc->def,
22757 			"The XPath '%s' of a field of %s evaluates to a "
22758 			"node-set with more than one member",
22759 			sto->sel->xpath,
22760 			xmlSchemaGetIDCDesignation(&str, matcher->aidc->def));
22761 		    FREE_AND_NULL(str);
22762 		    sto->nbHistory--;
22763 		    goto deregister_check;
22764 		} else
22765 		    goto create_key;
22766 
22767 create_sequence:
22768 		/*
22769 		* Create a key-sequence.
22770 		*/
22771 		keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
22772 		    matcher->aidc->def->nbFields *
22773 		    sizeof(xmlSchemaPSVIIDCKeyPtr));
22774 		if (keySeq == NULL) {
22775 		    xmlSchemaVErrMemory(NULL,
22776 			"allocating an IDC key-sequence", NULL);
22777 		    return(-1);
22778 		}
22779 		memset(keySeq, 0, matcher->aidc->def->nbFields *
22780 		    sizeof(xmlSchemaPSVIIDCKeyPtr));
22781 		matcher->keySeqs[pos] = keySeq;
22782 create_key:
22783 		/*
22784 		* Create a key once per node only.
22785 		*/
22786 		if (key == NULL) {
22787 		    key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
22788 			sizeof(xmlSchemaPSVIIDCKey));
22789 		    if (key == NULL) {
22790 			xmlSchemaVErrMemory(NULL,
22791 			    "allocating a IDC key", NULL);
22792 			xmlFree(keySeq);
22793 			matcher->keySeqs[pos] = NULL;
22794 			return(-1);
22795 		    }
22796 		    /*
22797 		    * Consume the compiled value.
22798 		    */
22799 		    key->type = simpleType;
22800 		    key->val = vctxt->inode->val;
22801 		    vctxt->inode->val = NULL;
22802 		    /*
22803 		    * Store the key in a global list.
22804 		    */
22805 		    if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
22806 			xmlSchemaIDCFreeKey(key);
22807 			return (-1);
22808 		    }
22809 		}
22810 		keySeq[idx] = key;
22811 	    }
22812 	} else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22813 
22814 	    xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
22815 	    /* xmlSchemaPSVIIDCBindingPtr bind; */
22816 	    xmlSchemaPSVIIDCNodePtr ntItem;
22817 	    xmlSchemaIDCMatcherPtr matcher;
22818 	    xmlSchemaIDCPtr idc;
22819 	    xmlSchemaItemListPtr targets;
22820 	    int pos, i, j, nbKeys;
22821 	    /*
22822 	    * Here we have the following scenario:
22823 	    * An IDC 'selector' state object resolved to a target node,
22824 	    * during the time this target node was in the
22825 	    * ancestor-or-self axis, the 'field' state object(s) looked
22826 	    * out for matching nodes to create a key-sequence for this
22827 	    * target node. Now we are back to this target node and need
22828 	    * to put the key-sequence, together with the target node
22829 	    * itself, into the node-table of the corresponding IDC
22830 	    * binding.
22831 	    */
22832 	    matcher = sto->matcher;
22833 	    idc = matcher->aidc->def;
22834 	    nbKeys = idc->nbFields;
22835 	    pos = depth - matcher->depth;
22836 	    /*
22837 	    * Check if the matcher has any key-sequences at all, plus
22838 	    * if it has a key-sequence for the current target node.
22839 	    */
22840 	    if ((matcher->keySeqs == NULL) ||
22841 		(matcher->sizeKeySeqs <= pos)) {
22842 		if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22843 		    goto selector_key_error;
22844 		else
22845 		    goto selector_leave;
22846 	    }
22847 
22848 	    keySeq = &(matcher->keySeqs[pos]);
22849 	    if (*keySeq == NULL) {
22850 		if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22851 		    goto selector_key_error;
22852 		else
22853 		    goto selector_leave;
22854 	    }
22855 
22856 	    for (i = 0; i < nbKeys; i++) {
22857 		if ((*keySeq)[i] == NULL) {
22858 		    /*
22859 		    * Not qualified, if not all fields did resolve.
22860 		    */
22861 		    if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
22862 			/*
22863 			* All fields of a "key" IDC must resolve.
22864 			*/
22865 			goto selector_key_error;
22866 		    }
22867 		    goto selector_leave;
22868 		}
22869 	    }
22870 	    /*
22871 	    * All fields did resolve.
22872 	    */
22873 
22874 	    /*
22875 	    * 4.1 If the {identity-constraint category} is unique(/key),
22876 	    * then no two members of the �qualified node set� have
22877 	    * �key-sequences� whose members are pairwise equal, as
22878 	    * defined by Equal in [XML Schemas: Datatypes].
22879 	    *
22880 	    * Get the IDC binding from the matcher and check for
22881 	    * duplicate key-sequences.
22882 	    */
22883 #if 0
22884 	    bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
22885 #endif
22886 	    targets = xmlSchemaIDCAcquireTargetList(vctxt, matcher);
22887 	    if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
22888 		(targets->nbItems != 0)) {
22889 		xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
22890 
22891 		i = 0;
22892 		res = 0;
22893 		/*
22894 		* Compare the key-sequences, key by key.
22895 		*/
22896 		do {
22897 		    bkeySeq =
22898 			((xmlSchemaPSVIIDCNodePtr) targets->items[i])->keys;
22899 		    for (j = 0; j < nbKeys; j++) {
22900 			ckey = (*keySeq)[j];
22901 			bkey = bkeySeq[j];
22902 			res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
22903 			if (res == -1) {
22904 			    return (-1);
22905 			} else if (res == 0) {
22906 			    /*
22907 			    * One of the keys differs, so the key-sequence
22908 			    * won't be equal; get out.
22909 			    */
22910 			    break;
22911 			}
22912 		    }
22913 		    if (res == 1) {
22914 			/*
22915 			* Duplicate key-sequence found.
22916 			*/
22917 			break;
22918 		    }
22919 		    i++;
22920 		} while (i < targets->nbItems);
22921 		if (i != targets->nbItems) {
22922 		    xmlChar *str = NULL, *strB = NULL;
22923 		    /*
22924 		    * TODO: Try to report the key-sequence.
22925 		    */
22926 		    xmlSchemaCustomErr(ACTXT_CAST vctxt,
22927 			XML_SCHEMAV_CVC_IDC, NULL,
22928 			WXS_BASIC_CAST idc,
22929 			"Duplicate key-sequence %s in %s",
22930 			xmlSchemaFormatIDCKeySequence(vctxt, &str,
22931 			    (*keySeq), nbKeys),
22932 			xmlSchemaGetIDCDesignation(&strB, idc));
22933 		    FREE_AND_NULL(str);
22934 		    FREE_AND_NULL(strB);
22935 		    goto selector_leave;
22936 		}
22937 	    }
22938 	    /*
22939 	    * Add a node-table item to the IDC binding.
22940 	    */
22941 	    ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
22942 		sizeof(xmlSchemaPSVIIDCNode));
22943 	    if (ntItem == NULL) {
22944 		xmlSchemaVErrMemory(NULL,
22945 		    "allocating an IDC node-table item", NULL);
22946 		xmlFree(*keySeq);
22947 		*keySeq = NULL;
22948 		return(-1);
22949 	    }
22950 	    memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
22951 
22952 	    /*
22953 	    * Store the node-table item in a global list.
22954 	    */
22955 	    if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
22956 		if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
22957 		    xmlFree(ntItem);
22958 		    xmlFree(*keySeq);
22959 		    *keySeq = NULL;
22960 		    return (-1);
22961 		}
22962 		ntItem->nodeQNameID = -1;
22963 	    } else {
22964 		/*
22965 		* Save a cached QName for this node on the IDC node, to be
22966 		* able to report it, even if the node is not saved.
22967 		*/
22968 		ntItem->nodeQNameID = xmlSchemaVAddNodeQName(vctxt,
22969 		    vctxt->inode->localName, vctxt->inode->nsName);
22970 		if (ntItem->nodeQNameID == -1) {
22971 		    xmlFree(ntItem);
22972 		    xmlFree(*keySeq);
22973 		    *keySeq = NULL;
22974 		    return (-1);
22975 		}
22976 	    }
22977 	    /*
22978 	    * Init the node-table item: Save the node, position and
22979 	    * consume the key-sequence.
22980 	    */
22981 	    ntItem->node = vctxt->node;
22982 	    ntItem->nodeLine = vctxt->inode->nodeLine;
22983 	    ntItem->keys = *keySeq;
22984 	    *keySeq = NULL;
22985 #if 0
22986 	    if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1)
22987 #endif
22988 	    if (xmlSchemaItemListAdd(targets, ntItem) == -1) {
22989 		if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
22990 		    /*
22991 		    * Free the item, since keyref items won't be
22992 		    * put on a global list.
22993 		    */
22994 		    xmlFree(ntItem->keys);
22995 		    xmlFree(ntItem);
22996 		}
22997 		return (-1);
22998 	    }
22999 
23000 	    goto selector_leave;
23001 selector_key_error:
23002 	    {
23003 		xmlChar *str = NULL;
23004 		/*
23005 		* 4.2.1 (KEY) The �target node set� and the
23006 		* �qualified node set� are equal, that is, every
23007 		* member of the �target node set� is also a member
23008 		* of the �qualified node set� and vice versa.
23009 		*/
23010 		xmlSchemaCustomErr(ACTXT_CAST vctxt,
23011 		    XML_SCHEMAV_CVC_IDC, NULL,
23012 		    WXS_BASIC_CAST idc,
23013 		    "Not all fields of %s evaluate to a node",
23014 		    xmlSchemaGetIDCDesignation(&str, idc), NULL);
23015 		FREE_AND_NULL(str);
23016 	    }
23017 selector_leave:
23018 	    /*
23019 	    * Free the key-sequence if not added to the IDC table.
23020 	    */
23021 	    if ((keySeq != NULL) && (*keySeq != NULL)) {
23022 		xmlFree(*keySeq);
23023 		*keySeq = NULL;
23024 	    }
23025 	} /* if selector */
23026 
23027 	sto->nbHistory--;
23028 
23029 deregister_check:
23030 	/*
23031 	* Deregister state objects if they reach the depth of creation.
23032 	*/
23033 	if ((sto->nbHistory == 0) && (sto->depth == depth)) {
23034 #ifdef DEBUG_IDC
23035 	    xmlGenericError(xmlGenericErrorContext, "IDC:   STO pop '%s'\n",
23036 		sto->sel->xpath);
23037 #endif
23038 	    if (vctxt->xpathStates != sto) {
23039 		VERROR_INT("xmlSchemaXPathProcessHistory",
23040 		    "The state object to be removed is not the first "
23041 		    "in the list");
23042 	    }
23043 	    nextsto = sto->next;
23044 	    /*
23045 	    * Unlink from the list of active XPath state objects.
23046 	    */
23047 	    vctxt->xpathStates = sto->next;
23048 	    sto->next = vctxt->xpathStatePool;
23049 	    /*
23050 	    * Link it to the pool of reusable state objects.
23051 	    */
23052 	    vctxt->xpathStatePool = sto;
23053 	    sto = nextsto;
23054 	} else
23055 	    sto = sto->next;
23056     } /* while (sto != NULL) */
23057     return (0);
23058 }
23059 
23060 /**
23061  * xmlSchemaIDCRegisterMatchers:
23062  * @vctxt: the WXS validation context
23063  * @elemDecl: the element declaration
23064  *
23065  * Creates helper objects to evaluate IDC selectors/fields
23066  * successively.
23067  *
23068  * Returns 0 if OK and -1 on internal errors.
23069  */
23070 static int
xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,xmlSchemaElementPtr elemDecl)23071 xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
23072 			     xmlSchemaElementPtr elemDecl)
23073 {
23074     xmlSchemaIDCMatcherPtr matcher, last = NULL;
23075     xmlSchemaIDCPtr idc, refIdc;
23076     xmlSchemaIDCAugPtr aidc;
23077 
23078     idc = (xmlSchemaIDCPtr) elemDecl->idcs;
23079     if (idc == NULL)
23080 	return (0);
23081 
23082 #ifdef DEBUG_IDC
23083     {
23084 	xmlChar *str = NULL;
23085 	xmlGenericError(xmlGenericErrorContext,
23086 	    "IDC: REGISTER on %s, depth %d\n",
23087 	    (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
23088 		vctxt->inode->localName), vctxt->depth);
23089 	FREE_AND_NULL(str)
23090     }
23091 #endif
23092     if (vctxt->inode->idcMatchers != NULL) {
23093 	VERROR_INT("xmlSchemaIDCRegisterMatchers",
23094 	    "The chain of IDC matchers is expected to be empty");
23095 	return (-1);
23096     }
23097     do {
23098 	if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23099 	    /*
23100 	    * Since IDCs bubbles are expensive we need to know the
23101 	    * depth at which the bubbles should stop; this will be
23102 	    * the depth of the top-most keyref IDC. If no keyref
23103 	    * references a key/unique IDC, the keyrefDepth will
23104 	    * be -1, indicating that no bubbles are needed.
23105 	    */
23106 	    refIdc = (xmlSchemaIDCPtr) idc->ref->item;
23107 	    if (refIdc != NULL) {
23108 		/*
23109 		* Remember that we have keyrefs on this node.
23110 		*/
23111 		vctxt->inode->hasKeyrefs = 1;
23112 		/*
23113 		* Lookup the referenced augmented IDC info.
23114 		*/
23115 		aidc = vctxt->aidcs;
23116 		while (aidc != NULL) {
23117 		    if (aidc->def == refIdc)
23118 			break;
23119 		    aidc = aidc->next;
23120 		}
23121 		if (aidc == NULL) {
23122 		    VERROR_INT("xmlSchemaIDCRegisterMatchers",
23123 			"Could not find an augmented IDC item for an IDC "
23124 			"definition");
23125 		    return (-1);
23126 		}
23127 		if ((aidc->keyrefDepth == -1) ||
23128 		    (vctxt->depth < aidc->keyrefDepth))
23129 		    aidc->keyrefDepth = vctxt->depth;
23130 	    }
23131 	}
23132 	/*
23133 	* Lookup the augmented IDC item for the IDC definition.
23134 	*/
23135 	aidc = vctxt->aidcs;
23136 	while (aidc != NULL) {
23137 	    if (aidc->def == idc)
23138 		break;
23139 	    aidc = aidc->next;
23140 	}
23141 	if (aidc == NULL) {
23142 	    VERROR_INT("xmlSchemaIDCRegisterMatchers",
23143 		"Could not find an augmented IDC item for an IDC definition");
23144 	    return (-1);
23145 	}
23146 	/*
23147 	* Create an IDC matcher for every IDC definition.
23148 	*/
23149 	if (vctxt->idcMatcherCache != NULL) {
23150 	    /*
23151 	    * Reuse a cached matcher.
23152 	    */
23153 	    matcher = vctxt->idcMatcherCache;
23154 	    vctxt->idcMatcherCache = matcher->nextCached;
23155 	    matcher->nextCached = NULL;
23156 	} else {
23157 	    matcher = (xmlSchemaIDCMatcherPtr)
23158 		xmlMalloc(sizeof(xmlSchemaIDCMatcher));
23159 	    if (matcher == NULL) {
23160 		xmlSchemaVErrMemory(vctxt,
23161 		    "allocating an IDC matcher", NULL);
23162 		return (-1);
23163 	    }
23164 	    memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
23165 	}
23166 	if (last == NULL)
23167 	    vctxt->inode->idcMatchers = matcher;
23168 	else
23169 	    last->next = matcher;
23170 	last = matcher;
23171 
23172 	matcher->type = IDC_MATCHER;
23173 	matcher->depth = vctxt->depth;
23174 	matcher->aidc = aidc;
23175 	matcher->idcType = aidc->def->type;
23176 #ifdef DEBUG_IDC
23177 	xmlGenericError(xmlGenericErrorContext, "IDC:   register matcher\n");
23178 #endif
23179 	/*
23180 	* Init the automaton state object.
23181 	*/
23182 	if (xmlSchemaIDCAddStateObject(vctxt, matcher,
23183 	    idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
23184 	    return (-1);
23185 
23186 	idc = idc->next;
23187     } while (idc != NULL);
23188     return (0);
23189 }
23190 
23191 static int
xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,xmlSchemaNodeInfoPtr ielem)23192 xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,
23193 			   xmlSchemaNodeInfoPtr ielem)
23194 {
23195     xmlSchemaPSVIIDCBindingPtr bind;
23196     int res, i, j, k, nbTargets, nbFields, nbDupls, nbNodeTable;
23197     xmlSchemaPSVIIDCKeyPtr *keys, *ntkeys;
23198     xmlSchemaPSVIIDCNodePtr *targets, *dupls;
23199 
23200     xmlSchemaIDCMatcherPtr matcher = ielem->idcMatchers;
23201     /* vctxt->createIDCNodeTables */
23202     while (matcher != NULL) {
23203 	/*
23204 	* Skip keyref IDCs and empty IDC target-lists.
23205 	*/
23206 	if ((matcher->aidc->def->type == XML_SCHEMA_TYPE_IDC_KEYREF) ||
23207 	    WXS_ILIST_IS_EMPTY(matcher->targets))
23208 	{
23209 	    matcher = matcher->next;
23210 	    continue;
23211 	}
23212 	/*
23213 	* If we _want_ the IDC node-table to be created in any case
23214 	* then do so. Otherwise create them only if keyrefs need them.
23215 	*/
23216 	if ((! vctxt->createIDCNodeTables) &&
23217 	    ((matcher->aidc->keyrefDepth == -1) ||
23218 	     (matcher->aidc->keyrefDepth > vctxt->depth)))
23219 	{
23220 	    matcher = matcher->next;
23221 	    continue;
23222 	}
23223 	/*
23224 	* Get/create the IDC binding on this element for the IDC definition.
23225 	*/
23226 	bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
23227 
23228 	if (! WXS_ILIST_IS_EMPTY(bind->dupls)) {
23229 	    dupls = (xmlSchemaPSVIIDCNodePtr *) bind->dupls->items;
23230 	    nbDupls = bind->dupls->nbItems;
23231 	} else {
23232 	    dupls = NULL;
23233 	    nbDupls = 0;
23234 	}
23235 	if (bind->nodeTable != NULL) {
23236 	    nbNodeTable = bind->nbNodes;
23237 	} else {
23238 	    nbNodeTable = 0;
23239 	}
23240 
23241 	if ((nbNodeTable == 0) && (nbDupls == 0)) {
23242 	    /*
23243 	    * Transfer all IDC target-nodes to the IDC node-table.
23244 	    */
23245 	    bind->nodeTable =
23246 		(xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23247 	    bind->sizeNodes = matcher->targets->sizeItems;
23248 	    bind->nbNodes = matcher->targets->nbItems;
23249 
23250 	    matcher->targets->items = NULL;
23251 	    matcher->targets->sizeItems = 0;
23252 	    matcher->targets->nbItems = 0;
23253 	} else {
23254 	    /*
23255 	    * Compare the key-sequences and add to the IDC node-table.
23256 	    */
23257 	    nbTargets = matcher->targets->nbItems;
23258 	    targets = (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23259 	    nbFields = matcher->aidc->def->nbFields;
23260 	    i = 0;
23261 	    do {
23262 		keys = targets[i]->keys;
23263 		if (nbDupls) {
23264 		    /*
23265 		    * Search in already found duplicates first.
23266 		    */
23267 		    j = 0;
23268 		    do {
23269 			if (nbFields == 1) {
23270 			    res = xmlSchemaAreValuesEqual(keys[0]->val,
23271 				dupls[j]->keys[0]->val);
23272 			    if (res == -1)
23273 				goto internal_error;
23274 			    if (res == 1) {
23275 				/*
23276 				* Equal key-sequence.
23277 				*/
23278 				goto next_target;
23279 			    }
23280 			} else {
23281 			    res = 0;
23282 			    ntkeys = dupls[j]->keys;
23283 			    for (k = 0; k < nbFields; k++) {
23284 				res = xmlSchemaAreValuesEqual(keys[k]->val,
23285 				    ntkeys[k]->val);
23286 				if (res == -1)
23287 				    goto internal_error;
23288 				if (res == 0) {
23289 				    /*
23290 				    * One of the keys differs.
23291 				    */
23292 				    break;
23293 				}
23294 			    }
23295 			    if (res == 1) {
23296 				/*
23297 				* Equal key-sequence found.
23298 				*/
23299 				goto next_target;
23300 			    }
23301 			}
23302 			j++;
23303 		    } while (j < nbDupls);
23304 		}
23305 		if (nbNodeTable) {
23306 		    j = 0;
23307 		    do {
23308 			if (nbFields == 1) {
23309 			    res = xmlSchemaAreValuesEqual(keys[0]->val,
23310 				bind->nodeTable[j]->keys[0]->val);
23311 			    if (res == -1)
23312 				goto internal_error;
23313 			    if (res == 0) {
23314 				/*
23315 				* The key-sequence differs.
23316 				*/
23317 				goto next_node_table_entry;
23318 			    }
23319 			} else {
23320 			    res = 0;
23321 			    ntkeys = bind->nodeTable[j]->keys;
23322 			    for (k = 0; k < nbFields; k++) {
23323 				res = xmlSchemaAreValuesEqual(keys[k]->val,
23324 				    ntkeys[k]->val);
23325 				if (res == -1)
23326 				    goto internal_error;
23327 				if (res == 0) {
23328 				    /*
23329 				    * One of the keys differs.
23330 				    */
23331 				    goto next_node_table_entry;
23332 				}
23333 			    }
23334 			}
23335 			/*
23336 			* Add the duplicate to the list of duplicates.
23337 			*/
23338 			if (bind->dupls == NULL) {
23339 			    bind->dupls = xmlSchemaItemListCreate();
23340 			    if (bind->dupls == NULL)
23341 				goto internal_error;
23342 			}
23343 			if (xmlSchemaItemListAdd(bind->dupls, bind->nodeTable[j]) == -1)
23344 			    goto internal_error;
23345 			/*
23346 			* Remove the duplicate entry from the IDC node-table.
23347 			*/
23348 			bind->nodeTable[j] = bind->nodeTable[bind->nbNodes -1];
23349 			bind->nbNodes--;
23350 
23351 			goto next_target;
23352 
23353 next_node_table_entry:
23354 			j++;
23355 		    } while (j < nbNodeTable);
23356 		}
23357 		/*
23358 		* If everything is fine, then add the IDC target-node to
23359 		* the IDC node-table.
23360 		*/
23361 		if (xmlSchemaIDCAppendNodeTableItem(bind, targets[i]) == -1)
23362 		    goto internal_error;
23363 
23364 next_target:
23365 		i++;
23366 	    } while (i < nbTargets);
23367 	}
23368 	matcher = matcher->next;
23369     }
23370     return(0);
23371 
23372 internal_error:
23373     return(-1);
23374 }
23375 
23376 /**
23377  * xmlSchemaBubbleIDCNodeTables:
23378  * @depth: the current tree depth
23379  *
23380  * Merges IDC bindings of an element at @depth into the corresponding IDC
23381  * bindings of its parent element. If a duplicate note-table entry is found,
23382  * both, the parent node-table entry and child entry are discarded from the
23383  * node-table of the parent.
23384  *
23385  * Returns 0 if OK and -1 on internal errors.
23386  */
23387 static int
xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)23388 xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
23389 {
23390     xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
23391     xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL; /* parent IDC bindings. */
23392     xmlSchemaPSVIIDCNodePtr node, parNode = NULL, *dupls, *parNodes; /* node-table entries. */
23393     xmlSchemaIDCAugPtr aidc;
23394     int i, j, k, ret = 0, nbFields, oldNum, oldDupls;
23395 
23396     bind = vctxt->inode->idcTable;
23397     if (bind == NULL) {
23398 	/* Fine, no table, no bubbles. */
23399 	return (0);
23400     }
23401 
23402     parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
23403     /*
23404     * Walk all bindings; create new or add to existing bindings.
23405     * Remove duplicate key-sequences.
23406     */
23407     while (bind != NULL) {
23408 
23409 	if ((bind->nbNodes == 0) && WXS_ILIST_IS_EMPTY(bind->dupls))
23410 	    goto next_binding;
23411 	/*
23412 	* Check if the key/unique IDC table needs to be bubbled.
23413 	*/
23414 	if (! vctxt->createIDCNodeTables) {
23415 	    aidc = vctxt->aidcs;
23416 	    do {
23417 		if (aidc->def == bind->definition) {
23418 		    if ((aidc->keyrefDepth == -1) ||
23419 			(aidc->keyrefDepth >= vctxt->depth)) {
23420 			goto next_binding;
23421 		    }
23422 		    break;
23423 		}
23424 		aidc = aidc->next;
23425 	    } while (aidc != NULL);
23426 	}
23427 
23428 	if (parTable != NULL)
23429 	    parBind = *parTable;
23430 	/*
23431 	* Search a matching parent binding for the
23432 	* IDC definition.
23433 	*/
23434 	while (parBind != NULL) {
23435 	    if (parBind->definition == bind->definition)
23436 		break;
23437 	    parBind = parBind->next;
23438 	}
23439 
23440 	if (parBind != NULL) {
23441 	    /*
23442 	    * Compare every node-table entry of the child node,
23443 	    * i.e. the key-sequence within, ...
23444 	    */
23445 	    oldNum = parBind->nbNodes; /* Skip newly added items. */
23446 
23447 	    if (! WXS_ILIST_IS_EMPTY(parBind->dupls)) {
23448 		oldDupls = parBind->dupls->nbItems;
23449 		dupls = (xmlSchemaPSVIIDCNodePtr *) parBind->dupls->items;
23450 	    } else {
23451 		dupls = NULL;
23452 		oldDupls = 0;
23453 	    }
23454 
23455 	    parNodes = parBind->nodeTable;
23456 	    nbFields = bind->definition->nbFields;
23457 
23458 	    for (i = 0; i < bind->nbNodes; i++) {
23459 		node = bind->nodeTable[i];
23460 		if (node == NULL)
23461 		    continue;
23462 		/*
23463 		* ...with every key-sequence of the parent node, already
23464 		* evaluated to be a duplicate key-sequence.
23465 		*/
23466 		if (oldDupls) {
23467 		    j = 0;
23468 		    while (j < oldDupls) {
23469 			if (nbFields == 1) {
23470 			    ret = xmlSchemaAreValuesEqual(
23471 				node->keys[0]->val,
23472 				dupls[j]->keys[0]->val);
23473 			    if (ret == -1)
23474 				goto internal_error;
23475 			    if (ret == 0) {
23476 				j++;
23477 				continue;
23478 			    }
23479 			} else {
23480 			    parNode = dupls[j];
23481 			    for (k = 0; k < nbFields; k++) {
23482 				ret = xmlSchemaAreValuesEqual(
23483 				    node->keys[k]->val,
23484 				    parNode->keys[k]->val);
23485 				if (ret == -1)
23486 				    goto internal_error;
23487 				if (ret == 0)
23488 				    break;
23489 			    }
23490 			}
23491 			if (ret == 1)
23492 			    /* Duplicate found. */
23493 			    break;
23494 			j++;
23495 		    }
23496 		    if (j != oldDupls) {
23497 			/* Duplicate found. Skip this entry. */
23498 			continue;
23499 		    }
23500 		}
23501 		/*
23502 		* ... and with every key-sequence of the parent node.
23503 		*/
23504 		if (oldNum) {
23505 		    j = 0;
23506 		    while (j < oldNum) {
23507 			parNode = parNodes[j];
23508 			if (nbFields == 1) {
23509 			    ret = xmlSchemaAreValuesEqual(
23510 				node->keys[0]->val,
23511 				parNode->keys[0]->val);
23512 			    if (ret == -1)
23513 				goto internal_error;
23514 			    if (ret == 0) {
23515 				j++;
23516 				continue;
23517 			    }
23518 			} else {
23519 			    for (k = 0; k < nbFields; k++) {
23520 				ret = xmlSchemaAreValuesEqual(
23521 				    node->keys[k]->val,
23522 				    parNode->keys[k]->val);
23523 				if (ret == -1)
23524 				    goto internal_error;
23525 				if (ret == 0)
23526 				    break;
23527 			    }
23528 			}
23529 			if (ret == 1)
23530 			    /* Duplicate found. */
23531 			    break;
23532 			j++;
23533 		    }
23534 		    if (j != oldNum) {
23535 			/*
23536 			* Handle duplicates. Move the duplicate in
23537 			* the parent's node-table to the list of
23538 			* duplicates.
23539 			*/
23540 			oldNum--;
23541 			parBind->nbNodes--;
23542 			/*
23543 			* Move last old item to pos of duplicate.
23544 			*/
23545 			parNodes[j] = parNodes[oldNum];
23546 
23547 			if (parBind->nbNodes != oldNum) {
23548 			    /*
23549 			    * If new items exist, move last new item to
23550 			    * last of old items.
23551 			    */
23552 			    parNodes[oldNum] =
23553 				parNodes[parBind->nbNodes];
23554 			}
23555 			if (parBind->dupls == NULL) {
23556 			    parBind->dupls = xmlSchemaItemListCreate();
23557 			    if (parBind->dupls == NULL)
23558 				goto internal_error;
23559 			}
23560 			xmlSchemaItemListAdd(parBind->dupls, parNode);
23561 		    } else {
23562 			/*
23563 			* Add the node-table entry (node and key-sequence) of
23564 			* the child node to the node table of the parent node.
23565 			*/
23566 			if (parBind->nodeTable == NULL) {
23567 			    parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23568 				xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
23569 			    if (parBind->nodeTable == NULL) {
23570 				xmlSchemaVErrMemory(NULL,
23571 				    "allocating IDC list of node-table items", NULL);
23572 				goto internal_error;
23573 			    }
23574 			    parBind->sizeNodes = 1;
23575 			} else if (parBind->nbNodes >= parBind->sizeNodes) {
23576 			    parBind->sizeNodes *= 2;
23577 			    parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23578 				xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
23579 				sizeof(xmlSchemaPSVIIDCNodePtr));
23580 			    if (parBind->nodeTable == NULL) {
23581 				xmlSchemaVErrMemory(NULL,
23582 				    "re-allocating IDC list of node-table items", NULL);
23583 				goto internal_error;
23584 			    }
23585 			}
23586 			parNodes = parBind->nodeTable;
23587 			/*
23588 			* Append the new node-table entry to the 'new node-table
23589 			* entries' section.
23590 			*/
23591 			parNodes[parBind->nbNodes++] = node;
23592 		    }
23593 
23594 		}
23595 
23596 	    }
23597 	} else {
23598 	    /*
23599 	    * No binding for the IDC was found: create a new one and
23600 	    * copy all node-tables.
23601 	    */
23602 	    parBind = xmlSchemaIDCNewBinding(bind->definition);
23603 	    if (parBind == NULL)
23604 		goto internal_error;
23605 
23606 	    /*
23607 	    * TODO: Hmm, how to optimize the initial number of
23608 	    * allocated entries?
23609 	    */
23610 	    if (bind->nbNodes != 0) {
23611 		/*
23612 		* Add all IDC node-table entries.
23613 		*/
23614 		if (! vctxt->psviExposeIDCNodeTables) {
23615 		    /*
23616 		    * Just move the entries.
23617 		    * NOTE: this is quite save here, since
23618 		    * all the keyref lookups have already been
23619 		    * performed.
23620 		    */
23621 		    parBind->nodeTable = bind->nodeTable;
23622 		    bind->nodeTable = NULL;
23623 		    parBind->sizeNodes = bind->sizeNodes;
23624 		    bind->sizeNodes = 0;
23625 		    parBind->nbNodes = bind->nbNodes;
23626 		    bind->nbNodes = 0;
23627 		} else {
23628 		    /*
23629 		    * Copy the entries.
23630 		    */
23631 		    parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23632 			xmlMalloc(bind->nbNodes *
23633 			sizeof(xmlSchemaPSVIIDCNodePtr));
23634 		    if (parBind->nodeTable == NULL) {
23635 			xmlSchemaVErrMemory(NULL,
23636 			    "allocating an array of IDC node-table "
23637 			    "items", NULL);
23638 			xmlSchemaIDCFreeBinding(parBind);
23639 			goto internal_error;
23640 		    }
23641 		    parBind->sizeNodes = bind->nbNodes;
23642 		    parBind->nbNodes = bind->nbNodes;
23643 		    memcpy(parBind->nodeTable, bind->nodeTable,
23644 			bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
23645 		}
23646 	    }
23647 	    if (bind->dupls) {
23648 		/*
23649 		* Move the duplicates.
23650 		*/
23651 		if (parBind->dupls != NULL)
23652 		    xmlSchemaItemListFree(parBind->dupls);
23653 		parBind->dupls = bind->dupls;
23654 		bind->dupls = NULL;
23655 	    }
23656 	    if (*parTable == NULL)
23657 		*parTable = parBind;
23658 	    else {
23659 		parBind->next = *parTable;
23660 		*parTable = parBind;
23661 	    }
23662 	}
23663 
23664 next_binding:
23665 	bind = bind->next;
23666     }
23667     return (0);
23668 
23669 internal_error:
23670     return(-1);
23671 }
23672 
23673 /**
23674  * xmlSchemaCheckCVCIDCKeyRef:
23675  * @vctxt: the WXS validation context
23676  * @elemDecl: the element declaration
23677  *
23678  * Check the cvc-idc-keyref constraints.
23679  */
23680 static int
xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)23681 xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
23682 {
23683     xmlSchemaIDCMatcherPtr matcher;
23684     xmlSchemaPSVIIDCBindingPtr bind;
23685 
23686     matcher = vctxt->inode->idcMatchers;
23687     /*
23688     * Find a keyref.
23689     */
23690     while (matcher != NULL) {
23691 	if ((matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) &&
23692 	    matcher->targets &&
23693 	    matcher->targets->nbItems)
23694 	{
23695 	    int i, j, k, res, nbFields, hasDupls;
23696 	    xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
23697 	    xmlSchemaPSVIIDCNodePtr refNode = NULL;
23698 
23699 	    nbFields = matcher->aidc->def->nbFields;
23700 
23701 	    /*
23702 	    * Find the IDC node-table for the referenced IDC key/unique.
23703 	    */
23704 	    bind = vctxt->inode->idcTable;
23705 	    while (bind != NULL) {
23706 		if ((xmlSchemaIDCPtr) matcher->aidc->def->ref->item ==
23707 		    bind->definition)
23708 		    break;
23709 		bind = bind->next;
23710 	    }
23711 	    hasDupls = (bind && bind->dupls && bind->dupls->nbItems) ? 1 : 0;
23712 	    /*
23713 	    * Search for a matching key-sequences.
23714 	    */
23715 	    for (i = 0; i < matcher->targets->nbItems; i++) {
23716 		res = 0;
23717 		refNode = matcher->targets->items[i];
23718 		if (bind != NULL) {
23719 		    refKeys = refNode->keys;
23720 		    for (j = 0; j < bind->nbNodes; j++) {
23721 			keys = bind->nodeTable[j]->keys;
23722 			for (k = 0; k < nbFields; k++) {
23723 			    res = xmlSchemaAreValuesEqual(keys[k]->val,
23724 				refKeys[k]->val);
23725 			    if (res == 0)
23726 				break;
23727 			    else if (res == -1) {
23728 				return (-1);
23729 			    }
23730 			}
23731 			if (res == 1) {
23732 			    /*
23733 			    * Match found.
23734 			    */
23735 			    break;
23736 			}
23737 		    }
23738 		    if ((res == 0) && hasDupls) {
23739 			/*
23740 			* Search in duplicates
23741 			*/
23742 			for (j = 0; j < bind->dupls->nbItems; j++) {
23743 			    keys = ((xmlSchemaPSVIIDCNodePtr)
23744 				bind->dupls->items[j])->keys;
23745 			    for (k = 0; k < nbFields; k++) {
23746 				res = xmlSchemaAreValuesEqual(keys[k]->val,
23747 				    refKeys[k]->val);
23748 				if (res == 0)
23749 				    break;
23750 				else if (res == -1) {
23751 				    return (-1);
23752 				}
23753 			    }
23754 			    if (res == 1) {
23755 				/*
23756 				* Match in duplicates found.
23757 				*/
23758 				xmlChar *str = NULL, *strB = NULL;
23759 				xmlSchemaKeyrefErr(vctxt,
23760 				    XML_SCHEMAV_CVC_IDC, refNode,
23761 				    (xmlSchemaTypePtr) matcher->aidc->def,
23762 				    "More than one match found for "
23763 				    "key-sequence %s of keyref '%s'",
23764 				    xmlSchemaFormatIDCKeySequence(vctxt, &str,
23765 					refNode->keys, nbFields),
23766 				    xmlSchemaGetComponentQName(&strB,
23767 					matcher->aidc->def));
23768 				FREE_AND_NULL(str);
23769 				FREE_AND_NULL(strB);
23770 				break;
23771 			    }
23772 			}
23773 		    }
23774 		}
23775 
23776 		if (res == 0) {
23777 		    xmlChar *str = NULL, *strB = NULL;
23778 		    xmlSchemaKeyrefErr(vctxt,
23779 			XML_SCHEMAV_CVC_IDC, refNode,
23780 			(xmlSchemaTypePtr) matcher->aidc->def,
23781 			"No match found for key-sequence %s of keyref '%s'",
23782 			xmlSchemaFormatIDCKeySequence(vctxt, &str,
23783 			    refNode->keys, nbFields),
23784 			xmlSchemaGetComponentQName(&strB, matcher->aidc->def));
23785 		    FREE_AND_NULL(str);
23786 		    FREE_AND_NULL(strB);
23787 		}
23788 	    }
23789 	}
23790 	matcher = matcher->next;
23791     }
23792     /* TODO: Return an error if any error encountered. */
23793     return (0);
23794 }
23795 
23796 /************************************************************************
23797  * 									*
23798  * 			XML Reader validation code                      *
23799  * 									*
23800  ************************************************************************/
23801 
23802 static xmlSchemaAttrInfoPtr
xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)23803 xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
23804 {
23805     xmlSchemaAttrInfoPtr iattr;
23806     /*
23807     * Grow/create list of attribute infos.
23808     */
23809     if (vctxt->attrInfos == NULL) {
23810 	vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23811 	    xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
23812 	vctxt->sizeAttrInfos = 1;
23813 	if (vctxt->attrInfos == NULL) {
23814 	    xmlSchemaVErrMemory(vctxt,
23815 		"allocating attribute info list", NULL);
23816 	    return (NULL);
23817 	}
23818     } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
23819 	vctxt->sizeAttrInfos++;
23820 	vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23821 	    xmlRealloc(vctxt->attrInfos,
23822 		vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
23823 	if (vctxt->attrInfos == NULL) {
23824 	    xmlSchemaVErrMemory(vctxt,
23825 		"re-allocating attribute info list", NULL);
23826 	    return (NULL);
23827 	}
23828     } else {
23829 	iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
23830 	if (iattr->localName != NULL) {
23831 	    VERROR_INT("xmlSchemaGetFreshAttrInfo",
23832 		"attr info not cleared");
23833 	    return (NULL);
23834 	}
23835 	iattr->nodeType = XML_ATTRIBUTE_NODE;
23836 	return (iattr);
23837     }
23838     /*
23839     * Create an attribute info.
23840     */
23841     iattr = (xmlSchemaAttrInfoPtr)
23842 	xmlMalloc(sizeof(xmlSchemaAttrInfo));
23843     if (iattr == NULL) {
23844 	xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
23845 	return (NULL);
23846     }
23847     memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
23848     iattr->nodeType = XML_ATTRIBUTE_NODE;
23849     vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
23850 
23851     return (iattr);
23852 }
23853 
23854 static int
xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,xmlNodePtr attrNode,int nodeLine,const xmlChar * localName,const xmlChar * nsName,int ownedNames,xmlChar * value,int ownedValue)23855 xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
23856 			xmlNodePtr attrNode,
23857 			int nodeLine,
23858 			const xmlChar *localName,
23859 			const xmlChar *nsName,
23860 			int ownedNames,
23861 			xmlChar *value,
23862 			int ownedValue)
23863 {
23864     xmlSchemaAttrInfoPtr attr;
23865 
23866     attr = xmlSchemaGetFreshAttrInfo(vctxt);
23867     if (attr == NULL) {
23868 	VERROR_INT("xmlSchemaPushAttribute",
23869 	    "calling xmlSchemaGetFreshAttrInfo()");
23870 	return (-1);
23871     }
23872     attr->node = attrNode;
23873     attr->nodeLine = nodeLine;
23874     attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
23875     attr->localName = localName;
23876     attr->nsName = nsName;
23877     if (ownedNames)
23878 	attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
23879     /*
23880     * Evaluate if it's an XSI attribute.
23881     */
23882     if (nsName != NULL) {
23883 	if (xmlStrEqual(localName, BAD_CAST "nil")) {
23884 	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23885 		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
23886 	    }
23887 	} else if (xmlStrEqual(localName, BAD_CAST "type")) {
23888 	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23889 		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
23890 	    }
23891 	} else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
23892 	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23893 		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
23894 	    }
23895 	} else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
23896 	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23897 		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
23898 	    }
23899 	} else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
23900 	    attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
23901 	}
23902     }
23903     attr->value = value;
23904     if (ownedValue)
23905 	attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
23906     if (attr->metaType != 0)
23907 	attr->state = XML_SCHEMAS_ATTR_META;
23908     return (0);
23909 }
23910 
23911 /**
23912  * xmlSchemaClearElemInfo:
23913  * @vctxt: the WXS validation context
23914  * @ielem: the element information item
23915  */
23916 static void
xmlSchemaClearElemInfo(xmlSchemaValidCtxtPtr vctxt,xmlSchemaNodeInfoPtr ielem)23917 xmlSchemaClearElemInfo(xmlSchemaValidCtxtPtr vctxt,
23918 		       xmlSchemaNodeInfoPtr ielem)
23919 {
23920     ielem->hasKeyrefs = 0;
23921     ielem->appliedXPath = 0;
23922     if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
23923 	FREE_AND_NULL(ielem->localName);
23924 	FREE_AND_NULL(ielem->nsName);
23925     } else {
23926 	ielem->localName = NULL;
23927 	ielem->nsName = NULL;
23928     }
23929     if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
23930 	FREE_AND_NULL(ielem->value);
23931     } else {
23932 	ielem->value = NULL;
23933     }
23934     if (ielem->val != NULL) {
23935 	/*
23936 	* PSVI TODO: Be careful not to free it when the value is
23937 	* exposed via PSVI.
23938 	*/
23939 	xmlSchemaFreeValue(ielem->val);
23940 	ielem->val = NULL;
23941     }
23942     if (ielem->idcMatchers != NULL) {
23943 	/*
23944 	* REVISIT OPTIMIZE TODO: Use a pool of IDC matchers.
23945 	*   Does it work?
23946 	*/
23947 	xmlSchemaIDCReleaseMatcherList(vctxt, ielem->idcMatchers);
23948 #if 0
23949 	xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
23950 #endif
23951 	ielem->idcMatchers = NULL;
23952     }
23953     if (ielem->idcTable != NULL) {
23954 	/*
23955 	* OPTIMIZE TODO: Use a pool of IDC tables??.
23956 	*/
23957 	xmlSchemaIDCFreeIDCTable(ielem->idcTable);
23958 	ielem->idcTable = NULL;
23959     }
23960     if (ielem->regexCtxt != NULL) {
23961 	xmlRegFreeExecCtxt(ielem->regexCtxt);
23962 	ielem->regexCtxt = NULL;
23963     }
23964     if (ielem->nsBindings != NULL) {
23965 	xmlFree((xmlChar **)ielem->nsBindings);
23966 	ielem->nsBindings = NULL;
23967 	ielem->nbNsBindings = 0;
23968 	ielem->sizeNsBindings = 0;
23969     }
23970 }
23971 
23972 /**
23973  * xmlSchemaGetFreshElemInfo:
23974  * @vctxt: the schema validation context
23975  *
23976  * Creates/reuses and initializes the element info item for
23977  * the currect tree depth.
23978  *
23979  * Returns the element info item or NULL on API or internal errors.
23980  */
23981 static xmlSchemaNodeInfoPtr
xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)23982 xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
23983 {
23984     xmlSchemaNodeInfoPtr info = NULL;
23985 
23986     if (vctxt->depth > vctxt->sizeElemInfos) {
23987 	VERROR_INT("xmlSchemaGetFreshElemInfo",
23988 	    "inconsistent depth encountered");
23989 	return (NULL);
23990     }
23991     if (vctxt->elemInfos == NULL) {
23992 	vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
23993 	    xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
23994 	if (vctxt->elemInfos == NULL) {
23995 	    xmlSchemaVErrMemory(vctxt,
23996 		"allocating the element info array", NULL);
23997 	    return (NULL);
23998 	}
23999 	memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
24000 	vctxt->sizeElemInfos = 10;
24001     } else if (vctxt->sizeElemInfos <= vctxt->depth) {
24002 	int i = vctxt->sizeElemInfos;
24003 
24004 	vctxt->sizeElemInfos *= 2;
24005 	vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24006 	    xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
24007 	    sizeof(xmlSchemaNodeInfoPtr));
24008 	if (vctxt->elemInfos == NULL) {
24009 	    xmlSchemaVErrMemory(vctxt,
24010 		"re-allocating the element info array", NULL);
24011 	    return (NULL);
24012 	}
24013 	/*
24014 	* We need the new memory to be NULLed.
24015 	* TODO: Use memset instead?
24016 	*/
24017 	for (; i < vctxt->sizeElemInfos; i++)
24018 	    vctxt->elemInfos[i] = NULL;
24019     } else
24020 	info = vctxt->elemInfos[vctxt->depth];
24021 
24022     if (info == NULL) {
24023 	info = (xmlSchemaNodeInfoPtr)
24024 	    xmlMalloc(sizeof(xmlSchemaNodeInfo));
24025 	if (info == NULL) {
24026 	    xmlSchemaVErrMemory(vctxt,
24027 		"allocating an element info", NULL);
24028 	    return (NULL);
24029 	}
24030 	vctxt->elemInfos[vctxt->depth] = info;
24031     } else {
24032 	if (info->localName != NULL) {
24033 	    VERROR_INT("xmlSchemaGetFreshElemInfo",
24034 		"elem info has not been cleared");
24035 	    return (NULL);
24036 	}
24037     }
24038     memset(info, 0, sizeof(xmlSchemaNodeInfo));
24039     info->nodeType = XML_ELEMENT_NODE;
24040     info->depth = vctxt->depth;
24041 
24042     return (info);
24043 }
24044 
24045 #define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
24046 #define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
24047 #define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
24048 
24049 static int
xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,xmlNodePtr node,xmlSchemaTypePtr type,xmlSchemaValType valType,const xmlChar * value,xmlSchemaValPtr val,unsigned long length,int fireErrors)24050 xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
24051 			xmlNodePtr node,
24052 			xmlSchemaTypePtr type,
24053 			xmlSchemaValType valType,
24054 			const xmlChar * value,
24055 			xmlSchemaValPtr val,
24056 			unsigned long length,
24057 			int fireErrors)
24058 {
24059     int ret, error = 0;
24060 
24061     xmlSchemaTypePtr tmpType;
24062     xmlSchemaFacetLinkPtr facetLink;
24063     xmlSchemaFacetPtr facet;
24064     unsigned long len = 0;
24065     xmlSchemaWhitespaceValueType ws;
24066 
24067     /*
24068     * In Libxml2, derived built-in types have currently no explicit facets.
24069     */
24070     if (type->type == XML_SCHEMA_TYPE_BASIC)
24071 	return (0);
24072 
24073     /*
24074     * NOTE: Do not jump away, if the facetSet of the given type is
24075     * empty: until now, "pattern" and "enumeration" facets of the
24076     * *base types* need to be checked as well.
24077     */
24078     if (type->facetSet == NULL)
24079 	goto pattern_and_enum;
24080 
24081     if (! WXS_IS_ATOMIC(type)) {
24082 	if (WXS_IS_LIST(type))
24083 	    goto WXS_IS_LIST;
24084 	else
24085 	    goto pattern_and_enum;
24086     }
24087     /*
24088     * Whitespace handling is only of importance for string-based
24089     * types.
24090     */
24091     tmpType = xmlSchemaGetPrimitiveType(type);
24092     if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
24093 	WXS_IS_ANY_SIMPLE_TYPE(tmpType)) {
24094 	ws = xmlSchemaGetWhiteSpaceFacetValue(type);
24095     } else
24096 	ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
24097     /*
24098     * If the value was not computed (for string or
24099     * anySimpleType based types), then use the provided
24100     * type.
24101     */
24102     if (val == NULL)
24103 	valType = valType;
24104     else
24105 	valType = xmlSchemaGetValType(val);
24106 
24107     ret = 0;
24108     for (facetLink = type->facetSet; facetLink != NULL;
24109 	facetLink = facetLink->next) {
24110 	/*
24111 	* Skip the pattern "whiteSpace": it is used to
24112 	* format the character content beforehand.
24113 	*/
24114 	switch (facetLink->facet->type) {
24115 	    case XML_SCHEMA_FACET_WHITESPACE:
24116 	    case XML_SCHEMA_FACET_PATTERN:
24117 	    case XML_SCHEMA_FACET_ENUMERATION:
24118 		continue;
24119 	    case XML_SCHEMA_FACET_LENGTH:
24120 	    case XML_SCHEMA_FACET_MINLENGTH:
24121 	    case XML_SCHEMA_FACET_MAXLENGTH:
24122 		ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
24123 		    valType, value, val, &len, ws);
24124 		break;
24125 	    default:
24126 		ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
24127 		    valType, value, val, ws);
24128 		break;
24129 	}
24130 	if (ret < 0) {
24131 	    AERROR_INT("xmlSchemaValidateFacets",
24132 		"validating against a atomic type facet");
24133 	    return (-1);
24134 	} else if (ret > 0) {
24135 	    if (fireErrors)
24136 		xmlSchemaFacetErr(actxt, ret, node,
24137 		value, len, type, facetLink->facet, NULL, NULL, NULL);
24138 	    else
24139 		return (ret);
24140 	    if (error == 0)
24141 		error = ret;
24142 	}
24143 	ret = 0;
24144     }
24145 
24146 WXS_IS_LIST:
24147     if (! WXS_IS_LIST(type))
24148 	goto pattern_and_enum;
24149     /*
24150     * "length", "minLength" and "maxLength" of list types.
24151     */
24152     ret = 0;
24153     for (facetLink = type->facetSet; facetLink != NULL;
24154 	facetLink = facetLink->next) {
24155 
24156 	switch (facetLink->facet->type) {
24157 	    case XML_SCHEMA_FACET_LENGTH:
24158 	    case XML_SCHEMA_FACET_MINLENGTH:
24159 	    case XML_SCHEMA_FACET_MAXLENGTH:
24160 		ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
24161 		    value, length, NULL);
24162 		break;
24163 	    default:
24164 		continue;
24165 	}
24166 	if (ret < 0) {
24167 	    AERROR_INT("xmlSchemaValidateFacets",
24168 		"validating against a list type facet");
24169 	    return (-1);
24170 	} else if (ret > 0) {
24171 	    if (fireErrors)
24172 		xmlSchemaFacetErr(actxt, ret, node,
24173 		value, length, type, facetLink->facet, NULL, NULL, NULL);
24174 	    else
24175 		return (ret);
24176 	    if (error == 0)
24177 		error = ret;
24178 	}
24179 	ret = 0;
24180     }
24181 
24182 pattern_and_enum:
24183     if (error >= 0) {
24184 	int found = 0;
24185 	/*
24186 	* Process enumerations. Facet values are in the value space
24187 	* of the defining type's base type. This seems to be a bug in the
24188 	* XML Schema 1.0 spec. Use the whitespace type of the base type.
24189 	* Only the first set of enumerations in the ancestor-or-self axis
24190 	* is used for validation.
24191 	*/
24192 	ret = 0;
24193 	tmpType = type;
24194 	do {
24195 	    for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
24196 		if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
24197 		    continue;
24198 		found = 1;
24199 		ret = xmlSchemaAreValuesEqual(facet->val, val);
24200 		if (ret == 1)
24201 		    break;
24202 		else if (ret < 0) {
24203 		    AERROR_INT("xmlSchemaValidateFacets",
24204 			"validating against an enumeration facet");
24205 		    return (-1);
24206 		}
24207 	    }
24208 	    if (ret != 0)
24209 		break;
24210 	    /*
24211 	    * Break on the first set of enumerations. Any additional
24212 	    *  enumerations which might be existent on the ancestors
24213 	    *  of the current type are restricted by this set; thus
24214 	    *  *must* *not* be taken into account.
24215 	    */
24216 	    if (found)
24217 		break;
24218 	    tmpType = tmpType->baseType;
24219 	} while ((tmpType != NULL) &&
24220 	    (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24221 	if (found && (ret == 0)) {
24222 	    ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
24223 	    if (fireErrors) {
24224 		xmlSchemaFacetErr(actxt, ret, node,
24225 		    value, 0, type, NULL, NULL, NULL, NULL);
24226 	    } else
24227 		return (ret);
24228 	    if (error == 0)
24229 		error = ret;
24230 	}
24231     }
24232 
24233     if (error >= 0) {
24234 	int found;
24235 	/*
24236 	* Process patters. Pattern facets are ORed at type level
24237 	* and ANDed if derived. Walk the base type axis.
24238 	*/
24239 	tmpType = type;
24240 	facet = NULL;
24241 	do {
24242 	    found = 0;
24243 	    for (facetLink = tmpType->facetSet; facetLink != NULL;
24244 		facetLink = facetLink->next) {
24245 		if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
24246 		    continue;
24247 		found = 1;
24248 		/*
24249 		* NOTE that for patterns, @value needs to be the
24250 		* normalized vaule.
24251 		*/
24252 		ret = xmlRegexpExec(facetLink->facet->regexp, value);
24253 		if (ret == 1)
24254 		    break;
24255 		else if (ret < 0) {
24256 		    AERROR_INT("xmlSchemaValidateFacets",
24257 			"validating against a pattern facet");
24258 		    return (-1);
24259 		} else {
24260 		    /*
24261 		    * Save the last non-validating facet.
24262 		    */
24263 		    facet = facetLink->facet;
24264 		}
24265 	    }
24266 	    if (found && (ret != 1)) {
24267 		ret = XML_SCHEMAV_CVC_PATTERN_VALID;
24268 		if (fireErrors) {
24269 		    xmlSchemaFacetErr(actxt, ret, node,
24270 			value, 0, type, facet, NULL, NULL, NULL);
24271 		} else
24272 		    return (ret);
24273 		if (error == 0)
24274 		    error = ret;
24275 		break;
24276 	    }
24277 	    tmpType = tmpType->baseType;
24278 	} while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24279     }
24280 
24281     return (error);
24282 }
24283 
24284 static xmlChar *
xmlSchemaNormalizeValue(xmlSchemaTypePtr type,const xmlChar * value)24285 xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
24286 			const xmlChar *value)
24287 {
24288     switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
24289 	case XML_SCHEMA_WHITESPACE_COLLAPSE:
24290 	    return (xmlSchemaCollapseString(value));
24291 	case XML_SCHEMA_WHITESPACE_REPLACE:
24292 	    return (xmlSchemaWhiteSpaceReplace(value));
24293 	default:
24294 	    return (NULL);
24295     }
24296 }
24297 
24298 static int
xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,const xmlChar * value,xmlSchemaValPtr * val,int valNeeded)24299 xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
24300 		       const xmlChar *value,
24301 		       xmlSchemaValPtr *val,
24302 		       int valNeeded)
24303 {
24304     int ret;
24305     const xmlChar *nsName;
24306     xmlChar *local, *prefix = NULL;
24307 
24308     ret = xmlValidateQName(value, 1);
24309     if (ret != 0) {
24310 	if (ret == -1) {
24311 	    VERROR_INT("xmlSchemaValidateQName",
24312 		"calling xmlValidateQName()");
24313 	    return (-1);
24314 	}
24315 	return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
24316     }
24317     /*
24318     * NOTE: xmlSplitQName2 will always return a duplicated
24319     * strings.
24320     */
24321     local = xmlSplitQName2(value, &prefix);
24322     if (local == NULL)
24323 	local = xmlStrdup(value);
24324     /*
24325     * OPTIMIZE TODO: Use flags for:
24326     *  - is there any namespace binding?
24327     *  - is there a default namespace?
24328     */
24329     nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24330 
24331     if (prefix != NULL) {
24332 	xmlFree(prefix);
24333 	/*
24334 	* A namespace must be found if the prefix is
24335 	* NOT NULL.
24336 	*/
24337 	if (nsName == NULL) {
24338 	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24339 	    xmlSchemaCustomErr(ACTXT_CAST vctxt, ret, NULL,
24340 		WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24341 		"The QName value '%s' has no "
24342 		"corresponding namespace declaration in "
24343 		"scope", value, NULL);
24344 	    if (local != NULL)
24345 		xmlFree(local);
24346 	    return (ret);
24347 	}
24348     }
24349     if (valNeeded && val) {
24350 	if (nsName != NULL)
24351 	    *val = xmlSchemaNewQNameValue(
24352 		BAD_CAST xmlStrdup(nsName), BAD_CAST local);
24353 	else
24354 	    *val = xmlSchemaNewQNameValue(NULL,
24355 		BAD_CAST local);
24356     } else
24357 	xmlFree(local);
24358     return (0);
24359 }
24360 
24361 /*
24362 * cvc-simple-type
24363 */
24364 static int
xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,xmlNodePtr node,xmlSchemaTypePtr type,const xmlChar * value,xmlSchemaValPtr * retVal,int fireErrors,int normalize,int isNormalized)24365 xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
24366 			     xmlNodePtr node,
24367 			     xmlSchemaTypePtr type,
24368 			     const xmlChar *value,
24369 			     xmlSchemaValPtr *retVal,
24370 			     int fireErrors,
24371 			     int normalize,
24372 			     int isNormalized)
24373 {
24374     int ret = 0, valNeeded = (retVal) ? 1 : 0;
24375     xmlSchemaValPtr val = NULL;
24376     /* xmlSchemaWhitespaceValueType ws; */
24377     xmlChar *normValue = NULL;
24378 
24379 #define NORMALIZE(atype) \
24380     if ((! isNormalized) && \
24381     (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
24382 	normValue = xmlSchemaNormalizeValue(atype, value); \
24383 	if (normValue != NULL) \
24384 	    value = normValue; \
24385 	isNormalized = 1; \
24386     }
24387 
24388     if ((retVal != NULL) && (*retVal != NULL)) {
24389 	xmlSchemaFreeValue(*retVal);
24390 	*retVal = NULL;
24391     }
24392     /*
24393     * 3.14.4 Simple Type Definition Validation Rules
24394     * Validation Rule: String Valid
24395     */
24396     /*
24397     * 1 It is schema-valid with respect to that definition as defined
24398     * by Datatype Valid in [XML Schemas: Datatypes].
24399     */
24400     /*
24401     * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
24402     * the empty set, as defined in Type Derivation OK (Simple) (�3.14.6), then
24403     * the string must be a �declared entity name�.
24404     */
24405     /*
24406     * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
24407     * given the empty set, as defined in Type Derivation OK (Simple) (�3.14.6),
24408     * then every whitespace-delimited substring of the string must be a �declared
24409     * entity name�.
24410     */
24411     /*
24412     * 2.3 otherwise no further condition applies.
24413     */
24414     if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
24415 	valNeeded = 1;
24416     if (value == NULL)
24417 	value = BAD_CAST "";
24418     if (WXS_IS_ANY_SIMPLE_TYPE(type) || WXS_IS_ATOMIC(type)) {
24419 	xmlSchemaTypePtr biType; /* The built-in type. */
24420 	/*
24421 	* SPEC (1.2.1) "if {variety} is �atomic� then the string must �match�
24422 	* a literal in the �lexical space� of {base type definition}"
24423 	*/
24424 	/*
24425 	* Whitespace-normalize.
24426 	*/
24427 	NORMALIZE(type);
24428 	if (type->type != XML_SCHEMA_TYPE_BASIC) {
24429 	    /*
24430 	    * Get the built-in type.
24431 	    */
24432 	    biType = type->baseType;
24433 	    while ((biType != NULL) &&
24434 		(biType->type != XML_SCHEMA_TYPE_BASIC))
24435 		biType = biType->baseType;
24436 
24437 	    if (biType == NULL) {
24438 		AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24439 		    "could not get the built-in type");
24440 		goto internal_error;
24441 	    }
24442 	} else
24443 	    biType = type;
24444 	/*
24445 	* NOTATIONs need to be processed here, since they need
24446 	* to lookup in the hashtable of NOTATION declarations of the schema.
24447 	*/
24448 	if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
24449 	    switch (biType->builtInType) {
24450 		case XML_SCHEMAS_NOTATION:
24451 		    ret = xmlSchemaValidateNotation(
24452 			(xmlSchemaValidCtxtPtr) actxt,
24453 			((xmlSchemaValidCtxtPtr) actxt)->schema,
24454 			NULL, value, &val, valNeeded);
24455 		    break;
24456 		case XML_SCHEMAS_QNAME:
24457 		    ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
24458 			value, &val, valNeeded);
24459 		    break;
24460 		default:
24461 		    /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24462 		    if (valNeeded)
24463 			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24464 			    value, &val, NULL);
24465 		    else
24466 			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24467 			    value, NULL, NULL);
24468 		    break;
24469 	    }
24470 	} else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
24471 	    switch (biType->builtInType) {
24472 		case XML_SCHEMAS_NOTATION:
24473 		    ret = xmlSchemaValidateNotation(NULL,
24474 			((xmlSchemaParserCtxtPtr) actxt)->schema, node,
24475 			value, &val, valNeeded);
24476 		    break;
24477 		default:
24478 		    /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24479 		    if (valNeeded)
24480 			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24481 			    value, &val, node);
24482 		    else
24483 			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24484 			    value, NULL, node);
24485 		    break;
24486 	    }
24487 	} else {
24488 	    /*
24489 	    * Validation via a public API is not implemented yet.
24490 	    */
24491 	    TODO
24492 	    goto internal_error;
24493 	}
24494 	if (ret != 0) {
24495 	    if (ret < 0) {
24496 		AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24497 		    "validating against a built-in type");
24498 		goto internal_error;
24499 	    }
24500 	    if (WXS_IS_LIST(type))
24501 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24502 	    else
24503 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24504 	}
24505 	if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24506 	    /*
24507 	    * Check facets.
24508 	    */
24509 	    ret = xmlSchemaValidateFacets(actxt, node, type,
24510 		(xmlSchemaValType) biType->builtInType, value, val,
24511 		0, fireErrors);
24512 	    if (ret != 0) {
24513 		if (ret < 0) {
24514 		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24515 			"validating facets of atomic simple type");
24516 		    goto internal_error;
24517 		}
24518 		if (WXS_IS_LIST(type))
24519 		    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24520 		else
24521 		    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24522 	    }
24523 	}
24524 	if (fireErrors && (ret > 0))
24525 	    xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24526     } else if (WXS_IS_LIST(type)) {
24527 
24528 	xmlSchemaTypePtr itemType;
24529 	const xmlChar *cur, *end;
24530 	xmlChar *tmpValue = NULL;
24531 	unsigned long len = 0;
24532 	xmlSchemaValPtr prevVal = NULL, curVal = NULL;
24533 	/* 1.2.2 if {variety} is �list� then the string must be a sequence
24534 	* of white space separated tokens, each of which �match�es a literal
24535 	* in the �lexical space� of {item type definition}
24536 	*/
24537 	/*
24538 	* Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
24539 	* the list type has an enum or pattern facet.
24540 	*/
24541 	NORMALIZE(type);
24542 	/*
24543 	* VAL TODO: Optimize validation of empty values.
24544 	* VAL TODO: We do not have computed values for lists.
24545 	*/
24546 	itemType = WXS_LIST_ITEMTYPE(type);
24547 	cur = value;
24548 	do {
24549 	    while (IS_BLANK_CH(*cur))
24550 		cur++;
24551 	    end = cur;
24552 	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
24553 		end++;
24554 	    if (end == cur)
24555 		break;
24556 	    tmpValue = xmlStrndup(cur, end - cur);
24557 	    len++;
24558 
24559 	    if (valNeeded)
24560 		ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24561 		    tmpValue, &curVal, fireErrors, 0, 1);
24562 	    else
24563 		ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24564 		    tmpValue, NULL, fireErrors, 0, 1);
24565 	    FREE_AND_NULL(tmpValue);
24566 	    if (curVal != NULL) {
24567 		/*
24568 		* Add to list of computed values.
24569 		*/
24570 		if (val == NULL)
24571 		    val = curVal;
24572 		else
24573 		    xmlSchemaValueAppend(prevVal, curVal);
24574 		prevVal = curVal;
24575 		curVal = NULL;
24576 	    }
24577 	    if (ret != 0) {
24578 		if (ret < 0) {
24579 		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24580 			"validating an item of list simple type");
24581 		    goto internal_error;
24582 		}
24583 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24584 		break;
24585 	    }
24586 	    cur = end;
24587 	} while (*cur != 0);
24588 	FREE_AND_NULL(tmpValue);
24589 	if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24590 	    /*
24591 	    * Apply facets (pattern, enumeration).
24592 	    */
24593 	    ret = xmlSchemaValidateFacets(actxt, node, type,
24594 		XML_SCHEMAS_UNKNOWN, value, val,
24595 		len, fireErrors);
24596 	    if (ret != 0) {
24597 		if (ret < 0) {
24598 		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24599 			"validating facets of list simple type");
24600 		    goto internal_error;
24601 		}
24602 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24603 	    }
24604 	}
24605 	if (fireErrors && (ret > 0)) {
24606 	    /*
24607 	    * Report the normalized value.
24608 	    */
24609 	    normalize = 1;
24610 	    NORMALIZE(type);
24611 	    xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24612 	}
24613     } else if (WXS_IS_UNION(type)) {
24614 	xmlSchemaTypeLinkPtr memberLink;
24615 	/*
24616 	* TODO: For all datatypes �derived� by �union�  whiteSpace does
24617 	* not apply directly; however, the normalization behavior of �union�
24618 	* types is controlled by the value of whiteSpace on that one of the
24619 	* �memberTypes� against which the �union� is successfully validated.
24620 	*
24621 	* This means that the value is normalized by the first validating
24622 	* member type, then the facets of the union type are applied. This
24623 	* needs changing of the value!
24624 	*/
24625 
24626 	/*
24627 	* 1.2.3 if {variety} is �union� then the string must �match� a
24628 	* literal in the �lexical space� of at least one member of
24629 	* {member type definitions}
24630 	*/
24631 	memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
24632 	if (memberLink == NULL) {
24633 	    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24634 		"union simple type has no member types");
24635 	    goto internal_error;
24636 	}
24637 	/*
24638 	* Always normalize union type values, since we currently
24639 	* cannot store the whitespace information with the value
24640 	* itself; otherwise a later value-comparison would be
24641 	* not possible.
24642 	*/
24643 	while (memberLink != NULL) {
24644 	    if (valNeeded)
24645 		ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24646 		    memberLink->type, value, &val, 0, 1, 0);
24647 	    else
24648 		ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24649 		    memberLink->type, value, NULL, 0, 1, 0);
24650 	    if (ret <= 0)
24651 		break;
24652 	    memberLink = memberLink->next;
24653 	}
24654 	if (ret != 0) {
24655 	    if (ret < 0) {
24656 		AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24657 		    "validating members of union simple type");
24658 		goto internal_error;
24659 	    }
24660 	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24661 	}
24662 	/*
24663 	* Apply facets (pattern, enumeration).
24664 	*/
24665 	if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24666 	    /*
24667 	    * The normalization behavior of �union� types is controlled by
24668 	    * the value of whiteSpace on that one of the �memberTypes�
24669 	    * against which the �union� is successfully validated.
24670 	    */
24671 	    NORMALIZE(memberLink->type);
24672 	    ret = xmlSchemaValidateFacets(actxt, node, type,
24673 		XML_SCHEMAS_UNKNOWN, value, val,
24674 		0, fireErrors);
24675 	    if (ret != 0) {
24676 		if (ret < 0) {
24677 		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24678 			"validating facets of union simple type");
24679 		    goto internal_error;
24680 		}
24681 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24682 	    }
24683 	}
24684 	if (fireErrors && (ret > 0))
24685 	    xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24686     }
24687 
24688     if (normValue != NULL)
24689 	xmlFree(normValue);
24690     if (ret == 0) {
24691 	if (retVal != NULL)
24692 	    *retVal = val;
24693 	else if (val != NULL)
24694 	    xmlSchemaFreeValue(val);
24695     } else if (val != NULL)
24696 	xmlSchemaFreeValue(val);
24697     return (ret);
24698 internal_error:
24699     if (normValue != NULL)
24700 	xmlFree(normValue);
24701     if (val != NULL)
24702 	xmlSchemaFreeValue(val);
24703     return (-1);
24704 }
24705 
24706 static int
xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,const xmlChar * value,const xmlChar ** nsName,const xmlChar ** localName)24707 xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
24708 			   const xmlChar *value,
24709 			   const xmlChar **nsName,
24710 			   const xmlChar **localName)
24711 {
24712     int ret = 0;
24713 
24714     if ((nsName == NULL) || (localName == NULL))
24715 	return (-1);
24716     *nsName = NULL;
24717     *localName = NULL;
24718 
24719     ret = xmlValidateQName(value, 1);
24720     if (ret == -1)
24721 	return (-1);
24722     if (ret > 0) {
24723 	xmlSchemaSimpleTypeErr(ACTXT_CAST vctxt,
24724 	    XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24725 	    value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
24726 	return (1);
24727     }
24728     {
24729 	xmlChar *local = NULL;
24730 	xmlChar *prefix;
24731 
24732 	/*
24733 	* NOTE: xmlSplitQName2 will return a duplicated
24734 	* string.
24735 	*/
24736 	local = xmlSplitQName2(value, &prefix);
24737 	if (local == NULL)
24738 	    *localName = xmlDictLookup(vctxt->dict, value, -1);
24739 	else {
24740 	    *localName = xmlDictLookup(vctxt->dict, local, -1);
24741 	    xmlFree(local);
24742 	}
24743 
24744 	*nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24745 
24746 	if (prefix != NULL) {
24747 	    xmlFree(prefix);
24748 	    /*
24749 	    * A namespace must be found if the prefix is NOT NULL.
24750 	    */
24751 	    if (*nsName == NULL) {
24752 		xmlSchemaCustomErr(ACTXT_CAST vctxt,
24753 		    XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24754 		    WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24755 		    "The QName value '%s' has no "
24756 		    "corresponding namespace declaration in scope",
24757 		    value, NULL);
24758 		return (2);
24759 	    }
24760 	}
24761     }
24762     return (0);
24763 }
24764 
24765 static int
xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,xmlSchemaAttrInfoPtr iattr,xmlSchemaTypePtr * localType,xmlSchemaElementPtr elemDecl)24766 xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
24767 			xmlSchemaAttrInfoPtr iattr,
24768 			xmlSchemaTypePtr *localType,
24769 			xmlSchemaElementPtr elemDecl)
24770 {
24771     int ret = 0;
24772     /*
24773     * cvc-elt (3.3.4) : (4)
24774     * AND
24775     * Schema-Validity Assessment (Element) (cvc-assess-elt)
24776     *   (1.2.1.2.1) - (1.2.1.2.4)
24777     * Handle 'xsi:type'.
24778     */
24779     if (localType == NULL)
24780 	return (-1);
24781     *localType = NULL;
24782     if (iattr == NULL)
24783 	return (0);
24784     else {
24785 	const xmlChar *nsName = NULL, *local = NULL;
24786 	/*
24787 	* TODO: We should report a *warning* that the type was overriden
24788 	* by the instance.
24789 	*/
24790 	ACTIVATE_ATTRIBUTE(iattr);
24791 	/*
24792 	* (cvc-elt) (3.3.4) : (4.1)
24793 	* (cvc-assess-elt) (1.2.1.2.2)
24794 	*/
24795 	ret = xmlSchemaVExpandQName(vctxt, iattr->value,
24796 	    &nsName, &local);
24797 	if (ret != 0) {
24798 	    if (ret < 0) {
24799 		VERROR_INT("xmlSchemaValidateElementByDeclaration",
24800 		    "calling xmlSchemaQNameExpand() to validate the "
24801 		    "attribute 'xsi:type'");
24802 		goto internal_error;
24803 	    }
24804 	    goto exit;
24805 	}
24806 	/*
24807 	* (cvc-elt) (3.3.4) : (4.2)
24808 	* (cvc-assess-elt) (1.2.1.2.3)
24809 	*/
24810 	*localType = xmlSchemaGetType(vctxt->schema, local, nsName);
24811 	if (*localType == NULL) {
24812 	    xmlChar *str = NULL;
24813 
24814 	    xmlSchemaCustomErr(ACTXT_CAST vctxt,
24815 		XML_SCHEMAV_CVC_ELT_4_2, NULL,
24816 		WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24817 		"The QName value '%s' of the xsi:type attribute does not "
24818 		"resolve to a type definition",
24819 		xmlSchemaFormatQName(&str, nsName, local), NULL);
24820 	    FREE_AND_NULL(str);
24821 	    ret = vctxt->err;
24822 	    goto exit;
24823 	}
24824 	if (elemDecl != NULL) {
24825 	    int set = 0;
24826 
24827 	    /*
24828 	    * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
24829 	    * "The �local type definition� must be validly
24830 	    * derived from the {type definition} given the union of
24831 	    * the {disallowed substitutions} and the {type definition}'s
24832 	    * {prohibited substitutions}, as defined in
24833 	    * Type Derivation OK (Complex) (�3.4.6)
24834 	    * (if it is a complex type definition),
24835 	    * or given {disallowed substitutions} as defined in Type
24836 	    * Derivation OK (Simple) (�3.14.6) (if it is a simple type
24837 	    * definition)."
24838 	    *
24839 	    * {disallowed substitutions}: the "block" on the element decl.
24840 	    * {prohibited substitutions}: the "block" on the type def.
24841 	    */
24842 	    /*
24843 	    * OPTIMIZE TODO: We could map types already evaluated
24844 	    * to be validly derived from other types to avoid checking
24845 	    * this over and over for the same types.
24846 	    */
24847 	    if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
24848 		(elemDecl->subtypes->flags &
24849 		    XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
24850 		set |= SUBSET_EXTENSION;
24851 
24852 	    if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
24853 		(elemDecl->subtypes->flags &
24854 		    XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
24855 		set |= SUBSET_RESTRICTION;
24856 
24857 	    /*
24858 	    * REMOVED and CHANGED since this produced a parser context
24859 	    * which adds to the string dict of the schema. So this would
24860 	    * change the schema and we don't want this. We don't need
24861 	    * the parser context anymore.
24862 	    *
24863 	    * if ((vctxt->pctxt == NULL) &&
24864 	    *	(xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
24865 	    *	    return (-1);
24866 	    */
24867 
24868 	    if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST vctxt, *localType,
24869 		elemDecl->subtypes, set) != 0) {
24870 		xmlChar *str = NULL;
24871 
24872 		xmlSchemaCustomErr(ACTXT_CAST vctxt,
24873 		    XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
24874 		    "The type definition '%s', specified by xsi:type, is "
24875 		    "blocked or not validly derived from the type definition "
24876 		    "of the element declaration",
24877 		    xmlSchemaFormatQName(&str,
24878 			(*localType)->targetNamespace,
24879 			(*localType)->name),
24880 		    NULL);
24881 		FREE_AND_NULL(str);
24882 		ret = vctxt->err;
24883 		*localType = NULL;
24884 	    }
24885 	}
24886     }
24887 exit:
24888     ACTIVATE_ELEM;
24889     return (ret);
24890 internal_error:
24891     ACTIVATE_ELEM;
24892     return (-1);
24893 }
24894 
24895 static int
xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)24896 xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
24897 {
24898     xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
24899     xmlSchemaTypePtr actualType;
24900 
24901     /*
24902     * cvc-elt (3.3.4) : 1
24903     */
24904     if (elemDecl == NULL) {
24905 	VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
24906 	    "No matching declaration available");
24907         return (vctxt->err);
24908     }
24909     actualType = WXS_ELEM_TYPEDEF(elemDecl);
24910     /*
24911     * cvc-elt (3.3.4) : 2
24912     */
24913     if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
24914 	VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
24915 	    "The element declaration is abstract");
24916         return (vctxt->err);
24917     }
24918     if (actualType == NULL) {
24919     	VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
24920     	    "The type definition is absent");
24921     	return (XML_SCHEMAV_CVC_TYPE_1);
24922     }
24923     if (vctxt->nbAttrInfos != 0) {
24924 	int ret;
24925 	xmlSchemaAttrInfoPtr iattr;
24926 	/*
24927 	* cvc-elt (3.3.4) : 3
24928 	* Handle 'xsi:nil'.
24929 	*/
24930 	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
24931 	    XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
24932 	if (iattr) {
24933 	    ACTIVATE_ATTRIBUTE(iattr);
24934 	    /*
24935 	    * Validate the value.
24936 	    */
24937 	    ret = xmlSchemaVCheckCVCSimpleType(
24938 		ACTXT_CAST vctxt, NULL,
24939 		xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
24940 		iattr->value, &(iattr->val), 1, 0, 0);
24941 	    ACTIVATE_ELEM;
24942 	    if (ret < 0) {
24943 		VERROR_INT("xmlSchemaValidateElemDecl",
24944 		    "calling xmlSchemaVCheckCVCSimpleType() to "
24945 		    "validate the attribute 'xsi:nil'");
24946 		return (-1);
24947 	    }
24948 	    if (ret == 0) {
24949 		if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
24950 		    /*
24951 		    * cvc-elt (3.3.4) : 3.1
24952 		    */
24953 		    VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
24954 			"The element is not 'nillable'");
24955 		    /* Does not return an error on purpose. */
24956 		} else {
24957 		    if (xmlSchemaValueGetAsBoolean(iattr->val)) {
24958 			/*
24959 			* cvc-elt (3.3.4) : 3.2.2
24960 			*/
24961 			if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
24962 			    (elemDecl->value != NULL)) {
24963 			    VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
24964 				"The element cannot be 'nilled' because "
24965 				"there is a fixed value constraint defined "
24966 				"for it");
24967 			     /* Does not return an error on purpose. */
24968 			} else
24969 			    vctxt->inode->flags |=
24970 				XML_SCHEMA_ELEM_INFO_NILLED;
24971 		    }
24972 		}
24973 	    }
24974 	}
24975 	/*
24976 	* cvc-elt (3.3.4) : 4
24977 	* Handle 'xsi:type'.
24978 	*/
24979 	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
24980 	    XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
24981 	if (iattr) {
24982 	    xmlSchemaTypePtr localType = NULL;
24983 
24984 	    ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
24985 		elemDecl);
24986 	    if (ret != 0) {
24987 		if (ret == -1) {
24988 		    VERROR_INT("xmlSchemaValidateElemDecl",
24989 			"calling xmlSchemaProcessXSIType() to "
24990 			"process the attribute 'xsi:type'");
24991 		    return (-1);
24992 		}
24993 		/* Does not return an error on purpose. */
24994 	    }
24995 	    if (localType != NULL) {
24996 		vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
24997 		actualType = localType;
24998 	    }
24999 	}
25000     }
25001     /*
25002     * IDC: Register identity-constraint XPath matchers.
25003     */
25004     if ((elemDecl->idcs != NULL) &&
25005 	(xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
25006 	    return (-1);
25007     /*
25008     * No actual type definition.
25009     */
25010     if (actualType == NULL) {
25011     	VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
25012     	    "The type definition is absent");
25013     	return (XML_SCHEMAV_CVC_TYPE_1);
25014     }
25015     /*
25016     * Remember the actual type definition.
25017     */
25018     vctxt->inode->typeDef = actualType;
25019 
25020     return (0);
25021 }
25022 
25023 static int
xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)25024 xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
25025 {
25026     xmlSchemaAttrInfoPtr iattr;
25027     int ret = 0, i;
25028 
25029     /*
25030     * SPEC cvc-type (3.1.1)
25031     * "The attributes of must be empty, excepting those whose namespace
25032     * name is identical to http://www.w3.org/2001/XMLSchema-instance and
25033     * whose local name is one of type, nil, schemaLocation or
25034     * noNamespaceSchemaLocation."
25035     */
25036     if (vctxt->nbAttrInfos == 0)
25037 	return (0);
25038     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25039 	iattr = vctxt->attrInfos[i];
25040 	if (! iattr->metaType) {
25041 	    ACTIVATE_ATTRIBUTE(iattr)
25042 	    xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25043 		XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
25044 	    ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
25045         }
25046     }
25047     ACTIVATE_ELEM
25048     return (ret);
25049 }
25050 
25051 /*
25052 * Cleanup currently used attribute infos.
25053 */
25054 static void
xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)25055 xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
25056 {
25057     int i;
25058     xmlSchemaAttrInfoPtr attr;
25059 
25060     if (vctxt->nbAttrInfos == 0)
25061 	return;
25062     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25063 	attr = vctxt->attrInfos[i];
25064 	if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
25065 	    if (attr->localName != NULL)
25066 		xmlFree((xmlChar *) attr->localName);
25067 	    if (attr->nsName != NULL)
25068 		xmlFree((xmlChar *) attr->nsName);
25069 	}
25070 	if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
25071 	    if (attr->value != NULL)
25072 		xmlFree((xmlChar *) attr->value);
25073 	}
25074 	if (attr->val != NULL) {
25075 	    xmlSchemaFreeValue(attr->val);
25076 	    attr->val = NULL;
25077 	}
25078 	memset(attr, 0, sizeof(xmlSchemaAttrInfo));
25079     }
25080     vctxt->nbAttrInfos = 0;
25081 }
25082 
25083 /*
25084 * 3.4.4 Complex Type Definition Validation Rules
25085 *   Element Locally Valid (Complex Type) (cvc-complex-type)
25086 * 3.2.4 Attribute Declaration Validation Rules
25087 *   Validation Rule: Attribute Locally Valid (cvc-attribute)
25088 *   Attribute Locally Valid (Use) (cvc-au)
25089 *
25090 * Only "assessed" attribute information items will be visible to
25091 * IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
25092 */
25093 static int
xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)25094 xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
25095 {
25096     xmlSchemaTypePtr type = vctxt->inode->typeDef;
25097     xmlSchemaItemListPtr attrUseList;
25098     xmlSchemaAttributeUsePtr attrUse = NULL;
25099     xmlSchemaAttributePtr attrDecl = NULL;
25100     xmlSchemaAttrInfoPtr iattr, tmpiattr;
25101     int i, j, found, nbAttrs, nbUses;
25102     int xpathRes = 0, res, wildIDs = 0, fixed;
25103     xmlNodePtr defAttrOwnerElem = NULL;
25104 
25105     /*
25106     * SPEC (cvc-attribute)
25107     * (1) "The declaration must not be �absent� (see Missing
25108     * Sub-components (�5.3) for how this can fail to be
25109     * the case)."
25110     * (2) "Its {type definition} must not be absent."
25111     *
25112     * NOTE (1) + (2): This is not handled here, since we currently do not
25113     * allow validation against schemas which have missing sub-components.
25114     *
25115     * SPEC (cvc-complex-type)
25116     * (3) "For each attribute information item in the element information
25117     * item's [attributes] excepting those whose [namespace name] is
25118     * identical to http://www.w3.org/2001/XMLSchema-instance and whose
25119     * [local name] is one of type, nil, schemaLocation or
25120     * noNamespaceSchemaLocation, the appropriate case among the following
25121     * must be true:
25122     *
25123     */
25124     attrUseList = (xmlSchemaItemListPtr) type->attrUses;
25125     /*
25126     * @nbAttrs is the number of attributes present in the instance.
25127     */
25128     nbAttrs = vctxt->nbAttrInfos;
25129     if (attrUseList != NULL)
25130 	nbUses = attrUseList->nbItems;
25131     else
25132 	nbUses = 0;
25133     for (i = 0; i < nbUses; i++) {
25134         found = 0;
25135 	attrUse = attrUseList->items[i];
25136 	attrDecl = WXS_ATTRUSE_DECL(attrUse);
25137         for (j = 0; j < nbAttrs; j++) {
25138 	    iattr = vctxt->attrInfos[j];
25139 	    /*
25140 	    * SPEC (cvc-complex-type) (3)
25141 	    * Skip meta attributes.
25142 	    */
25143 	    if (iattr->metaType)
25144 		continue;
25145 	    if (iattr->localName[0] != attrDecl->name[0])
25146 		continue;
25147 	    if (!xmlStrEqual(iattr->localName, attrDecl->name))
25148 		continue;
25149 	    if (!xmlStrEqual(iattr->nsName, attrDecl->targetNamespace))
25150 		continue;
25151 	    found = 1;
25152 	    /*
25153 	    * SPEC (cvc-complex-type)
25154 	    * (3.1) "If there is among the {attribute uses} an attribute
25155 	    * use with an {attribute declaration} whose {name} matches
25156 	    * the attribute information item's [local name] and whose
25157 	    * {target namespace} is identical to the attribute information
25158 	    * item's [namespace name] (where an �absent� {target namespace}
25159 	    * is taken to be identical to a [namespace name] with no value),
25160 	    * then the attribute information must be �valid� with respect
25161 	    * to that attribute use as per Attribute Locally Valid (Use)
25162 	    * (�3.5.4). In this case the {attribute declaration} of that
25163 	    * attribute use is the �context-determined declaration� for the
25164 	    * attribute information item with respect to Schema-Validity
25165 	    * Assessment (Attribute) (�3.2.4) and
25166 	    * Assessment Outcome (Attribute) (�3.2.5).
25167 	    */
25168 	    iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25169 	    iattr->use = attrUse;
25170 	    /*
25171 	    * Context-determined declaration.
25172 	    */
25173 	    iattr->decl = attrDecl;
25174 	    iattr->typeDef = attrDecl->subtypes;
25175 	    break;
25176 	}
25177 
25178 	if (found)
25179 	    continue;
25180 
25181 	if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
25182 	    /*
25183 	    * Handle non-existent, required attributes.
25184 	    *
25185 	    * SPEC (cvc-complex-type)
25186 	    * (4) "The {attribute declaration} of each attribute use in
25187 	    * the {attribute uses} whose {required} is true matches one
25188 	    * of the attribute information items in the element information
25189 	    * item's [attributes] as per clause 3.1 above."
25190 	    */
25191 	    tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25192 	    if (tmpiattr == NULL) {
25193 		VERROR_INT(
25194 		    "xmlSchemaVAttributesComplex",
25195 		    "calling xmlSchemaGetFreshAttrInfo()");
25196 		return (-1);
25197 	    }
25198 	    tmpiattr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
25199 	    tmpiattr->use = attrUse;
25200 	    tmpiattr->decl = attrDecl;
25201 	} else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
25202 	    ((attrUse->defValue != NULL) ||
25203 	     (attrDecl->defValue != NULL))) {
25204 	    /*
25205 	    * Handle non-existent, optional, default/fixed attributes.
25206 	    */
25207 	    tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25208 	    if (tmpiattr == NULL) {
25209 		VERROR_INT(
25210 		    "xmlSchemaVAttributesComplex",
25211 		    "calling xmlSchemaGetFreshAttrInfo()");
25212 		return (-1);
25213 	    }
25214 	    tmpiattr->state = XML_SCHEMAS_ATTR_DEFAULT;
25215 	    tmpiattr->use = attrUse;
25216 	    tmpiattr->decl = attrDecl;
25217 	    tmpiattr->typeDef = attrDecl->subtypes;
25218 	    tmpiattr->localName = attrDecl->name;
25219 	    tmpiattr->nsName = attrDecl->targetNamespace;
25220 	}
25221     }
25222 
25223     if (vctxt->nbAttrInfos == 0)
25224 	return (0);
25225     nbUses = vctxt->nbAttrInfos;
25226     /*
25227     * Validate against the wildcard.
25228     */
25229     if (type->attributeWildcard != NULL) {
25230 	/*
25231 	* SPEC (cvc-complex-type)
25232 	* (3.2.1) "There must be an {attribute wildcard}."
25233 	*/
25234 	for (i = 0; i < nbAttrs; i++) {
25235 	    iattr = vctxt->attrInfos[i];
25236 	    /*
25237 	    * SPEC (cvc-complex-type) (3)
25238 	    * Skip meta attributes.
25239 	    */
25240 	    if (iattr->state != XML_SCHEMAS_ATTR_UNKNOWN)
25241 		continue;
25242 	    /*
25243 	    * SPEC (cvc-complex-type)
25244 	    * (3.2.2) "The attribute information item must be �valid� with
25245 	    * respect to it as defined in Item Valid (Wildcard) (�3.10.4)."
25246 	    *
25247 	    * SPEC Item Valid (Wildcard) (cvc-wildcard)
25248 	    * "... its [namespace name] must be �valid� with respect to
25249 	    * the wildcard constraint, as defined in Wildcard allows
25250 	    * Namespace Name (�3.10.4)."
25251 	    */
25252 	    if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
25253 		    iattr->nsName) == 0) {
25254 		/*
25255 		* Handle processContents.
25256 		*
25257 		* SPEC (cvc-wildcard):
25258 		* processContents | context-determined declaration:
25259 		* "strict"          "mustFind"
25260 		* "lax"             "none"
25261 		* "skip"            "skip"
25262 		*/
25263 		if (type->attributeWildcard->processContents ==
25264 		    XML_SCHEMAS_ANY_SKIP) {
25265 		     /*
25266 		    * context-determined declaration = "skip"
25267 		    *
25268 		    * SPEC PSVI Assessment Outcome (Attribute)
25269 		    * [validity] = "notKnown"
25270 		    * [validation attempted] = "none"
25271 		    */
25272 		    iattr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
25273 		    continue;
25274 		}
25275 		/*
25276 		* Find an attribute declaration.
25277 		*/
25278 		iattr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
25279 		    iattr->localName, iattr->nsName);
25280 		if (iattr->decl != NULL) {
25281 		    iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25282 		    /*
25283 		    * SPEC (cvc-complex-type)
25284 		    * (5) "Let [Definition:]  the wild IDs be the set of
25285 		    * all attribute information item to which clause 3.2
25286 		    * applied and whose �validation� resulted in a
25287 		    * �context-determined declaration� of mustFind or no
25288 		    * �context-determined declaration� at all, and whose
25289 		    * [local name] and [namespace name] resolve (as
25290 		    * defined by QName resolution (Instance) (�3.15.4)) to
25291 		    * an attribute declaration whose {type definition} is
25292 		    * or is derived from ID. Then all of the following
25293 		    * must be true:"
25294 		    */
25295 		    iattr->typeDef = WXS_ATTR_TYPEDEF(iattr->decl);
25296 		    if (xmlSchemaIsDerivedFromBuiltInType(
25297 			iattr->typeDef, XML_SCHEMAS_ID)) {
25298 			/*
25299 			* SPEC (5.1) "There must be no more than one
25300 			* item in �wild IDs�."
25301 			*/
25302 			if (wildIDs != 0) {
25303 			    /* VAL TODO */
25304 			    iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
25305 			    TODO
25306 			    continue;
25307 			}
25308 			wildIDs++;
25309 			/*
25310 			* SPEC (cvc-complex-type)
25311 			* (5.2) "If �wild IDs� is non-empty, there must not
25312 			* be any attribute uses among the {attribute uses}
25313 			* whose {attribute declaration}'s {type definition}
25314 			* is or is derived from ID."
25315 			*/
25316 			for (j = 0; j < attrUseList->nbItems; j++) {
25317 			    if (xmlSchemaIsDerivedFromBuiltInType(
25318 				WXS_ATTRUSE_TYPEDEF(attrUseList->items[j]),
25319 				XML_SCHEMAS_ID)) {
25320 				/* URGENT VAL TODO: implement */
25321 				iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
25322 				TODO
25323 				break;
25324 			    }
25325 			}
25326 		    }
25327 		} else if (type->attributeWildcard->processContents ==
25328 		    XML_SCHEMAS_ANY_LAX) {
25329 		    iattr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
25330 		    /*
25331 		    * SPEC PSVI Assessment Outcome (Attribute)
25332 		    * [validity] = "notKnown"
25333 		    * [validation attempted] = "none"
25334 		    */
25335 		} else {
25336 		    iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
25337 		}
25338 	    }
25339 	}
25340     }
25341 
25342     if (vctxt->nbAttrInfos == 0)
25343 	return (0);
25344 
25345     /*
25346     * Get the owner element; needed for creation of default attributes.
25347     * This fixes bug #341337, reported by David Grohmann.
25348     */
25349     if (vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
25350 	xmlSchemaNodeInfoPtr ielem = vctxt->elemInfos[vctxt->depth];
25351 	if (ielem && ielem->node && ielem->node->doc)
25352 	    defAttrOwnerElem = ielem->node;
25353     }
25354     /*
25355     * Validate values, create default attributes, evaluate IDCs.
25356     */
25357     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25358 	iattr = vctxt->attrInfos[i];
25359 	/*
25360 	* VAL TODO: Note that we won't try to resolve IDCs to
25361 	* "lax" and "skip" validated attributes. Check what to
25362 	* do in this case.
25363 	*/
25364 	if ((iattr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
25365 	    (iattr->state != XML_SCHEMAS_ATTR_DEFAULT))
25366 	    continue;
25367 	/*
25368 	* VAL TODO: What to do if the type definition is missing?
25369 	*/
25370 	if (iattr->typeDef == NULL) {
25371 	    iattr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
25372 	    continue;
25373 	}
25374 
25375 	ACTIVATE_ATTRIBUTE(iattr);
25376 	fixed = 0;
25377 	xpathRes = 0;
25378 
25379 	if (vctxt->xpathStates != NULL) {
25380 	    /*
25381 	    * Evaluate IDCs.
25382 	    */
25383 	    xpathRes = xmlSchemaXPathEvaluate(vctxt,
25384 		XML_ATTRIBUTE_NODE);
25385 	    if (xpathRes == -1) {
25386 		VERROR_INT("xmlSchemaVAttributesComplex",
25387 		    "calling xmlSchemaXPathEvaluate()");
25388 		goto internal_error;
25389 	    }
25390 	}
25391 
25392 	if (iattr->state == XML_SCHEMAS_ATTR_DEFAULT) {
25393 	    /*
25394 	    * Default/fixed attributes.
25395 	    * We need the value only if we need to resolve IDCs or
25396 	    * will create default attributes.
25397 	    */
25398 	    if ((xpathRes) || (defAttrOwnerElem)) {
25399 		if (iattr->use->defValue != NULL) {
25400 		    iattr->value = (xmlChar *) iattr->use->defValue;
25401 		    iattr->val = iattr->use->defVal;
25402 		} else {
25403 		    iattr->value = (xmlChar *) iattr->decl->defValue;
25404 		    iattr->val = iattr->decl->defVal;
25405 		}
25406 		/*
25407 		* IDCs will consume the precomputed default value,
25408 		* so we need to clone it.
25409 		*/
25410 		if (iattr->val == NULL) {
25411 		    VERROR_INT("xmlSchemaVAttributesComplex",
25412 			"default/fixed value on an attribute use was "
25413 			"not precomputed");
25414 		    goto internal_error;
25415 		}
25416 		iattr->val = xmlSchemaCopyValue(iattr->val);
25417 		if (iattr->val == NULL) {
25418 		    VERROR_INT("xmlSchemaVAttributesComplex",
25419 			"calling xmlSchemaCopyValue()");
25420 		    goto internal_error;
25421 		}
25422 	    }
25423 	    /*
25424 	    * PSVI: Add the default attribute to the current element.
25425 	    * VAL TODO: Should we use the *normalized* value? This currently
25426 	    *   uses the *initial* value.
25427 	    */
25428 
25429 	    if (defAttrOwnerElem) {
25430 		xmlChar *normValue;
25431 		const xmlChar *value;
25432 
25433 		value = iattr->value;
25434 		/*
25435 		* Normalize the value.
25436 		*/
25437 		normValue = xmlSchemaNormalizeValue(iattr->typeDef,
25438 		    iattr->value);
25439 		if (normValue != NULL)
25440 		    value = BAD_CAST normValue;
25441 
25442 		if (iattr->nsName == NULL) {
25443 		    if (xmlNewProp(defAttrOwnerElem,
25444 			iattr->localName, value) == NULL) {
25445 			VERROR_INT("xmlSchemaVAttributesComplex",
25446 			    "callling xmlNewProp()");
25447 			if (normValue != NULL)
25448 			    xmlFree(normValue);
25449 			goto internal_error;
25450 		    }
25451 		} else {
25452 		    xmlNsPtr ns;
25453 
25454 		    ns = xmlSearchNsByHref(defAttrOwnerElem->doc,
25455 			defAttrOwnerElem, iattr->nsName);
25456 		    if (ns == NULL) {
25457 			xmlChar prefix[12];
25458 			int counter = 0;
25459 
25460 			/*
25461 			* Create a namespace declaration on the validation
25462 			* root node if no namespace declaration is in scope.
25463 			*/
25464 			do {
25465 			    snprintf((char *) prefix, 12, "p%d", counter++);
25466 			    ns = xmlSearchNs(defAttrOwnerElem->doc,
25467 				defAttrOwnerElem, BAD_CAST prefix);
25468 			    if (counter > 1000) {
25469 				VERROR_INT(
25470 				    "xmlSchemaVAttributesComplex",
25471 				    "could not compute a ns prefix for a "
25472 				    "default/fixed attribute");
25473 				if (normValue != NULL)
25474 				    xmlFree(normValue);
25475 				goto internal_error;
25476 			    }
25477 			} while (ns != NULL);
25478 			ns = xmlNewNs(vctxt->validationRoot,
25479 			    iattr->nsName, BAD_CAST prefix);
25480 		    }
25481 		    /*
25482 		    * TODO:
25483 		    * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0406.html
25484 		    * If we have QNames: do we need to ensure there's a
25485 		    * prefix defined for the QName?
25486 		    */
25487 		    xmlNewNsProp(defAttrOwnerElem, ns, iattr->localName, value);
25488 		}
25489 		if (normValue != NULL)
25490 		    xmlFree(normValue);
25491 	    }
25492 	    /*
25493 	    * Go directly to IDC evaluation.
25494 	    */
25495 	    goto eval_idcs;
25496 	}
25497 	/*
25498 	* Validate the value.
25499 	*/
25500 	if (vctxt->value != NULL) {
25501 	    /*
25502 	    * Free last computed value; just for safety reasons.
25503 	    */
25504 	    xmlSchemaFreeValue(vctxt->value);
25505 	    vctxt->value = NULL;
25506 	}
25507 	/*
25508 	* Note that the attribute *use* can be unavailable, if
25509 	* the attribute was a wild attribute.
25510 	*/
25511 	if ((iattr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
25512 	    ((iattr->use != NULL) &&
25513 	     (iattr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
25514 	    fixed = 1;
25515 	else
25516 	    fixed = 0;
25517 	/*
25518 	* SPEC (cvc-attribute)
25519 	* (3) "The item's �normalized value� must be locally �valid�
25520 	* with respect to that {type definition} as per
25521 	* String Valid (�3.14.4)."
25522 	*
25523 	* VAL TODO: Do we already have the
25524 	* "normalized attribute value" here?
25525 	*/
25526 	if (xpathRes || fixed) {
25527 	    iattr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
25528 	    /*
25529 	    * Request a computed value.
25530 	    */
25531 	    res = xmlSchemaVCheckCVCSimpleType(
25532 		ACTXT_CAST vctxt,
25533 		iattr->node, iattr->typeDef, iattr->value, &(iattr->val),
25534 		1, 1, 0);
25535 	} else {
25536 	    res = xmlSchemaVCheckCVCSimpleType(
25537 		ACTXT_CAST vctxt,
25538 		iattr->node, iattr->typeDef, iattr->value, NULL,
25539 		1, 0, 0);
25540 	}
25541 
25542 	if (res != 0) {
25543 	    if (res == -1) {
25544 		VERROR_INT("xmlSchemaVAttributesComplex",
25545 		    "calling xmlSchemaStreamValidateSimpleTypeValue()");
25546 		goto internal_error;
25547 	    }
25548 	    iattr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
25549 	    /*
25550 	    * SPEC PSVI Assessment Outcome (Attribute)
25551 	    * [validity] = "invalid"
25552 	    */
25553 	    goto eval_idcs;
25554 	}
25555 
25556 	if (fixed) {
25557 	    /*
25558 	    * SPEC Attribute Locally Valid (Use) (cvc-au)
25559 	    * "For an attribute information item to be�valid�
25560 	    * with respect to an attribute use its *normalized*
25561 	    * value� must match the *canonical* lexical
25562 	    * representation of the attribute use's {value
25563 	    * constraint}value, if it is present and fixed."
25564 	    *
25565 	    * VAL TODO: The requirement for the *canonical* value
25566 	    * will be removed in XML Schema 1.1.
25567 	    */
25568 	    /*
25569 	    * SPEC Attribute Locally Valid (cvc-attribute)
25570 	    * (4) "The item's *actual* value� must match the *value* of
25571 	    * the {value constraint}, if it is present and fixed."
25572 	    */
25573 	    if (iattr->val == NULL) {
25574 		/* VAL TODO: A value was not precomputed. */
25575 		TODO
25576 		goto eval_idcs;
25577 	    }
25578 	    if ((iattr->use != NULL) &&
25579 		(iattr->use->defValue != NULL)) {
25580 		if (iattr->use->defVal == NULL) {
25581 		    /* VAL TODO: A default value was not precomputed. */
25582 		    TODO
25583 		    goto eval_idcs;
25584 		}
25585 		iattr->vcValue = iattr->use->defValue;
25586 		/*
25587 		if (xmlSchemaCompareValuesWhtsp(attr->val,
25588 		    (xmlSchemaWhitespaceValueType) ws,
25589 		    attr->use->defVal,
25590 		    (xmlSchemaWhitespaceValueType) ws) != 0) {
25591 		*/
25592 		if (! xmlSchemaAreValuesEqual(iattr->val, iattr->use->defVal))
25593 		    iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25594 	    } else {
25595 		if (iattr->decl->defVal == NULL) {
25596 		    /* VAL TODO: A default value was not precomputed. */
25597 		    TODO
25598 		    goto eval_idcs;
25599 		}
25600 		iattr->vcValue = iattr->decl->defValue;
25601 		/*
25602 		if (xmlSchemaCompareValuesWhtsp(attr->val,
25603 		    (xmlSchemaWhitespaceValueType) ws,
25604 		    attrDecl->defVal,
25605 		    (xmlSchemaWhitespaceValueType) ws) != 0) {
25606 		*/
25607 		if (! xmlSchemaAreValuesEqual(iattr->val, iattr->decl->defVal))
25608 		    iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25609 	    }
25610 	    /*
25611 	    * [validity] = "valid"
25612 	    */
25613 	}
25614 eval_idcs:
25615 	/*
25616 	* Evaluate IDCs.
25617 	*/
25618 	if (xpathRes) {
25619 	    if (xmlSchemaXPathProcessHistory(vctxt,
25620 		vctxt->depth +1) == -1) {
25621 		VERROR_INT("xmlSchemaVAttributesComplex",
25622 		    "calling xmlSchemaXPathEvaluate()");
25623 		goto internal_error;
25624 	    }
25625 	} else if (vctxt->xpathStates != NULL)
25626 	    xmlSchemaXPathPop(vctxt);
25627     }
25628 
25629     /*
25630     * Report errors.
25631     */
25632     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25633 	iattr = vctxt->attrInfos[i];
25634 	if ((iattr->state == XML_SCHEMAS_ATTR_META) ||
25635 	    (iattr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
25636 	    (iattr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
25637 	    (iattr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
25638 	    continue;
25639 	ACTIVATE_ATTRIBUTE(iattr);
25640 	switch (iattr->state) {
25641 	    case XML_SCHEMAS_ATTR_ERR_MISSING: {
25642 		    xmlChar *str = NULL;
25643 		    ACTIVATE_ELEM;
25644 		    xmlSchemaCustomErr(ACTXT_CAST vctxt,
25645 			XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
25646 			"The attribute '%s' is required but missing",
25647 			xmlSchemaFormatQName(&str,
25648 			    iattr->decl->targetNamespace,
25649 			    iattr->decl->name),
25650 			NULL);
25651 		    FREE_AND_NULL(str)
25652 		    break;
25653 		}
25654 	    case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
25655 		VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
25656 		    "The type definition is absent");
25657 		break;
25658 	    case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
25659 		xmlSchemaCustomErr(ACTXT_CAST vctxt,
25660 		    XML_SCHEMAV_CVC_AU, NULL, NULL,
25661 		    "The value '%s' does not match the fixed "
25662 		    "value constraint '%s'",
25663 		    iattr->value, iattr->vcValue);
25664 		break;
25665 	    case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
25666 		VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
25667 		    "No matching global attribute declaration available, but "
25668 		    "demanded by the strict wildcard");
25669 		break;
25670 	    case XML_SCHEMAS_ATTR_UNKNOWN:
25671 		if (iattr->metaType)
25672 		    break;
25673 		/*
25674 		* MAYBE VAL TODO: One might report different error messages
25675 		* for the following errors.
25676 		*/
25677 		if (type->attributeWildcard == NULL) {
25678 		    xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25679 			XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, iattr, NULL);
25680 		} else {
25681 		    xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25682 			XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, iattr, NULL);
25683 		}
25684 		break;
25685 	    default:
25686 		break;
25687 	}
25688     }
25689 
25690     ACTIVATE_ELEM;
25691     return (0);
25692 internal_error:
25693     ACTIVATE_ELEM;
25694     return (-1);
25695 }
25696 
25697 static int
xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,int * skip)25698 xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
25699 			      int *skip)
25700 {
25701     xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
25702     /*
25703     * The namespace of the element was already identified to be
25704     * matching the wildcard.
25705     */
25706     if ((skip == NULL) || (wild == NULL) ||
25707 	(wild->type != XML_SCHEMA_TYPE_ANY)) {
25708 	VERROR_INT("xmlSchemaValidateElemWildcard",
25709 	    "bad arguments");
25710 	return (-1);
25711     }
25712     *skip = 0;
25713     if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
25714 	/*
25715 	* URGENT VAL TODO: Either we need to position the stream to the
25716 	* next sibling, or walk the whole subtree.
25717 	*/
25718 	*skip = 1;
25719 	return (0);
25720     }
25721     {
25722 	xmlSchemaElementPtr decl = NULL;
25723 
25724 	decl = xmlSchemaGetElem(vctxt->schema,
25725 	    vctxt->inode->localName, vctxt->inode->nsName);
25726 	if (decl != NULL) {
25727 	    vctxt->inode->decl = decl;
25728 	    return (0);
25729 	}
25730     }
25731     if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
25732 	/* VAL TODO: Change to proper error code. */
25733 	VERROR(XML_SCHEMAV_CVC_ELT_1, NULL, /* WXS_BASIC_CAST wild */
25734 	    "No matching global element declaration available, but "
25735 	    "demanded by the strict wildcard");
25736 	return (vctxt->err);
25737     }
25738     if (vctxt->nbAttrInfos != 0) {
25739 	xmlSchemaAttrInfoPtr iattr;
25740 	/*
25741 	* SPEC Validation Rule: Schema-Validity Assessment (Element)
25742 	* (1.2.1.2.1) - (1.2.1.2.3 )
25743 	*
25744 	* Use the xsi:type attribute for the type definition.
25745 	*/
25746 	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25747 	    XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25748 	if (iattr != NULL) {
25749 	    if (xmlSchemaProcessXSIType(vctxt, iattr,
25750 		&(vctxt->inode->typeDef), NULL) == -1) {
25751 		VERROR_INT("xmlSchemaValidateElemWildcard",
25752 		    "calling xmlSchemaProcessXSIType() to "
25753 		    "process the attribute 'xsi:nil'");
25754 		return (-1);
25755 	    }
25756 	    /*
25757 	    * Don't return an error on purpose.
25758 	    */
25759 	    return (0);
25760 	}
25761     }
25762     /*
25763     * SPEC Validation Rule: Schema-Validity Assessment (Element)
25764     *
25765     * Fallback to "anyType".
25766     */
25767     vctxt->inode->typeDef =
25768 	xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
25769     return (0);
25770 }
25771 
25772 /*
25773 * xmlSchemaCheckCOSValidDefault:
25774 *
25775 * This will be called if: not nilled, no content and a default/fixed
25776 * value is provided.
25777 */
25778 
25779 static int
xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,const xmlChar * value,xmlSchemaValPtr * val)25780 xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
25781 			      const xmlChar *value,
25782 			      xmlSchemaValPtr *val)
25783 {
25784     int ret = 0;
25785     xmlSchemaNodeInfoPtr inode = vctxt->inode;
25786 
25787     /*
25788     * cos-valid-default:
25789     * Schema Component Constraint: Element Default Valid (Immediate)
25790     * For a string to be a valid default with respect to a type
25791     * definition the appropriate case among the following must be true:
25792     */
25793     if WXS_IS_COMPLEX(inode->typeDef) {
25794 	/*
25795 	* Complex type.
25796 	*
25797 	* SPEC (2.1) "its {content type} must be a simple type definition
25798 	* or mixed."
25799 	* SPEC (2.2.2) "If the {content type} is mixed, then the {content
25800 	* type}'s particle must be �emptiable� as defined by
25801 	* Particle Emptiable (�3.9.6)."
25802 	*/
25803 	if ((! WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) &&
25804 	    ((! WXS_HAS_MIXED_CONTENT(inode->typeDef)) ||
25805 	     (! WXS_EMPTIABLE(inode->typeDef)))) {
25806 	    ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
25807 	    /* NOTE that this covers (2.2.2) as well. */
25808 	    VERROR(ret, NULL,
25809 		"For a string to be a valid default, the type definition "
25810 		"must be a simple type or a complex type with simple content "
25811 		"or mixed content and a particle emptiable");
25812 	    return(ret);
25813 	}
25814     }
25815     /*
25816     * 1 If the type definition is a simple type definition, then the string
25817     * must be �valid� with respect to that definition as defined by String
25818     * Valid (�3.14.4).
25819     *
25820     * AND
25821     *
25822     * 2.2.1 If the {content type} is a simple type definition, then the
25823     * string must be �valid� with respect to that simple type definition
25824     * as defined by String Valid (�3.14.4).
25825     */
25826     if (WXS_IS_SIMPLE(inode->typeDef)) {
25827 
25828 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
25829 	    NULL, inode->typeDef, value, val, 1, 1, 0);
25830 
25831     } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
25832 
25833 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
25834 	    NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
25835     }
25836     if (ret < 0) {
25837 	VERROR_INT("xmlSchemaCheckCOSValidDefault",
25838 	    "calling xmlSchemaVCheckCVCSimpleType()");
25839     }
25840     return (ret);
25841 }
25842 
25843 static void
xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,const xmlChar * name ATTRIBUTE_UNUSED,xmlSchemaElementPtr item,xmlSchemaNodeInfoPtr inode)25844 xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
25845 			       const xmlChar * name ATTRIBUTE_UNUSED,
25846 			       xmlSchemaElementPtr item,
25847 			       xmlSchemaNodeInfoPtr inode)
25848 {
25849     inode->decl = item;
25850 #ifdef DEBUG_CONTENT
25851     {
25852 	xmlChar *str = NULL;
25853 
25854 	if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
25855 	    xmlGenericError(xmlGenericErrorContext,
25856 		"AUTOMATON callback for '%s' [declaration]\n",
25857 		xmlSchemaFormatQName(&str,
25858 		inode->localName, inode->nsName));
25859 	} else {
25860 	    xmlGenericError(xmlGenericErrorContext,
25861 		    "AUTOMATON callback for '%s' [wildcard]\n",
25862 		    xmlSchemaFormatQName(&str,
25863 		    inode->localName, inode->nsName));
25864 
25865 	}
25866 	FREE_AND_NULL(str)
25867     }
25868 #endif
25869 }
25870 
25871 static int
xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)25872 xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
25873 {
25874     vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
25875     if (vctxt->inode == NULL) {
25876 	VERROR_INT("xmlSchemaValidatorPushElem",
25877 	    "calling xmlSchemaGetFreshElemInfo()");
25878 	return (-1);
25879     }
25880     vctxt->nbAttrInfos = 0;
25881     return (0);
25882 }
25883 
25884 static int
xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,xmlSchemaNodeInfoPtr inode,xmlSchemaTypePtr type,const xmlChar * value)25885 xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
25886 			     xmlSchemaNodeInfoPtr inode,
25887 			     xmlSchemaTypePtr type,
25888 			     const xmlChar *value)
25889 {
25890     if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
25891 	return (xmlSchemaVCheckCVCSimpleType(
25892 	    ACTXT_CAST vctxt, NULL,
25893 	    type, value, &(inode->val), 1, 1, 0));
25894     else
25895 	return (xmlSchemaVCheckCVCSimpleType(
25896 	    ACTXT_CAST vctxt, NULL,
25897 	    type, value, NULL, 1, 0, 0));
25898 }
25899 
25900 
25901 
25902 /*
25903 * Process END of element.
25904 */
25905 static int
xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)25906 xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
25907 {
25908     int ret = 0;
25909     xmlSchemaNodeInfoPtr inode = vctxt->inode;
25910 
25911     if (vctxt->nbAttrInfos != 0)
25912 	xmlSchemaClearAttrInfos(vctxt);
25913     if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
25914 	/*
25915 	* This element was not expected;
25916 	* we will not validate child elements of broken parents.
25917 	* Skip validation of all content of the parent.
25918 	*/
25919 	vctxt->skipDepth = vctxt->depth -1;
25920 	goto end_elem;
25921     }
25922     if ((inode->typeDef == NULL) ||
25923 	(inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
25924 	/*
25925 	* 1. the type definition might be missing if the element was
25926 	*    error prone
25927 	* 2. it might be abstract.
25928 	*/
25929 	goto end_elem;
25930     }
25931     /*
25932     * Check the content model.
25933     */
25934     if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
25935 	(inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
25936 
25937 	/*
25938 	* Workaround for "anyType".
25939 	*/
25940 	if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
25941 	    goto character_content;
25942 
25943 	if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
25944 	    xmlChar *values[10];
25945 	    int terminal, nbval = 10, nbneg;
25946 
25947 	    if (inode->regexCtxt == NULL) {
25948 		/*
25949 		* Create the regex context.
25950 		*/
25951 		inode->regexCtxt =
25952 		    xmlRegNewExecCtxt(inode->typeDef->contModel,
25953 		    (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
25954 		    vctxt);
25955 		if (inode->regexCtxt == NULL) {
25956 		    VERROR_INT("xmlSchemaValidatorPopElem",
25957 			"failed to create a regex context");
25958 		    goto internal_error;
25959 		}
25960 #ifdef DEBUG_AUTOMATA
25961 		xmlGenericError(xmlGenericErrorContext,
25962 		    "AUTOMATON create on '%s'\n", inode->localName);
25963 #endif
25964 	    }
25965 	    /*
25966 	    * Get hold of the still expected content, since a further
25967 	    * call to xmlRegExecPushString() will loose this information.
25968 	    */
25969 	    xmlRegExecNextValues(inode->regexCtxt,
25970 		&nbval, &nbneg, &values[0], &terminal);
25971 	    ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
25972 	    if ((ret<0) || ((ret==0) && (!INODE_NILLED(inode)))) {
25973 		/*
25974 		* Still missing something.
25975 		*/
25976 		ret = 1;
25977 		inode->flags |=
25978 		    XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
25979 		xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
25980 		    XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
25981 		    "Missing child element(s)",
25982 		    nbval, nbneg, values);
25983 #ifdef DEBUG_AUTOMATA
25984 		xmlGenericError(xmlGenericErrorContext,
25985 		    "AUTOMATON missing ERROR on '%s'\n",
25986 		    inode->localName);
25987 #endif
25988 	    } else {
25989 		/*
25990 		* Content model is satisfied.
25991 		*/
25992 		ret = 0;
25993 #ifdef DEBUG_AUTOMATA
25994 		xmlGenericError(xmlGenericErrorContext,
25995 		    "AUTOMATON succeeded on '%s'\n",
25996 		    inode->localName);
25997 #endif
25998 	    }
25999 
26000 	}
26001     }
26002     if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
26003 	goto end_elem;
26004 
26005 character_content:
26006 
26007     if (vctxt->value != NULL) {
26008 	xmlSchemaFreeValue(vctxt->value);
26009 	vctxt->value = NULL;
26010     }
26011     /*
26012     * Check character content.
26013     */
26014     if (inode->decl == NULL) {
26015 	/*
26016 	* Speedup if no declaration exists.
26017 	*/
26018 	if (WXS_IS_SIMPLE(inode->typeDef)) {
26019 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26020 		inode, inode->typeDef, inode->value);
26021 	} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26022 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26023 		inode, inode->typeDef->contentTypeDef,
26024 		inode->value);
26025 	}
26026 	if (ret < 0) {
26027 	    VERROR_INT("xmlSchemaValidatorPopElem",
26028 		"calling xmlSchemaVCheckCVCSimpleType()");
26029 	    goto internal_error;
26030 	}
26031 	goto end_elem;
26032     }
26033     /*
26034     * cvc-elt (3.3.4) : 5
26035     * The appropriate case among the following must be true:
26036     */
26037     /*
26038     * cvc-elt (3.3.4) : 5.1
26039     * If the declaration has a {value constraint},
26040     * the item has neither element nor character [children] and
26041     * clause 3.2 has not applied, then all of the following must be true:
26042     */
26043     if ((inode->decl->value != NULL) &&
26044 	(inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
26045 	(! INODE_NILLED(inode))) {
26046 	/*
26047 	* cvc-elt (3.3.4) : 5.1.1
26048 	* If the �actual type definition� is a �local type definition�
26049 	* then the canonical lexical representation of the {value constraint}
26050 	* value must be a valid default for the �actual type definition� as
26051 	* defined in Element Default Valid (Immediate) (�3.3.6).
26052 	*/
26053 	/*
26054 	* NOTE: 'local' above means types acquired by xsi:type.
26055 	* NOTE: Although the *canonical* value is stated, it is not
26056 	* relevant if canonical or not. Additionally XML Schema 1.1
26057 	* will removed this requirement as well.
26058 	*/
26059 	if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
26060 
26061 	    ret = xmlSchemaCheckCOSValidDefault(vctxt,
26062 		inode->decl->value, &(inode->val));
26063 	    if (ret != 0) {
26064 		if (ret < 0) {
26065 		    VERROR_INT("xmlSchemaValidatorPopElem",
26066 			"calling xmlSchemaCheckCOSValidDefault()");
26067 		    goto internal_error;
26068 		}
26069 		goto end_elem;
26070 	    }
26071 	    /*
26072 	    * Stop here, to avoid redundant validation of the value
26073 	    * (see following).
26074 	    */
26075 	    goto default_psvi;
26076 	}
26077 	/*
26078 	* cvc-elt (3.3.4) : 5.1.2
26079 	* The element information item with the canonical lexical
26080 	* representation of the {value constraint} value used as its
26081 	* �normalized value� must be �valid� with respect to the
26082 	* �actual type definition� as defined by Element Locally Valid (Type)
26083 	* (�3.3.4).
26084 	*/
26085 	if (WXS_IS_SIMPLE(inode->typeDef)) {
26086 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26087 		inode, inode->typeDef, inode->decl->value);
26088 	} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26089 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26090 		inode, inode->typeDef->contentTypeDef,
26091 		inode->decl->value);
26092 	}
26093 	if (ret != 0) {
26094 	    if (ret < 0) {
26095 		VERROR_INT("xmlSchemaValidatorPopElem",
26096 		    "calling xmlSchemaVCheckCVCSimpleType()");
26097 		goto internal_error;
26098 	    }
26099 	    goto end_elem;
26100 	}
26101 
26102 default_psvi:
26103 	/*
26104 	* PSVI: Create a text node on the instance element.
26105 	*/
26106 	if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
26107 	    (inode->node != NULL)) {
26108 	    xmlNodePtr textChild;
26109 	    xmlChar *normValue;
26110 	    /*
26111 	    * VAL TODO: Normalize the value.
26112 	    */
26113 	    normValue = xmlSchemaNormalizeValue(inode->typeDef,
26114 		inode->decl->value);
26115 	    if (normValue != NULL) {
26116 		textChild = xmlNewText(BAD_CAST normValue);
26117 		xmlFree(normValue);
26118 	    } else
26119 		textChild = xmlNewText(inode->decl->value);
26120 	    if (textChild == NULL) {
26121 		VERROR_INT("xmlSchemaValidatorPopElem",
26122 		    "calling xmlNewText()");
26123 		goto internal_error;
26124 	    } else
26125 		xmlAddChild(inode->node, textChild);
26126 	}
26127 
26128     } else if (! INODE_NILLED(inode)) {
26129 	/*
26130 	* 5.2.1 The element information item must be �valid� with respect
26131 	* to the �actual type definition� as defined by Element Locally
26132 	* Valid (Type) (�3.3.4).
26133 	*/
26134 	if (WXS_IS_SIMPLE(inode->typeDef)) {
26135 	     /*
26136 	    * SPEC (cvc-type) (3.1)
26137 	    * "If the type definition is a simple type definition, ..."
26138 	    * (3.1.3) "If clause 3.2 of Element Locally Valid
26139 	    * (Element) (�3.3.4) did not apply, then the �normalized value�
26140 	    * must be �valid� with respect to the type definition as defined
26141 	    * by String Valid (�3.14.4).
26142 	    */
26143 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26144 		    inode, inode->typeDef, inode->value);
26145 	} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26146 	    /*
26147 	    * SPEC (cvc-type) (3.2) "If the type definition is a complex type
26148 	    * definition, then the element information item must be
26149 	    * �valid� with respect to the type definition as per
26150 	    * Element Locally Valid (Complex Type) (�3.4.4);"
26151 	    *
26152 	    * SPEC (cvc-complex-type) (2.2)
26153 	    * "If the {content type} is a simple type definition, ...
26154 	    * the �normalized value� of the element information item is
26155 	    * �valid� with respect to that simple type definition as
26156 	    * defined by String Valid (�3.14.4)."
26157 	    */
26158 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26159 		inode, inode->typeDef->contentTypeDef, inode->value);
26160 	}
26161 	if (ret != 0) {
26162 	    if (ret < 0) {
26163 		VERROR_INT("xmlSchemaValidatorPopElem",
26164 		    "calling xmlSchemaVCheckCVCSimpleType()");
26165 		goto internal_error;
26166 	    }
26167 	    goto end_elem;
26168 	}
26169 	/*
26170 	* 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
26171 	* not applied, all of the following must be true:
26172 	*/
26173 	if ((inode->decl->value != NULL) &&
26174 	    (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
26175 
26176 	    /*
26177 	    * TODO: We will need a computed value, when comparison is
26178 	    * done on computed values.
26179 	    */
26180 	    /*
26181 	    * 5.2.2.1 The element information item must have no element
26182 	    * information item [children].
26183 	    */
26184 	    if (inode->flags &
26185 		    XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
26186 		ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
26187 		VERROR(ret, NULL,
26188 		    "The content must not containt element nodes since "
26189 		    "there is a fixed value constraint");
26190 		goto end_elem;
26191 	    } else {
26192 		/*
26193 		* 5.2.2.2 The appropriate case among the following must
26194 		* be true:
26195 		*/
26196 		if (WXS_HAS_MIXED_CONTENT(inode->typeDef)) {
26197 		    /*
26198 		    * 5.2.2.2.1 If the {content type} of the �actual type
26199 		    * definition� is mixed, then the *initial value* of the
26200 		    * item must match the canonical lexical representation
26201 		    * of the {value constraint} value.
26202 		    *
26203 		    * ... the *initial value* of an element information
26204 		    * item is the string composed of, in order, the
26205 		    * [character code] of each character information item in
26206 		    * the [children] of that element information item.
26207 		    */
26208 		    if (! xmlStrEqual(inode->value, inode->decl->value)){
26209 			/*
26210 			* VAL TODO: Report invalid & expected values as well.
26211 			* VAL TODO: Implement the canonical stuff.
26212 			*/
26213 			ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
26214 			xmlSchemaCustomErr(ACTXT_CAST vctxt,
26215 			    ret, NULL, NULL,
26216 			    "The initial value '%s' does not match the fixed "
26217 			    "value constraint '%s'",
26218 			    inode->value, inode->decl->value);
26219 			goto end_elem;
26220 		    }
26221 		} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26222 		    /*
26223 		    * 5.2.2.2.2 If the {content type} of the �actual type
26224 		    * definition� is a simple type definition, then the
26225 		    * *actual value* of the item must match the canonical
26226 		    * lexical representation of the {value constraint} value.
26227 		    */
26228 		    /*
26229 		    * VAL TODO: *actual value* is the normalized value, impl.
26230 		    *           this.
26231 		    * VAL TODO: Report invalid & expected values as well.
26232 		    * VAL TODO: Implement a comparison with the computed values.
26233 		    */
26234 		    if (! xmlStrEqual(inode->value,
26235 			    inode->decl->value)) {
26236 			ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
26237 			xmlSchemaCustomErr(ACTXT_CAST vctxt,
26238 			    ret, NULL, NULL,
26239 			    "The actual value '%s' does not match the fixed "
26240 			    "value constraint '%s'",
26241 			    inode->value,
26242 			    inode->decl->value);
26243 			goto end_elem;
26244 		    }
26245 		}
26246 	    }
26247 	}
26248     }
26249 
26250 end_elem:
26251     if (vctxt->depth < 0) {
26252 	/* TODO: raise error? */
26253 	return (0);
26254     }
26255     if (vctxt->depth == vctxt->skipDepth)
26256 	vctxt->skipDepth = -1;
26257     /*
26258     * Evaluate the history of XPath state objects.
26259     */
26260     if (inode->appliedXPath &&
26261 	(xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1))
26262 	goto internal_error;
26263     /*
26264     * MAYBE TODO:
26265     * SPEC (6) "The element information item must be �valid� with
26266     * respect to each of the {identity-constraint definitions} as per
26267     * Identity-constraint Satisfied (�3.11.4)."
26268     */
26269     /*
26270     * PSVI TODO: If we expose IDC node-tables via PSVI then the tables
26271     *   need to be built in any case.
26272     *   We will currently build IDC node-tables and bubble them only if
26273     *   keyrefs do exist.
26274     */
26275 
26276     /*
26277     * Add the current IDC target-nodes to the IDC node-tables.
26278     */
26279     if ((inode->idcMatchers != NULL) &&
26280 	(vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26281     {
26282 	if (xmlSchemaIDCFillNodeTables(vctxt, inode) == -1)
26283 	    goto internal_error;
26284     }
26285     /*
26286     * Validate IDC keyrefs.
26287     */
26288     if (vctxt->inode->hasKeyrefs)
26289 	if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
26290 	    goto internal_error;
26291     /*
26292     * Merge/free the IDC table.
26293     */
26294     if (inode->idcTable != NULL) {
26295 #ifdef DEBUG_IDC_NODE_TABLE
26296 	xmlSchemaDebugDumpIDCTable(stdout,
26297 	    inode->nsName,
26298 	    inode->localName,
26299 	    inode->idcTable);
26300 #endif
26301 	if ((vctxt->depth > 0) &&
26302 	    (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26303 	{
26304 	    /*
26305 	    * Merge the IDC node table with the table of the parent node.
26306 	    */
26307 	    if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
26308 		goto internal_error;
26309 	}
26310     }
26311     /*
26312     * Clear the current ielem.
26313     * VAL TODO: Don't free the PSVI IDC tables if they are
26314     * requested for the PSVI.
26315     */
26316     xmlSchemaClearElemInfo(vctxt, inode);
26317     /*
26318     * Skip further processing if we are on the validation root.
26319     */
26320     if (vctxt->depth == 0) {
26321 	vctxt->depth--;
26322 	vctxt->inode = NULL;
26323 	return (0);
26324     }
26325     /*
26326     * Reset the keyrefDepth if needed.
26327     */
26328     if (vctxt->aidcs != NULL) {
26329 	xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
26330 	do {
26331 	    if (aidc->keyrefDepth == vctxt->depth) {
26332 		/*
26333 		* A 'keyrefDepth' of a key/unique IDC matches the current
26334 		* depth, this means that we are leaving the scope of the
26335 		* top-most keyref IDC which refers to this IDC.
26336 		*/
26337 		aidc->keyrefDepth = -1;
26338 	    }
26339 	    aidc = aidc->next;
26340 	} while (aidc != NULL);
26341     }
26342     vctxt->depth--;
26343     vctxt->inode = vctxt->elemInfos[vctxt->depth];
26344     /*
26345     * VAL TODO: 7 If the element information item is the �validation root�, it must be
26346     * �valid� per Validation Root Valid (ID/IDREF) (�3.3.4).
26347     */
26348     return (ret);
26349 
26350 internal_error:
26351     vctxt->err = -1;
26352     return (-1);
26353 }
26354 
26355 /*
26356 * 3.4.4 Complex Type Definition Validation Rules
26357 * Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
26358 */
26359 static int
xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)26360 xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
26361 {
26362     xmlSchemaNodeInfoPtr pielem;
26363     xmlSchemaTypePtr ptype;
26364     int ret = 0;
26365 
26366     if (vctxt->depth <= 0) {
26367 	VERROR_INT("xmlSchemaValidateChildElem",
26368 	    "not intended for the validation root");
26369 	return (-1);
26370     }
26371     pielem = vctxt->elemInfos[vctxt->depth -1];
26372     if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26373 	pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26374     /*
26375     * Handle 'nilled' elements.
26376     */
26377     if (INODE_NILLED(pielem)) {
26378 	/*
26379 	* SPEC (cvc-elt) (3.3.4) : (3.2.1)
26380 	*/
26381 	ACTIVATE_PARENT_ELEM;
26382 	ret = XML_SCHEMAV_CVC_ELT_3_2_1;
26383 	VERROR(ret, NULL,
26384 	    "Neither character nor element content is allowed, "
26385 	    "because the element was 'nilled'");
26386 	ACTIVATE_ELEM;
26387 	goto unexpected_elem;
26388     }
26389 
26390     ptype = pielem->typeDef;
26391 
26392     if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
26393 	/*
26394 	* Workaround for "anyType": we have currently no content model
26395 	* assigned for "anyType", so handle it explicitely.
26396 	* "anyType" has an unbounded, lax "any" wildcard.
26397 	*/
26398 	vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26399 	    vctxt->inode->localName,
26400 	    vctxt->inode->nsName);
26401 
26402 	if (vctxt->inode->decl == NULL) {
26403 	    xmlSchemaAttrInfoPtr iattr;
26404 	    /*
26405 	    * Process "xsi:type".
26406 	    * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
26407 	    */
26408 	    iattr = xmlSchemaGetMetaAttrInfo(vctxt,
26409 		XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
26410 	    if (iattr != NULL) {
26411 		ret = xmlSchemaProcessXSIType(vctxt, iattr,
26412 		    &(vctxt->inode->typeDef), NULL);
26413 		if (ret != 0) {
26414 		    if (ret == -1) {
26415 			VERROR_INT("xmlSchemaValidateChildElem",
26416 			    "calling xmlSchemaProcessXSIType() to "
26417 			    "process the attribute 'xsi:nil'");
26418 			return (-1);
26419 		    }
26420 		    return (ret);
26421 		}
26422 	    } else {
26423 		 /*
26424 		 * Fallback to "anyType".
26425 		 *
26426 		 * SPEC (cvc-assess-elt)
26427 		 * "If the item cannot be �strictly assessed�, [...]
26428 		 * an element information item's schema validity may be laxly
26429 		 * assessed if its �context-determined declaration� is not
26430 		 * skip by �validating� with respect to the �ur-type
26431 		 * definition� as per Element Locally Valid (Type) (�3.3.4)."
26432 		*/
26433 		vctxt->inode->typeDef =
26434 		    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
26435 	    }
26436 	}
26437 	return (0);
26438     }
26439 
26440     switch (ptype->contentType) {
26441 	case XML_SCHEMA_CONTENT_EMPTY:
26442 	    /*
26443 	    * SPEC (2.1) "If the {content type} is empty, then the
26444 	    * element information item has no character or element
26445 	    * information item [children]."
26446 	    */
26447 	    ACTIVATE_PARENT_ELEM
26448 	    ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
26449 	    VERROR(ret, NULL,
26450 		"Element content is not allowed, "
26451 		"because the content type is empty");
26452 	    ACTIVATE_ELEM
26453 	    goto unexpected_elem;
26454 	    break;
26455 
26456 	case XML_SCHEMA_CONTENT_MIXED:
26457         case XML_SCHEMA_CONTENT_ELEMENTS: {
26458 	    xmlRegExecCtxtPtr regexCtxt;
26459 	    xmlChar *values[10];
26460 	    int terminal, nbval = 10, nbneg;
26461 
26462 	    /* VAL TODO: Optimized "anyType" validation.*/
26463 
26464 	    if (ptype->contModel == NULL) {
26465 		VERROR_INT("xmlSchemaValidateChildElem",
26466 		    "type has elem content but no content model");
26467 		return (-1);
26468 	    }
26469 	    /*
26470 	    * Safety belf for evaluation if the cont. model was already
26471 	    * examined to be invalid.
26472 	    */
26473 	    if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
26474 		VERROR_INT("xmlSchemaValidateChildElem",
26475 		    "validating elem, but elem content is already invalid");
26476 		return (-1);
26477 	    }
26478 
26479 	    regexCtxt = pielem->regexCtxt;
26480 	    if (regexCtxt == NULL) {
26481 		/*
26482 		* Create the regex context.
26483 		*/
26484 		regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
26485 		    (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
26486 		    vctxt);
26487 		if (regexCtxt == NULL) {
26488 		    VERROR_INT("xmlSchemaValidateChildElem",
26489 			"failed to create a regex context");
26490 		    return (-1);
26491 		}
26492 		pielem->regexCtxt = regexCtxt;
26493 #ifdef DEBUG_AUTOMATA
26494 		xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
26495 		    pielem->localName);
26496 #endif
26497 	    }
26498 
26499 	    /*
26500 	    * SPEC (2.4) "If the {content type} is element-only or mixed,
26501 	    * then the sequence of the element information item's
26502 	    * element information item [children], if any, taken in
26503 	    * order, is �valid� with respect to the {content type}'s
26504 	    * particle, as defined in Element Sequence Locally Valid
26505 	    * (Particle) (�3.9.4)."
26506 	    */
26507 	    ret = xmlRegExecPushString2(regexCtxt,
26508 		vctxt->inode->localName,
26509 		vctxt->inode->nsName,
26510 		vctxt->inode);
26511 #ifdef DEBUG_AUTOMATA
26512 	    if (ret < 0)
26513 		xmlGenericError(xmlGenericErrorContext,
26514 		"AUTOMATON push ERROR for '%s' on '%s'\n",
26515 		vctxt->inode->localName, pielem->localName);
26516 	    else
26517 		xmlGenericError(xmlGenericErrorContext,
26518 		"AUTOMATON push OK for '%s' on '%s'\n",
26519 		vctxt->inode->localName, pielem->localName);
26520 #endif
26521 	    if (vctxt->err == XML_SCHEMAV_INTERNAL) {
26522 		VERROR_INT("xmlSchemaValidateChildElem",
26523 		    "calling xmlRegExecPushString2()");
26524 		return (-1);
26525 	    }
26526 	    if (ret < 0) {
26527 		xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
26528 		    &values[0], &terminal);
26529 		xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26530 		    XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
26531 		    "This element is not expected",
26532 		    nbval, nbneg, values);
26533 		ret = vctxt->err;
26534 		goto unexpected_elem;
26535 	    } else
26536 		ret = 0;
26537 	}
26538 	    break;
26539 	case XML_SCHEMA_CONTENT_SIMPLE:
26540 	case XML_SCHEMA_CONTENT_BASIC:
26541 	    ACTIVATE_PARENT_ELEM
26542 	    if (WXS_IS_COMPLEX(ptype)) {
26543 		/*
26544 		* SPEC (cvc-complex-type) (2.2)
26545 		* "If the {content type} is a simple type definition, then
26546 		* the element information item has no element information
26547 		* item [children], ..."
26548 		*/
26549 		ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
26550 		VERROR(ret, NULL, "Element content is not allowed, "
26551 		    "because the content type is a simple type definition");
26552 	    } else {
26553 		/*
26554 		* SPEC (cvc-type) (3.1.2) "The element information item must
26555 		* have no element information item [children]."
26556 		*/
26557 		ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
26558 		VERROR(ret, NULL, "Element content is not allowed, "
26559 		    "because the type definition is simple");
26560 	    }
26561 	    ACTIVATE_ELEM
26562 	    ret = vctxt->err;
26563 	    goto unexpected_elem;
26564 	    break;
26565 
26566 	default:
26567 	    break;
26568     }
26569     return (ret);
26570 unexpected_elem:
26571     /*
26572     * Pop this element and set the skipDepth to skip
26573     * all further content of the parent element.
26574     */
26575     vctxt->skipDepth = vctxt->depth;
26576     vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
26577     pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26578     return (ret);
26579 }
26580 
26581 #define XML_SCHEMA_PUSH_TEXT_PERSIST 1
26582 #define XML_SCHEMA_PUSH_TEXT_CREATED 2
26583 #define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
26584 
26585 static int
xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,int nodeType,const xmlChar * value,int len,int mode,int * consumed)26586 xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
26587 		  int nodeType, const xmlChar *value, int len,
26588 		  int mode, int *consumed)
26589 {
26590     /*
26591     * Unfortunately we have to duplicate the text sometimes.
26592     * OPTIMIZE: Maybe we could skip it, if:
26593     *   1. content type is simple
26594     *   2. whitespace is "collapse"
26595     *   3. it consists of whitespace only
26596     *
26597     * Process character content.
26598     */
26599     if (consumed != NULL)
26600 	*consumed = 0;
26601     if (INODE_NILLED(vctxt->inode)) {
26602 	/*
26603 	* SPEC cvc-elt (3.3.4 - 3.2.1)
26604 	* "The element information item must have no character or
26605 	* element information item [children]."
26606 	*/
26607 	VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
26608 	    "Neither character nor element content is allowed "
26609 	    "because the element is 'nilled'");
26610 	return (vctxt->err);
26611     }
26612     /*
26613     * SPEC (2.1) "If the {content type} is empty, then the
26614     * element information item has no character or element
26615     * information item [children]."
26616     */
26617     if (vctxt->inode->typeDef->contentType ==
26618 	    XML_SCHEMA_CONTENT_EMPTY) {
26619 	VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
26620 	    "Character content is not allowed, "
26621 	    "because the content type is empty");
26622 	return (vctxt->err);
26623     }
26624 
26625     if (vctxt->inode->typeDef->contentType ==
26626 	    XML_SCHEMA_CONTENT_ELEMENTS) {
26627 	if ((nodeType != XML_TEXT_NODE) ||
26628 	    (! xmlSchemaIsBlank((xmlChar *) value, len))) {
26629 	    /*
26630 	    * SPEC cvc-complex-type (2.3)
26631 	    * "If the {content type} is element-only, then the
26632 	    * element information item has no character information
26633 	    * item [children] other than those whose [character
26634 	    * code] is defined as a white space in [XML 1.0 (Second
26635 	    * Edition)]."
26636 	    */
26637 	    VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
26638 		"Character content other than whitespace is not allowed "
26639 		"because the content type is 'element-only'");
26640 	    return (vctxt->err);
26641 	}
26642 	return (0);
26643     }
26644 
26645     if ((value == NULL) || (value[0] == 0))
26646 	return (0);
26647     /*
26648     * Save the value.
26649     * NOTE that even if the content type is *mixed*, we need the
26650     * *initial value* for default/fixed value constraints.
26651     */
26652     if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
26653 	((vctxt->inode->decl == NULL) ||
26654 	(vctxt->inode->decl->value == NULL)))
26655 	return (0);
26656 
26657     if (vctxt->inode->value == NULL) {
26658 	/*
26659 	* Set the value.
26660 	*/
26661 	switch (mode) {
26662 	    case XML_SCHEMA_PUSH_TEXT_PERSIST:
26663 		/*
26664 		* When working on a tree.
26665 		*/
26666 		vctxt->inode->value = value;
26667 		break;
26668 	    case XML_SCHEMA_PUSH_TEXT_CREATED:
26669 		/*
26670 		* When working with the reader.
26671 		* The value will be freed by the element info.
26672 		*/
26673 		vctxt->inode->value = value;
26674 		if (consumed != NULL)
26675 		    *consumed = 1;
26676 		vctxt->inode->flags |=
26677 		    XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26678 		break;
26679 	    case XML_SCHEMA_PUSH_TEXT_VOLATILE:
26680 		/*
26681 		* When working with SAX.
26682 		* The value will be freed by the element info.
26683 		*/
26684 		if (len != -1)
26685 		    vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
26686 		else
26687 		    vctxt->inode->value = BAD_CAST xmlStrdup(value);
26688 		vctxt->inode->flags |=
26689 		    XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26690 		break;
26691 	    default:
26692 		break;
26693 	}
26694     } else {
26695 	if (len < 0)
26696 	    len = xmlStrlen(value);
26697 	/*
26698 	* Concat the value.
26699 	*/
26700 	if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
26701 	    vctxt->inode->value = BAD_CAST xmlStrncat(
26702 		(xmlChar *) vctxt->inode->value, value, len);
26703 	} else {
26704 	    vctxt->inode->value =
26705 		BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
26706 	    vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26707 	}
26708     }
26709 
26710     return (0);
26711 }
26712 
26713 static int
xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)26714 xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
26715 {
26716     int ret = 0;
26717 
26718     if ((vctxt->skipDepth != -1) &&
26719 	(vctxt->depth >= vctxt->skipDepth)) {
26720 	VERROR_INT("xmlSchemaValidateElem",
26721 	    "in skip-state");
26722 	goto internal_error;
26723     }
26724     if (vctxt->xsiAssemble) {
26725 	/*
26726 	* We will stop validation if there was an error during
26727 	* dynamic schema construction.
26728 	* Note that we simply set @skipDepth to 0, this could
26729 	* mean that a streaming document via SAX would be
26730 	* still read to the end but it won't be validated any more.
26731 	* TODO: If we are sure how to stop the validation at once
26732 	*   for all input scenarios, then this should be changed to
26733 	*   instantly stop the validation.
26734 	*/
26735 	ret = xmlSchemaAssembleByXSI(vctxt);
26736 	if (ret != 0) {
26737 	    if (ret == -1)
26738 		goto internal_error;
26739 	    vctxt->skipDepth = 0;
26740 	    return(ret);
26741 	}
26742     }
26743     if (vctxt->depth > 0) {
26744 	/*
26745 	* Validate this element against the content model
26746 	* of the parent.
26747 	*/
26748 	ret = xmlSchemaValidateChildElem(vctxt);
26749 	if (ret != 0) {
26750 	    if (ret < 0) {
26751 		VERROR_INT("xmlSchemaValidateElem",
26752 		    "calling xmlSchemaStreamValidateChildElement()");
26753 		goto internal_error;
26754 	    }
26755 	    goto exit;
26756 	}
26757 	if (vctxt->depth == vctxt->skipDepth)
26758 	    goto exit;
26759 	if ((vctxt->inode->decl == NULL) &&
26760 	    (vctxt->inode->typeDef == NULL)) {
26761 	    VERROR_INT("xmlSchemaValidateElem",
26762 		"the child element was valid but neither the "
26763 		"declaration nor the type was set");
26764 	    goto internal_error;
26765 	}
26766     } else {
26767 	/*
26768 	* Get the declaration of the validation root.
26769 	*/
26770 	vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26771 	    vctxt->inode->localName,
26772 	    vctxt->inode->nsName);
26773 	if (vctxt->inode->decl == NULL) {
26774 	    ret = XML_SCHEMAV_CVC_ELT_1;
26775 	    VERROR(ret, NULL,
26776 		"No matching global declaration available "
26777 		"for the validation root");
26778 	    goto exit;
26779 	}
26780     }
26781 
26782     if (vctxt->inode->decl == NULL)
26783 	goto type_validation;
26784 
26785     if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
26786 	int skip;
26787 	/*
26788 	* Wildcards.
26789 	*/
26790 	ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
26791 	if (ret != 0) {
26792 	    if (ret < 0) {
26793 		VERROR_INT("xmlSchemaValidateElem",
26794 		    "calling xmlSchemaValidateElemWildcard()");
26795 		goto internal_error;
26796 	    }
26797 	    goto exit;
26798 	}
26799 	if (skip) {
26800 	    vctxt->skipDepth = vctxt->depth;
26801 	    goto exit;
26802 	}
26803 	/*
26804 	* The declaration might be set by the wildcard validation,
26805 	* when the processContents is "lax" or "strict".
26806 	*/
26807 	if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
26808 	    /*
26809 	    * Clear the "decl" field to not confuse further processing.
26810 	    */
26811 	    vctxt->inode->decl = NULL;
26812 	    goto type_validation;
26813 	}
26814     }
26815     /*
26816     * Validate against the declaration.
26817     */
26818     ret = xmlSchemaValidateElemDecl(vctxt);
26819     if (ret != 0) {
26820 	if (ret < 0) {
26821 	    VERROR_INT("xmlSchemaValidateElem",
26822 		"calling xmlSchemaValidateElemDecl()");
26823 	    goto internal_error;
26824 	}
26825 	goto exit;
26826     }
26827     /*
26828     * Validate against the type definition.
26829     */
26830 type_validation:
26831 
26832     if (vctxt->inode->typeDef == NULL) {
26833 	vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26834 	ret = XML_SCHEMAV_CVC_TYPE_1;
26835     	VERROR(ret, NULL,
26836     	    "The type definition is absent");
26837 	goto exit;
26838     }
26839     if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
26840 	vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26841 	ret = XML_SCHEMAV_CVC_TYPE_2;
26842     	    VERROR(ret, NULL,
26843     	    "The type definition is abstract");
26844 	goto exit;
26845     }
26846     /*
26847     * Evaluate IDCs. Do it here, since new IDC matchers are registered
26848     * during validation against the declaration. This must be done
26849     * _before_ attribute validation.
26850     */
26851     if (vctxt->xpathStates != NULL) {
26852 	ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
26853 	vctxt->inode->appliedXPath = 1;
26854 	if (ret == -1) {
26855 	    VERROR_INT("xmlSchemaValidateElem",
26856 		"calling xmlSchemaXPathEvaluate()");
26857 	    goto internal_error;
26858 	}
26859     }
26860     /*
26861     * Validate attributes.
26862     */
26863     if (WXS_IS_COMPLEX(vctxt->inode->typeDef)) {
26864 	if ((vctxt->nbAttrInfos != 0) ||
26865 	    (vctxt->inode->typeDef->attrUses != NULL)) {
26866 
26867 	    ret = xmlSchemaVAttributesComplex(vctxt);
26868 	}
26869     } else if (vctxt->nbAttrInfos != 0) {
26870 
26871 	ret = xmlSchemaVAttributesSimple(vctxt);
26872     }
26873     /*
26874     * Clear registered attributes.
26875     */
26876     if (vctxt->nbAttrInfos != 0)
26877 	xmlSchemaClearAttrInfos(vctxt);
26878     if (ret == -1) {
26879 	VERROR_INT("xmlSchemaValidateElem",
26880 	    "calling attributes validation");
26881 	goto internal_error;
26882     }
26883     /*
26884     * Don't return an error if attributes are invalid on purpose.
26885     */
26886     ret = 0;
26887 
26888 exit:
26889     if (ret != 0)
26890 	vctxt->skipDepth = vctxt->depth;
26891     return (ret);
26892 internal_error:
26893     return (-1);
26894 }
26895 
26896 #ifdef XML_SCHEMA_READER_ENABLED
26897 static int
xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)26898 xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
26899 {
26900     const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
26901     int depth, nodeType, ret = 0, consumed;
26902     xmlSchemaNodeInfoPtr ielem;
26903 
26904     vctxt->depth = -1;
26905     ret = xmlTextReaderRead(vctxt->reader);
26906     /*
26907     * Move to the document element.
26908     */
26909     while (ret == 1) {
26910 	nodeType = xmlTextReaderNodeType(vctxt->reader);
26911 	if (nodeType == XML_ELEMENT_NODE)
26912 	    goto root_found;
26913 	ret = xmlTextReaderRead(vctxt->reader);
26914     }
26915     goto exit;
26916 
26917 root_found:
26918 
26919     do {
26920 	depth = xmlTextReaderDepth(vctxt->reader);
26921 	nodeType = xmlTextReaderNodeType(vctxt->reader);
26922 
26923 	if (nodeType == XML_ELEMENT_NODE) {
26924 
26925 	    vctxt->depth++;
26926 	    if (xmlSchemaValidatorPushElem(vctxt) == -1) {
26927 		VERROR_INT("xmlSchemaVReaderWalk",
26928 		    "calling xmlSchemaValidatorPushElem()");
26929 		goto internal_error;
26930 	    }
26931 	    ielem = vctxt->inode;
26932 	    ielem->localName = xmlTextReaderLocalName(vctxt->reader);
26933 	    ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
26934 	    ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
26935 	    /*
26936 	    * Is the element empty?
26937 	    */
26938 	    ret = xmlTextReaderIsEmptyElement(vctxt->reader);
26939 	    if (ret == -1) {
26940 		VERROR_INT("xmlSchemaVReaderWalk",
26941 		    "calling xmlTextReaderIsEmptyElement()");
26942 		goto internal_error;
26943 	    }
26944 	    if (ret) {
26945 		ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
26946 	    }
26947 	    /*
26948 	    * Register attributes.
26949 	    */
26950 	    vctxt->nbAttrInfos = 0;
26951 	    ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
26952 	    if (ret == -1) {
26953 		VERROR_INT("xmlSchemaVReaderWalk",
26954 		    "calling xmlTextReaderMoveToFirstAttribute()");
26955 		goto internal_error;
26956 	    }
26957 	    if (ret == 1) {
26958 		do {
26959 		    /*
26960 		    * VAL TODO: How do we know that the reader works on a
26961 		    * node tree, to be able to pass a node here?
26962 		    */
26963 		    if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
26964 			(const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
26965 			xmlTextReaderNamespaceUri(vctxt->reader), 1,
26966 			xmlTextReaderValue(vctxt->reader), 1) == -1) {
26967 
26968 			VERROR_INT("xmlSchemaVReaderWalk",
26969 			    "calling xmlSchemaValidatorPushAttribute()");
26970 			goto internal_error;
26971 		    }
26972 		    ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
26973 		    if (ret == -1) {
26974 			VERROR_INT("xmlSchemaVReaderWalk",
26975 			    "calling xmlTextReaderMoveToFirstAttribute()");
26976 			goto internal_error;
26977 		    }
26978 		} while (ret == 1);
26979 		/*
26980 		* Back to element position.
26981 		*/
26982 		ret = xmlTextReaderMoveToElement(vctxt->reader);
26983 		if (ret == -1) {
26984 		    VERROR_INT("xmlSchemaVReaderWalk",
26985 			"calling xmlTextReaderMoveToElement()");
26986 		    goto internal_error;
26987 		}
26988 	    }
26989 	    /*
26990 	    * Validate the element.
26991 	    */
26992 	    ret= xmlSchemaValidateElem(vctxt);
26993 	    if (ret != 0) {
26994 		if (ret == -1) {
26995 		    VERROR_INT("xmlSchemaVReaderWalk",
26996 			"calling xmlSchemaValidateElem()");
26997 		    goto internal_error;
26998 		}
26999 		goto exit;
27000 	    }
27001 	    if (vctxt->depth == vctxt->skipDepth) {
27002 		int curDepth;
27003 		/*
27004 		* Skip all content.
27005 		*/
27006 		if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
27007 		    ret = xmlTextReaderRead(vctxt->reader);
27008 		    curDepth = xmlTextReaderDepth(vctxt->reader);
27009 		    while ((ret == 1) && (curDepth != depth)) {
27010 			ret = xmlTextReaderRead(vctxt->reader);
27011 			curDepth = xmlTextReaderDepth(vctxt->reader);
27012 		    }
27013 		    if (ret < 0) {
27014 			/*
27015 			* VAL TODO: A reader error occured; what to do here?
27016 			*/
27017 			ret = 1;
27018 			goto exit;
27019 		    }
27020 		}
27021 		goto leave_elem;
27022 	    }
27023 	    /*
27024 	    * READER VAL TODO: Is an END_ELEM really never called
27025 	    * if the elem is empty?
27026 	    */
27027 	    if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27028 		goto leave_elem;
27029 	} else if (nodeType == END_ELEM) {
27030 	    /*
27031 	    * Process END of element.
27032 	    */
27033 leave_elem:
27034 	    ret = xmlSchemaValidatorPopElem(vctxt);
27035 	    if (ret != 0) {
27036 		if (ret < 0) {
27037 		    VERROR_INT("xmlSchemaVReaderWalk",
27038 			"calling xmlSchemaValidatorPopElem()");
27039 		    goto internal_error;
27040 		}
27041 		goto exit;
27042 	    }
27043 	    if (vctxt->depth >= 0)
27044 		ielem = vctxt->inode;
27045 	    else
27046 		ielem = NULL;
27047 	} else if ((nodeType == XML_TEXT_NODE) ||
27048 	    (nodeType == XML_CDATA_SECTION_NODE) ||
27049 	    (nodeType == WHTSP) ||
27050 	    (nodeType == SIGN_WHTSP)) {
27051 	    /*
27052 	    * Process character content.
27053 	    */
27054 	    xmlChar *value;
27055 
27056 	    if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
27057 		nodeType = XML_TEXT_NODE;
27058 
27059 	    value = xmlTextReaderValue(vctxt->reader);
27060 	    ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
27061 		-1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
27062 	    if (! consumed)
27063 		xmlFree(value);
27064 	    if (ret == -1) {
27065 		VERROR_INT("xmlSchemaVReaderWalk",
27066 		    "calling xmlSchemaVPushText()");
27067 		goto internal_error;
27068 	    }
27069 	} else if ((nodeType == XML_ENTITY_NODE) ||
27070 	    (nodeType == XML_ENTITY_REF_NODE)) {
27071 	    /*
27072 	    * VAL TODO: What to do with entities?
27073 	    */
27074 	    TODO
27075 	}
27076 	/*
27077 	* Read next node.
27078 	*/
27079 	ret = xmlTextReaderRead(vctxt->reader);
27080     } while (ret == 1);
27081 
27082 exit:
27083     return (ret);
27084 internal_error:
27085     return (-1);
27086 }
27087 #endif
27088 
27089 /************************************************************************
27090  * 									*
27091  * 			SAX validation handlers				*
27092  * 									*
27093  ************************************************************************/
27094 
27095 /*
27096 * Process text content.
27097 */
27098 static void
xmlSchemaSAXHandleText(void * ctx,const xmlChar * ch,int len)27099 xmlSchemaSAXHandleText(void *ctx,
27100 		       const xmlChar * ch,
27101 		       int len)
27102 {
27103     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27104 
27105     if (vctxt->depth < 0)
27106 	return;
27107     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27108 	return;
27109     if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27110 	vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27111     if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
27112 	XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27113 	VERROR_INT("xmlSchemaSAXHandleCDataSection",
27114 	    "calling xmlSchemaVPushText()");
27115 	vctxt->err = -1;
27116 	xmlStopParser(vctxt->parserCtxt);
27117     }
27118 }
27119 
27120 /*
27121 * Process CDATA content.
27122 */
27123 static void
xmlSchemaSAXHandleCDataSection(void * ctx,const xmlChar * ch,int len)27124 xmlSchemaSAXHandleCDataSection(void *ctx,
27125 			     const xmlChar * ch,
27126 			     int len)
27127 {
27128     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27129 
27130     if (vctxt->depth < 0)
27131 	return;
27132     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27133 	return;
27134     if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27135 	vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27136     if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
27137 	XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27138 	VERROR_INT("xmlSchemaSAXHandleCDataSection",
27139 	    "calling xmlSchemaVPushText()");
27140 	vctxt->err = -1;
27141 	xmlStopParser(vctxt->parserCtxt);
27142     }
27143 }
27144 
27145 static void
xmlSchemaSAXHandleReference(void * ctx ATTRIBUTE_UNUSED,const xmlChar * name ATTRIBUTE_UNUSED)27146 xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
27147 			    const xmlChar * name ATTRIBUTE_UNUSED)
27148 {
27149     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27150 
27151     if (vctxt->depth < 0)
27152 	return;
27153     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27154 	return;
27155     /* SAX VAL TODO: What to do here? */
27156     TODO
27157 }
27158 
27159 static void
xmlSchemaSAXHandleStartElementNs(void * ctx,const xmlChar * localname,const xmlChar * prefix ATTRIBUTE_UNUSED,const xmlChar * URI,int nb_namespaces,const xmlChar ** namespaces,int nb_attributes,int nb_defaulted ATTRIBUTE_UNUSED,const xmlChar ** attributes)27160 xmlSchemaSAXHandleStartElementNs(void *ctx,
27161 				 const xmlChar * localname,
27162 				 const xmlChar * prefix ATTRIBUTE_UNUSED,
27163 				 const xmlChar * URI,
27164 				 int nb_namespaces,
27165 				 const xmlChar ** namespaces,
27166 				 int nb_attributes,
27167 				 int nb_defaulted ATTRIBUTE_UNUSED,
27168 				 const xmlChar ** attributes)
27169 {
27170     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27171     int ret;
27172     xmlSchemaNodeInfoPtr ielem;
27173     int i, j;
27174 
27175     /*
27176     * SAX VAL TODO: What to do with nb_defaulted?
27177     */
27178     /*
27179     * Skip elements if inside a "skip" wildcard or invalid.
27180     */
27181     vctxt->depth++;
27182     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27183 	return;
27184     /*
27185     * Push the element.
27186     */
27187     if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27188 	VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27189 	    "calling xmlSchemaValidatorPushElem()");
27190 	goto internal_error;
27191     }
27192     ielem = vctxt->inode;
27193     /*
27194     * TODO: Is this OK?
27195     */
27196     ielem->nodeLine = xmlSAX2GetLineNumber(vctxt->parserCtxt);
27197     ielem->localName = localname;
27198     ielem->nsName = URI;
27199     ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27200     /*
27201     * Register namespaces on the elem info.
27202     */
27203     if (nb_namespaces != 0) {
27204 	/*
27205 	* Although the parser builds its own namespace list,
27206 	* we have no access to it, so we'll use an own one.
27207 	*/
27208         for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
27209 	    /*
27210 	    * Store prefix and namespace name.
27211 	    */
27212 	    if (ielem->nsBindings == NULL) {
27213 		ielem->nsBindings =
27214 		    (const xmlChar **) xmlMalloc(10 *
27215 			sizeof(const xmlChar *));
27216 		if (ielem->nsBindings == NULL) {
27217 		    xmlSchemaVErrMemory(vctxt,
27218 			"allocating namespace bindings for SAX validation",
27219 			NULL);
27220 		    goto internal_error;
27221 		}
27222 		ielem->nbNsBindings = 0;
27223 		ielem->sizeNsBindings = 5;
27224 	    } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
27225 		ielem->sizeNsBindings *= 2;
27226 		ielem->nsBindings =
27227 		    (const xmlChar **) xmlRealloc(
27228 			(void *) ielem->nsBindings,
27229 			ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
27230 		if (ielem->nsBindings == NULL) {
27231 		    xmlSchemaVErrMemory(vctxt,
27232 			"re-allocating namespace bindings for SAX validation",
27233 			NULL);
27234 		    goto internal_error;
27235 		}
27236 	    }
27237 
27238 	    ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
27239 	    if (namespaces[j+1][0] == 0) {
27240 		/*
27241 		* Handle xmlns="".
27242 		*/
27243 		ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
27244 	    } else
27245 		ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
27246 		    namespaces[j+1];
27247 	    ielem->nbNsBindings++;
27248 	}
27249     }
27250     /*
27251     * Register attributes.
27252     * SAX VAL TODO: We are not adding namespace declaration
27253     * attributes yet.
27254     */
27255     if (nb_attributes != 0) {
27256 	xmlChar *value;
27257 
27258         for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
27259 	    /*
27260 	    * Duplicate the value.
27261 	    */
27262 	    value = xmlStrndup(attributes[j+3],
27263 		attributes[j+4] - attributes[j+3]);
27264 	    /*
27265 	    * TODO: Set the node line.
27266 	    */
27267 	    ret = xmlSchemaValidatorPushAttribute(vctxt,
27268 		NULL, ielem->nodeLine, attributes[j], attributes[j+2], 0,
27269 		value, 1);
27270 	    if (ret == -1) {
27271 		VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27272 		    "calling xmlSchemaValidatorPushAttribute()");
27273 		goto internal_error;
27274 	    }
27275 	}
27276     }
27277     /*
27278     * Validate the element.
27279     */
27280     ret = xmlSchemaValidateElem(vctxt);
27281     if (ret != 0) {
27282 	if (ret == -1) {
27283 	    VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27284 		"calling xmlSchemaValidateElem()");
27285 	    goto internal_error;
27286 	}
27287 	goto exit;
27288     }
27289 
27290 exit:
27291     return;
27292 internal_error:
27293     vctxt->err = -1;
27294     xmlStopParser(vctxt->parserCtxt);
27295     return;
27296 }
27297 
27298 static void
xmlSchemaSAXHandleEndElementNs(void * ctx,const xmlChar * localname ATTRIBUTE_UNUSED,const xmlChar * prefix ATTRIBUTE_UNUSED,const xmlChar * URI ATTRIBUTE_UNUSED)27299 xmlSchemaSAXHandleEndElementNs(void *ctx,
27300 			       const xmlChar * localname ATTRIBUTE_UNUSED,
27301 			       const xmlChar * prefix ATTRIBUTE_UNUSED,
27302 			       const xmlChar * URI ATTRIBUTE_UNUSED)
27303 {
27304     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27305     int res;
27306 
27307     /*
27308     * Skip elements if inside a "skip" wildcard or if invalid.
27309     */
27310     if (vctxt->skipDepth != -1) {
27311 	if (vctxt->depth > vctxt->skipDepth) {
27312 	    vctxt->depth--;
27313 	    return;
27314 	} else
27315 	    vctxt->skipDepth = -1;
27316     }
27317     /*
27318     * SAX VAL TODO: Just a temporary check.
27319     */
27320     if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
27321 	(!xmlStrEqual(vctxt->inode->nsName, URI))) {
27322 	VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27323 	    "elem pop mismatch");
27324     }
27325     res = xmlSchemaValidatorPopElem(vctxt);
27326     if (res != 0) {
27327 	if (res < 0) {
27328 	    VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27329 		"calling xmlSchemaValidatorPopElem()");
27330 	    goto internal_error;
27331 	}
27332 	goto exit;
27333     }
27334 exit:
27335     return;
27336 internal_error:
27337     vctxt->err = -1;
27338     xmlStopParser(vctxt->parserCtxt);
27339     return;
27340 }
27341 
27342 /************************************************************************
27343  * 									*
27344  * 			Validation interfaces				*
27345  * 									*
27346  ************************************************************************/
27347 
27348 /**
27349  * xmlSchemaNewValidCtxt:
27350  * @schema:  a precompiled XML Schemas
27351  *
27352  * Create an XML Schemas validation context based on the given schema.
27353  *
27354  * Returns the validation context or NULL in case of error
27355  */
27356 xmlSchemaValidCtxtPtr
xmlSchemaNewValidCtxt(xmlSchemaPtr schema)27357 xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
27358 {
27359     xmlSchemaValidCtxtPtr ret;
27360 
27361     ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
27362     if (ret == NULL) {
27363         xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
27364         return (NULL);
27365     }
27366     memset(ret, 0, sizeof(xmlSchemaValidCtxt));
27367     ret->type = XML_SCHEMA_CTXT_VALIDATOR;
27368     ret->dict = xmlDictCreate();
27369     ret->nodeQNames = xmlSchemaItemListCreate();
27370     ret->schema = schema;
27371     return (ret);
27372 }
27373 
27374 /**
27375  * xmlSchemaClearValidCtxt:
27376  * @ctxt: the schema validation context
27377  *
27378  * Free the resources associated to the schema validation context;
27379  * leaves some fields alive intended for reuse of the context.
27380  */
27381 static void
xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)27382 xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
27383 {
27384     if (vctxt == NULL)
27385         return;
27386 
27387     /*
27388     * TODO: Should we clear the flags?
27389     *   Might be problematic if one reuses the context
27390     *   and assumes that the options remain the same.
27391     */
27392     vctxt->flags = 0;
27393     vctxt->validationRoot = NULL;
27394     vctxt->doc = NULL;
27395 #ifdef LIBXML_READER_ENABLED
27396     vctxt->reader = NULL;
27397 #endif
27398     vctxt->hasKeyrefs = 0;
27399 
27400     if (vctxt->value != NULL) {
27401         xmlSchemaFreeValue(vctxt->value);
27402 	vctxt->value = NULL;
27403     }
27404     /*
27405     * Augmented IDC information.
27406     */
27407     if (vctxt->aidcs != NULL) {
27408 	xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
27409 	do {
27410 	    next = cur->next;
27411 	    xmlFree(cur);
27412 	    cur = next;
27413 	} while (cur != NULL);
27414 	vctxt->aidcs = NULL;
27415     }
27416     if (vctxt->idcMatcherCache != NULL) {
27417 	xmlSchemaIDCMatcherPtr matcher = vctxt->idcMatcherCache, tmp;
27418 
27419 	while (matcher) {
27420 	    tmp = matcher;
27421 	    matcher = matcher->nextCached;
27422 	    xmlSchemaIDCFreeMatcherList(tmp);
27423 	}
27424 	vctxt->idcMatcherCache = NULL;
27425     }
27426 
27427 
27428     if (vctxt->idcNodes != NULL) {
27429 	int i;
27430 	xmlSchemaPSVIIDCNodePtr item;
27431 
27432 	for (i = 0; i < vctxt->nbIdcNodes; i++) {
27433 	    item = vctxt->idcNodes[i];
27434 	    xmlFree(item->keys);
27435 	    xmlFree(item);
27436 	}
27437 	xmlFree(vctxt->idcNodes);
27438 	vctxt->idcNodes = NULL;
27439 	vctxt->nbIdcNodes = 0;
27440 	vctxt->sizeIdcNodes = 0;
27441     }
27442     /*
27443     * Note that we won't delete the XPath state pool here.
27444     */
27445     if (vctxt->xpathStates != NULL) {
27446 	xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
27447 	vctxt->xpathStates = NULL;
27448     }
27449     /*
27450     * Attribute info.
27451     */
27452     if (vctxt->nbAttrInfos != 0) {
27453 	xmlSchemaClearAttrInfos(vctxt);
27454     }
27455     /*
27456     * Element info.
27457     */
27458     if (vctxt->elemInfos != NULL) {
27459 	int i;
27460 	xmlSchemaNodeInfoPtr ei;
27461 
27462 	for (i = 0; i < vctxt->sizeElemInfos; i++) {
27463 	    ei = vctxt->elemInfos[i];
27464 	    if (ei == NULL)
27465 		break;
27466 	    xmlSchemaClearElemInfo(vctxt, ei);
27467 	}
27468     }
27469     xmlSchemaItemListClear(vctxt->nodeQNames);
27470     /* Recreate the dict. */
27471     xmlDictFree(vctxt->dict);
27472     /*
27473     * TODO: Is is save to recreate it? Do we have a scenario
27474     * where the user provides the dict?
27475     */
27476     vctxt->dict = xmlDictCreate();
27477 }
27478 
27479 /**
27480  * xmlSchemaFreeValidCtxt:
27481  * @ctxt:  the schema validation context
27482  *
27483  * Free the resources associated to the schema validation context
27484  */
27485 void
xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)27486 xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
27487 {
27488     if (ctxt == NULL)
27489         return;
27490     if (ctxt->value != NULL)
27491         xmlSchemaFreeValue(ctxt->value);
27492     if (ctxt->pctxt != NULL)
27493 	xmlSchemaFreeParserCtxt(ctxt->pctxt);
27494     if (ctxt->idcNodes != NULL) {
27495 	int i;
27496 	xmlSchemaPSVIIDCNodePtr item;
27497 
27498 	for (i = 0; i < ctxt->nbIdcNodes; i++) {
27499 	    item = ctxt->idcNodes[i];
27500 	    xmlFree(item->keys);
27501 	    xmlFree(item);
27502 	}
27503 	xmlFree(ctxt->idcNodes);
27504     }
27505     if (ctxt->idcKeys != NULL) {
27506 	int i;
27507 	for (i = 0; i < ctxt->nbIdcKeys; i++)
27508 	    xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
27509 	xmlFree(ctxt->idcKeys);
27510     }
27511 
27512     if (ctxt->xpathStates != NULL) {
27513 	xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
27514 	ctxt->xpathStates = NULL;
27515     }
27516     if (ctxt->xpathStatePool != NULL) {
27517 	xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
27518 	ctxt->xpathStatePool = NULL;
27519     }
27520 
27521     /*
27522     * Augmented IDC information.
27523     */
27524     if (ctxt->aidcs != NULL) {
27525 	xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
27526 	do {
27527 	    next = cur->next;
27528 	    xmlFree(cur);
27529 	    cur = next;
27530 	} while (cur != NULL);
27531     }
27532     if (ctxt->attrInfos != NULL) {
27533 	int i;
27534 	xmlSchemaAttrInfoPtr attr;
27535 
27536 	/* Just a paranoid call to the cleanup. */
27537 	if (ctxt->nbAttrInfos != 0)
27538 	    xmlSchemaClearAttrInfos(ctxt);
27539 	for (i = 0; i < ctxt->sizeAttrInfos; i++) {
27540 	    attr = ctxt->attrInfos[i];
27541 	    xmlFree(attr);
27542 	}
27543 	xmlFree(ctxt->attrInfos);
27544     }
27545     if (ctxt->elemInfos != NULL) {
27546 	int i;
27547 	xmlSchemaNodeInfoPtr ei;
27548 
27549 	for (i = 0; i < ctxt->sizeElemInfos; i++) {
27550 	    ei = ctxt->elemInfos[i];
27551 	    if (ei == NULL)
27552 		break;
27553 	    xmlSchemaClearElemInfo(ctxt, ei);
27554 	    xmlFree(ei);
27555 	}
27556 	xmlFree(ctxt->elemInfos);
27557     }
27558     if (ctxt->nodeQNames != NULL)
27559 	xmlSchemaItemListFree(ctxt->nodeQNames);
27560     if (ctxt->dict != NULL)
27561 	xmlDictFree(ctxt->dict);
27562     xmlFree(ctxt);
27563 }
27564 
27565 /**
27566  * xmlSchemaIsValid:
27567  * @ctxt: the schema validation context
27568  *
27569  * Check if any error was detected during validation.
27570  *
27571  * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
27572  *         of internal error.
27573  */
27574 int
xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)27575 xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
27576 {
27577     if (ctxt == NULL)
27578         return(-1);
27579     return(ctxt->err == 0);
27580 }
27581 
27582 /**
27583  * xmlSchemaSetValidErrors:
27584  * @ctxt:  a schema validation context
27585  * @err:  the error function
27586  * @warn: the warning function
27587  * @ctx: the functions context
27588  *
27589  * Set the error and warning callback informations
27590  */
27591 void
xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,xmlSchemaValidityErrorFunc err,xmlSchemaValidityWarningFunc warn,void * ctx)27592 xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
27593                         xmlSchemaValidityErrorFunc err,
27594                         xmlSchemaValidityWarningFunc warn, void *ctx)
27595 {
27596     if (ctxt == NULL)
27597         return;
27598     ctxt->error = err;
27599     ctxt->warning = warn;
27600     ctxt->errCtxt = ctx;
27601     if (ctxt->pctxt != NULL)
27602 	xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
27603 }
27604 
27605 /**
27606  * xmlSchemaSetValidStructuredErrors:
27607  * @ctxt:  a schema validation context
27608  * @serror:  the structured error function
27609  * @ctx: the functions context
27610  *
27611  * Set the structured error callback
27612  */
27613 void
xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,xmlStructuredErrorFunc serror,void * ctx)27614 xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
27615 				  xmlStructuredErrorFunc serror, void *ctx)
27616 {
27617     if (ctxt == NULL)
27618         return;
27619 	ctxt->serror = serror;
27620     ctxt->error = NULL;
27621     ctxt->warning = NULL;
27622     ctxt->errCtxt = ctx;
27623     if (ctxt->pctxt != NULL)
27624 	xmlSchemaSetParserStructuredErrors(ctxt->pctxt, serror, ctx);
27625 }
27626 
27627 /**
27628  * xmlSchemaGetValidErrors:
27629  * @ctxt: a XML-Schema validation context
27630  * @err: the error function result
27631  * @warn: the warning function result
27632  * @ctx: the functions context result
27633  *
27634  * Get the error and warning callback informations
27635  *
27636  * Returns -1 in case of error and 0 otherwise
27637  */
27638 int
xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,xmlSchemaValidityErrorFunc * err,xmlSchemaValidityWarningFunc * warn,void ** ctx)27639 xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
27640 			xmlSchemaValidityErrorFunc * err,
27641 			xmlSchemaValidityWarningFunc * warn, void **ctx)
27642 {
27643 	if (ctxt == NULL)
27644 		return (-1);
27645 	if (err != NULL)
27646 		*err = ctxt->error;
27647 	if (warn != NULL)
27648 		*warn = ctxt->warning;
27649 	if (ctx != NULL)
27650 		*ctx = ctxt->errCtxt;
27651 	return (0);
27652 }
27653 
27654 
27655 /**
27656  * xmlSchemaSetValidOptions:
27657  * @ctxt:	a schema validation context
27658  * @options: a combination of xmlSchemaValidOption
27659  *
27660  * Sets the options to be used during the validation.
27661  *
27662  * Returns 0 in case of success, -1 in case of an
27663  * API error.
27664  */
27665 int
xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,int options)27666 xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
27667 			 int options)
27668 
27669 {
27670     int i;
27671 
27672     if (ctxt == NULL)
27673 	return (-1);
27674     /*
27675     * WARNING: Change the start value if adding to the
27676     * xmlSchemaValidOption.
27677     * TODO: Is there an other, more easy to maintain,
27678     * way?
27679     */
27680     for (i = 1; i < (int) sizeof(int) * 8; i++) {
27681         if (options & 1<<i)
27682 	    return (-1);
27683     }
27684     ctxt->options = options;
27685     return (0);
27686 }
27687 
27688 /**
27689  * xmlSchemaValidCtxtGetOptions:
27690  * @ctxt: a schema validation context
27691  *
27692  * Get the validation context options.
27693  *
27694  * Returns the option combination or -1 on error.
27695  */
27696 int
xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)27697 xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
27698 
27699 {
27700     if (ctxt == NULL)
27701 	return (-1);
27702     else
27703 	return (ctxt->options);
27704 }
27705 
27706 static int
xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)27707 xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
27708 {
27709     xmlAttrPtr attr;
27710     int ret = 0;
27711     xmlSchemaNodeInfoPtr ielem = NULL;
27712     xmlNodePtr node, valRoot;
27713     const xmlChar *nsName;
27714 
27715     /* DOC VAL TODO: Move this to the start function. */
27716     valRoot = xmlDocGetRootElement(vctxt->doc);
27717     if (valRoot == NULL) {
27718 	/* VAL TODO: Error code? */
27719 	VERROR(1, NULL, "The document has no document element");
27720 	return (1);
27721     }
27722     vctxt->depth = -1;
27723     vctxt->validationRoot = valRoot;
27724     node = valRoot;
27725     while (node != NULL) {
27726 	if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27727 	    goto next_sibling;
27728 	if (node->type == XML_ELEMENT_NODE) {
27729 
27730 	    /*
27731 	    * Init the node-info.
27732 	    */
27733 	    vctxt->depth++;
27734 	    if (xmlSchemaValidatorPushElem(vctxt) == -1)
27735 		goto internal_error;
27736 	    ielem = vctxt->inode;
27737 	    ielem->node = node;
27738 	    ielem->nodeLine = node->line;
27739 	    ielem->localName = node->name;
27740 	    if (node->ns != NULL)
27741 		ielem->nsName = node->ns->href;
27742 	    ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27743 	    /*
27744 	    * Register attributes.
27745 	    * DOC VAL TODO: We do not register namespace declaration
27746 	    * attributes yet.
27747 	    */
27748 	    vctxt->nbAttrInfos = 0;
27749 	    if (node->properties != NULL) {
27750 		attr = node->properties;
27751 		do {
27752 		    if (attr->ns != NULL)
27753 			nsName = attr->ns->href;
27754 		    else
27755 			nsName = NULL;
27756 		    ret = xmlSchemaValidatorPushAttribute(vctxt,
27757 			(xmlNodePtr) attr,
27758 			/*
27759 			* Note that we give it the line number of the
27760 			* parent element.
27761 			*/
27762 			ielem->nodeLine,
27763 			attr->name, nsName, 0,
27764 			xmlNodeListGetString(attr->doc, attr->children, 1), 1);
27765 		    if (ret == -1) {
27766 			VERROR_INT("xmlSchemaDocWalk",
27767 			    "calling xmlSchemaValidatorPushAttribute()");
27768 			goto internal_error;
27769 		    }
27770 		    attr = attr->next;
27771 		} while (attr);
27772 	    }
27773 	    /*
27774 	    * Validate the element.
27775 	    */
27776 	    ret = xmlSchemaValidateElem(vctxt);
27777 	    if (ret != 0) {
27778 		if (ret == -1) {
27779 		    VERROR_INT("xmlSchemaDocWalk",
27780 			"calling xmlSchemaValidateElem()");
27781 		    goto internal_error;
27782 		}
27783 		/*
27784 		* Don't stop validation; just skip the content
27785 		* of this element.
27786 		*/
27787 		goto leave_node;
27788 	    }
27789 	    if ((vctxt->skipDepth != -1) &&
27790 		(vctxt->depth >= vctxt->skipDepth))
27791 		goto leave_node;
27792 	} else if ((node->type == XML_TEXT_NODE) ||
27793 	    (node->type == XML_CDATA_SECTION_NODE)) {
27794 	    /*
27795 	    * Process character content.
27796 	    */
27797 	    if ((ielem != NULL) && (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY))
27798 		ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27799 	    ret = xmlSchemaVPushText(vctxt, node->type, node->content,
27800 		-1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
27801 	    if (ret < 0) {
27802 		VERROR_INT("xmlSchemaVDocWalk",
27803 		    "calling xmlSchemaVPushText()");
27804 		goto internal_error;
27805 	    }
27806 	    /*
27807 	    * DOC VAL TODO: Should we skip further validation of the
27808 	    * element content here?
27809 	    */
27810 	} else if ((node->type == XML_ENTITY_NODE) ||
27811 	    (node->type == XML_ENTITY_REF_NODE)) {
27812 	    /*
27813 	    * DOC VAL TODO: What to do with entities?
27814 	    */
27815 	    VERROR_INT("xmlSchemaVDocWalk",
27816 		"there is at least one entity reference in the node-tree "
27817 		"currently being validated. Processing of entities with "
27818 		"this XML Schema processor is not supported (yet). Please "
27819 		"substitute entities before validation.");
27820 	    goto internal_error;
27821 	} else {
27822 	    goto leave_node;
27823 	    /*
27824 	    * DOC VAL TODO: XInclude nodes, etc.
27825 	    */
27826 	}
27827 	/*
27828 	* Walk the doc.
27829 	*/
27830 	if (node->children != NULL) {
27831 	    node = node->children;
27832 	    continue;
27833 	}
27834 leave_node:
27835 	if (node->type == XML_ELEMENT_NODE) {
27836 	    /*
27837 	    * Leaving the scope of an element.
27838 	    */
27839 	    if (node != vctxt->inode->node) {
27840 		VERROR_INT("xmlSchemaVDocWalk",
27841 		    "element position mismatch");
27842 		goto internal_error;
27843 	    }
27844 	    ret = xmlSchemaValidatorPopElem(vctxt);
27845 	    if (ret != 0) {
27846 		if (ret < 0) {
27847 		    VERROR_INT("xmlSchemaVDocWalk",
27848 			"calling xmlSchemaValidatorPopElem()");
27849 		    goto internal_error;
27850 		}
27851 	    }
27852 	    if (node == valRoot)
27853 		goto exit;
27854 	}
27855 next_sibling:
27856 	if (node->next != NULL)
27857 	    node = node->next;
27858 	else {
27859 	    node = node->parent;
27860 	    goto leave_node;
27861 	}
27862     }
27863 
27864 exit:
27865     return (ret);
27866 internal_error:
27867     return (-1);
27868 }
27869 
27870 static int
xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt)27871 xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
27872     /*
27873     * Some initialization.
27874     */
27875     vctxt->err = 0;
27876     vctxt->nberrors = 0;
27877     vctxt->depth = -1;
27878     vctxt->skipDepth = -1;
27879     vctxt->xsiAssemble = 0;
27880     vctxt->hasKeyrefs = 0;
27881 #ifdef ENABLE_IDC_NODE_TABLES_TEST
27882     vctxt->createIDCNodeTables = 1;
27883 #else
27884     vctxt->createIDCNodeTables = 0;
27885 #endif
27886     /*
27887     * Create a schema + parser if necessary.
27888     */
27889     if (vctxt->schema == NULL) {
27890 	xmlSchemaParserCtxtPtr pctxt;
27891 
27892 	vctxt->xsiAssemble = 1;
27893 	/*
27894 	* If not schema was given then we will create a schema
27895 	* dynamically using XSI schema locations.
27896 	*
27897 	* Create the schema parser context.
27898 	*/
27899 	if ((vctxt->pctxt == NULL) &&
27900 	   (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
27901 	   return (-1);
27902 	pctxt = vctxt->pctxt;
27903 	pctxt->xsiAssemble = 1;
27904 	/*
27905 	* Create the schema.
27906 	*/
27907 	vctxt->schema = xmlSchemaNewSchema(pctxt);
27908 	if (vctxt->schema == NULL)
27909 	    return (-1);
27910 	/*
27911 	* Create the schema construction context.
27912 	*/
27913 	pctxt->constructor = xmlSchemaConstructionCtxtCreate(pctxt->dict);
27914 	if (pctxt->constructor == NULL)
27915 	    return(-1);
27916 	pctxt->constructor->mainSchema = vctxt->schema;
27917 	/*
27918 	* Take ownership of the constructor to be able to free it.
27919 	*/
27920 	pctxt->ownsConstructor = 1;
27921     }
27922     /*
27923     * Augment the IDC definitions for the main schema and all imported ones
27924     * NOTE: main schema if the first in the imported list
27925     */
27926     xmlHashScan(vctxt->schema->schemasImports,(xmlHashScanner)xmlSchemaAugmentImportedIDC, vctxt);
27927 
27928     return(0);
27929 }
27930 
27931 static void
xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt)27932 xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
27933     if (vctxt->xsiAssemble) {
27934 	if (vctxt->schema != NULL) {
27935 	    xmlSchemaFree(vctxt->schema);
27936 	    vctxt->schema = NULL;
27937 	}
27938     }
27939     xmlSchemaClearValidCtxt(vctxt);
27940 }
27941 
27942 static int
xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)27943 xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
27944 {
27945     int ret = 0;
27946 
27947     if (xmlSchemaPreRun(vctxt) < 0)
27948         return(-1);
27949 
27950     if (vctxt->doc != NULL) {
27951 	/*
27952 	 * Tree validation.
27953 	 */
27954 	ret = xmlSchemaVDocWalk(vctxt);
27955 #ifdef LIBXML_READER_ENABLED
27956     } else if (vctxt->reader != NULL) {
27957 	/*
27958 	 * XML Reader validation.
27959 	 */
27960 #ifdef XML_SCHEMA_READER_ENABLED
27961 	ret = xmlSchemaVReaderWalk(vctxt);
27962 #endif
27963 #endif
27964     } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
27965 	/*
27966 	 * SAX validation.
27967 	 */
27968 	ret = xmlParseDocument(vctxt->parserCtxt);
27969     } else {
27970 	VERROR_INT("xmlSchemaVStart",
27971 	    "no instance to validate");
27972 	ret = -1;
27973     }
27974 
27975     xmlSchemaPostRun(vctxt);
27976     if (ret == 0)
27977 	ret = vctxt->err;
27978     return (ret);
27979 }
27980 
27981 /**
27982  * xmlSchemaValidateOneElement:
27983  * @ctxt:  a schema validation context
27984  * @elem:  an element node
27985  *
27986  * Validate a branch of a tree, starting with the given @elem.
27987  *
27988  * Returns 0 if the element and its subtree is valid, a positive error
27989  * code number otherwise and -1 in case of an internal or API error.
27990  */
27991 int
xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt,xmlNodePtr elem)27992 xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
27993 {
27994     if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
27995 	return (-1);
27996 
27997     if (ctxt->schema == NULL)
27998 	return (-1);
27999 
28000     ctxt->doc = elem->doc;
28001     ctxt->node = elem;
28002     ctxt->validationRoot = elem;
28003     return(xmlSchemaVStart(ctxt));
28004 }
28005 
28006 /**
28007  * xmlSchemaValidateDoc:
28008  * @ctxt:  a schema validation context
28009  * @doc:  a parsed document tree
28010  *
28011  * Validate a document tree in memory.
28012  *
28013  * Returns 0 if the document is schemas valid, a positive error code
28014  *     number otherwise and -1 in case of internal or API error.
28015  */
28016 int
xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt,xmlDocPtr doc)28017 xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
28018 {
28019     if ((ctxt == NULL) || (doc == NULL))
28020         return (-1);
28021 
28022     ctxt->doc = doc;
28023     ctxt->node = xmlDocGetRootElement(doc);
28024     if (ctxt->node == NULL) {
28025         xmlSchemaCustomErr(ACTXT_CAST ctxt,
28026 	    XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
28027 	    (xmlNodePtr) doc, NULL,
28028 	    "The document has no document element", NULL, NULL);
28029         return (ctxt->err);
28030     }
28031     ctxt->validationRoot = ctxt->node;
28032     return (xmlSchemaVStart(ctxt));
28033 }
28034 
28035 
28036 /************************************************************************
28037  * 									*
28038  * 		Function and data for SAX streaming API			*
28039  * 									*
28040  ************************************************************************/
28041 typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
28042 typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
28043 
28044 struct _xmlSchemaSplitSAXData {
28045     xmlSAXHandlerPtr      user_sax;
28046     void                 *user_data;
28047     xmlSchemaValidCtxtPtr ctxt;
28048     xmlSAXHandlerPtr      schemas_sax;
28049 };
28050 
28051 #define XML_SAX_PLUG_MAGIC 0xdc43ba21
28052 
28053 struct _xmlSchemaSAXPlug {
28054     unsigned int magic;
28055 
28056     /* the original callbacks informations */
28057     xmlSAXHandlerPtr     *user_sax_ptr;
28058     xmlSAXHandlerPtr      user_sax;
28059     void                **user_data_ptr;
28060     void                 *user_data;
28061 
28062     /* the block plugged back and validation informations */
28063     xmlSAXHandler         schemas_sax;
28064     xmlSchemaValidCtxtPtr ctxt;
28065 };
28066 
28067 /* All those functions just bounces to the user provided SAX handlers */
28068 static void
internalSubsetSplit(void * ctx,const xmlChar * name,const xmlChar * ExternalID,const xmlChar * SystemID)28069 internalSubsetSplit(void *ctx, const xmlChar *name,
28070 	       const xmlChar *ExternalID, const xmlChar *SystemID)
28071 {
28072     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28073     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28074         (ctxt->user_sax->internalSubset != NULL))
28075 	ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
28076 	                               SystemID);
28077 }
28078 
28079 static int
isStandaloneSplit(void * ctx)28080 isStandaloneSplit(void *ctx)
28081 {
28082     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28083     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28084         (ctxt->user_sax->isStandalone != NULL))
28085 	return(ctxt->user_sax->isStandalone(ctxt->user_data));
28086     return(0);
28087 }
28088 
28089 static int
hasInternalSubsetSplit(void * ctx)28090 hasInternalSubsetSplit(void *ctx)
28091 {
28092     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28093     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28094         (ctxt->user_sax->hasInternalSubset != NULL))
28095 	return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
28096     return(0);
28097 }
28098 
28099 static int
hasExternalSubsetSplit(void * ctx)28100 hasExternalSubsetSplit(void *ctx)
28101 {
28102     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28103     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28104         (ctxt->user_sax->hasExternalSubset != NULL))
28105 	return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
28106     return(0);
28107 }
28108 
28109 static void
externalSubsetSplit(void * ctx,const xmlChar * name,const xmlChar * ExternalID,const xmlChar * SystemID)28110 externalSubsetSplit(void *ctx, const xmlChar *name,
28111 	       const xmlChar *ExternalID, const xmlChar *SystemID)
28112 {
28113     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28114     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28115         (ctxt->user_sax->externalSubset != NULL))
28116 	ctxt->user_sax->externalSubset(ctxt->user_data, name, ExternalID,
28117 	                               SystemID);
28118 }
28119 
28120 static xmlParserInputPtr
resolveEntitySplit(void * ctx,const xmlChar * publicId,const xmlChar * systemId)28121 resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
28122 {
28123     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28124     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28125         (ctxt->user_sax->resolveEntity != NULL))
28126 	return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
28127 	                                     systemId));
28128     return(NULL);
28129 }
28130 
28131 static xmlEntityPtr
getEntitySplit(void * ctx,const xmlChar * name)28132 getEntitySplit(void *ctx, const xmlChar *name)
28133 {
28134     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28135     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28136         (ctxt->user_sax->getEntity != NULL))
28137 	return(ctxt->user_sax->getEntity(ctxt->user_data, name));
28138     return(NULL);
28139 }
28140 
28141 static xmlEntityPtr
getParameterEntitySplit(void * ctx,const xmlChar * name)28142 getParameterEntitySplit(void *ctx, const xmlChar *name)
28143 {
28144     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28145     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28146         (ctxt->user_sax->getParameterEntity != NULL))
28147 	return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
28148     return(NULL);
28149 }
28150 
28151 
28152 static void
entityDeclSplit(void * ctx,const xmlChar * name,int type,const xmlChar * publicId,const xmlChar * systemId,xmlChar * content)28153 entityDeclSplit(void *ctx, const xmlChar *name, int type,
28154           const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
28155 {
28156     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28157     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28158         (ctxt->user_sax->entityDecl != NULL))
28159 	ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
28160 	                           systemId, content);
28161 }
28162 
28163 static void
attributeDeclSplit(void * ctx,const xmlChar * elem,const xmlChar * name,int type,int def,const xmlChar * defaultValue,xmlEnumerationPtr tree)28164 attributeDeclSplit(void *ctx, const xmlChar * elem,
28165                    const xmlChar * name, int type, int def,
28166                    const xmlChar * defaultValue, xmlEnumerationPtr tree)
28167 {
28168     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28169     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28170         (ctxt->user_sax->attributeDecl != NULL)) {
28171 	ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
28172 	                              def, defaultValue, tree);
28173     } else {
28174 	xmlFreeEnumeration(tree);
28175     }
28176 }
28177 
28178 static void
elementDeclSplit(void * ctx,const xmlChar * name,int type,xmlElementContentPtr content)28179 elementDeclSplit(void *ctx, const xmlChar *name, int type,
28180 	    xmlElementContentPtr content)
28181 {
28182     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28183     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28184         (ctxt->user_sax->elementDecl != NULL))
28185 	ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
28186 }
28187 
28188 static void
notationDeclSplit(void * ctx,const xmlChar * name,const xmlChar * publicId,const xmlChar * systemId)28189 notationDeclSplit(void *ctx, const xmlChar *name,
28190 	     const xmlChar *publicId, const xmlChar *systemId)
28191 {
28192     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28193     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28194         (ctxt->user_sax->notationDecl != NULL))
28195 	ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
28196 	                             systemId);
28197 }
28198 
28199 static void
unparsedEntityDeclSplit(void * ctx,const xmlChar * name,const xmlChar * publicId,const xmlChar * systemId,const xmlChar * notationName)28200 unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
28201 		   const xmlChar *publicId, const xmlChar *systemId,
28202 		   const xmlChar *notationName)
28203 {
28204     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28205     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28206         (ctxt->user_sax->unparsedEntityDecl != NULL))
28207 	ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
28208 	                                   systemId, notationName);
28209 }
28210 
28211 static void
setDocumentLocatorSplit(void * ctx,xmlSAXLocatorPtr loc)28212 setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
28213 {
28214     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28215     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28216         (ctxt->user_sax->setDocumentLocator != NULL))
28217 	ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
28218 }
28219 
28220 static void
startDocumentSplit(void * ctx)28221 startDocumentSplit(void *ctx)
28222 {
28223     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28224     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28225         (ctxt->user_sax->startDocument != NULL))
28226 	ctxt->user_sax->startDocument(ctxt->user_data);
28227 }
28228 
28229 static void
endDocumentSplit(void * ctx)28230 endDocumentSplit(void *ctx)
28231 {
28232     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28233     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28234         (ctxt->user_sax->endDocument != NULL))
28235 	ctxt->user_sax->endDocument(ctxt->user_data);
28236 }
28237 
28238 static void
processingInstructionSplit(void * ctx,const xmlChar * target,const xmlChar * data)28239 processingInstructionSplit(void *ctx, const xmlChar *target,
28240                       const xmlChar *data)
28241 {
28242     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28243     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28244         (ctxt->user_sax->processingInstruction != NULL))
28245 	ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
28246 }
28247 
28248 static void
commentSplit(void * ctx,const xmlChar * value)28249 commentSplit(void *ctx, const xmlChar *value)
28250 {
28251     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28252     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28253         (ctxt->user_sax->comment != NULL))
28254 	ctxt->user_sax->comment(ctxt->user_data, value);
28255 }
28256 
28257 /*
28258  * Varargs error callbacks to the user application, harder ...
28259  */
28260 
28261 static void XMLCDECL
warningSplit(void * ctx,const char * msg ATTRIBUTE_UNUSED,...)28262 warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28263     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28264     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28265         (ctxt->user_sax->warning != NULL)) {
28266 	TODO
28267     }
28268 }
28269 static void XMLCDECL
errorSplit(void * ctx,const char * msg ATTRIBUTE_UNUSED,...)28270 errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28271     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28272     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28273         (ctxt->user_sax->error != NULL)) {
28274 	TODO
28275     }
28276 }
28277 static void XMLCDECL
fatalErrorSplit(void * ctx,const char * msg ATTRIBUTE_UNUSED,...)28278 fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28279     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28280     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28281         (ctxt->user_sax->fatalError != NULL)) {
28282 	TODO
28283     }
28284 }
28285 
28286 /*
28287  * Those are function where both the user handler and the schemas handler
28288  * need to be called.
28289  */
28290 static void
charactersSplit(void * ctx,const xmlChar * ch,int len)28291 charactersSplit(void *ctx, const xmlChar *ch, int len)
28292 {
28293     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28294     if (ctxt == NULL)
28295         return;
28296     if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
28297 	ctxt->user_sax->characters(ctxt->user_data, ch, len);
28298     if (ctxt->ctxt != NULL)
28299 	xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28300 }
28301 
28302 static void
ignorableWhitespaceSplit(void * ctx,const xmlChar * ch,int len)28303 ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
28304 {
28305     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28306     if (ctxt == NULL)
28307         return;
28308     if ((ctxt->user_sax != NULL) &&
28309         (ctxt->user_sax->ignorableWhitespace != NULL))
28310 	ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
28311     if (ctxt->ctxt != NULL)
28312 	xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28313 }
28314 
28315 static void
cdataBlockSplit(void * ctx,const xmlChar * value,int len)28316 cdataBlockSplit(void *ctx, const xmlChar *value, int len)
28317 {
28318     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28319     if (ctxt == NULL)
28320         return;
28321     if ((ctxt->user_sax != NULL) &&
28322         (ctxt->user_sax->cdataBlock != NULL))
28323 	ctxt->user_sax->cdataBlock(ctxt->user_data, value, len);
28324     if (ctxt->ctxt != NULL)
28325 	xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
28326 }
28327 
28328 static void
referenceSplit(void * ctx,const xmlChar * name)28329 referenceSplit(void *ctx, const xmlChar *name)
28330 {
28331     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28332     if (ctxt == NULL)
28333         return;
28334     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28335         (ctxt->user_sax->reference != NULL))
28336 	ctxt->user_sax->reference(ctxt->user_data, name);
28337     if (ctxt->ctxt != NULL)
28338         xmlSchemaSAXHandleReference(ctxt->user_data, name);
28339 }
28340 
28341 static void
startElementNsSplit(void * ctx,const xmlChar * localname,const xmlChar * prefix,const xmlChar * URI,int nb_namespaces,const xmlChar ** namespaces,int nb_attributes,int nb_defaulted,const xmlChar ** attributes)28342 startElementNsSplit(void *ctx, const xmlChar * localname,
28343 		    const xmlChar * prefix, const xmlChar * URI,
28344 		    int nb_namespaces, const xmlChar ** namespaces,
28345 		    int nb_attributes, int nb_defaulted,
28346 		    const xmlChar ** attributes) {
28347     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28348     if (ctxt == NULL)
28349         return;
28350     if ((ctxt->user_sax != NULL) &&
28351         (ctxt->user_sax->startElementNs != NULL))
28352 	ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
28353 	                               URI, nb_namespaces, namespaces,
28354 				       nb_attributes, nb_defaulted,
28355 				       attributes);
28356     if (ctxt->ctxt != NULL)
28357 	xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
28358 	                                 URI, nb_namespaces, namespaces,
28359 					 nb_attributes, nb_defaulted,
28360 					 attributes);
28361 }
28362 
28363 static void
endElementNsSplit(void * ctx,const xmlChar * localname,const xmlChar * prefix,const xmlChar * URI)28364 endElementNsSplit(void *ctx, const xmlChar * localname,
28365 		    const xmlChar * prefix, const xmlChar * URI) {
28366     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28367     if (ctxt == NULL)
28368         return;
28369     if ((ctxt->user_sax != NULL) &&
28370         (ctxt->user_sax->endElementNs != NULL))
28371 	ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
28372     if (ctxt->ctxt != NULL)
28373 	xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
28374 }
28375 
28376 /**
28377  * xmlSchemaSAXPlug:
28378  * @ctxt:  a schema validation context
28379  * @sax:  a pointer to the original xmlSAXHandlerPtr
28380  * @user_data:  a pointer to the original SAX user data pointer
28381  *
28382  * Plug a SAX based validation layer in a SAX parsing event flow.
28383  * The original @saxptr and @dataptr data are replaced by new pointers
28384  * but the calls to the original will be maintained.
28385  *
28386  * Returns a pointer to a data structure needed to unplug the validation layer
28387  *         or NULL in case of errors.
28388  */
28389 xmlSchemaSAXPlugPtr
xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,xmlSAXHandlerPtr * sax,void ** user_data)28390 xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
28391 		 xmlSAXHandlerPtr *sax, void **user_data)
28392 {
28393     xmlSchemaSAXPlugPtr ret;
28394     xmlSAXHandlerPtr old_sax;
28395 
28396     if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
28397         return(NULL);
28398 
28399     /*
28400      * We only allow to plug into SAX2 event streams
28401      */
28402     old_sax = *sax;
28403     if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
28404         return(NULL);
28405     if ((old_sax != NULL) &&
28406         (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
28407         ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
28408         return(NULL);
28409 
28410     /*
28411      * everything seems right allocate the local data needed for that layer
28412      */
28413     ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
28414     if (ret == NULL) {
28415         return(NULL);
28416     }
28417     memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
28418     ret->magic = XML_SAX_PLUG_MAGIC;
28419     ret->schemas_sax.initialized = XML_SAX2_MAGIC;
28420     ret->ctxt = ctxt;
28421     ret->user_sax_ptr = sax;
28422     ret->user_sax = old_sax;
28423     if (old_sax == NULL) {
28424         /*
28425 	 * go direct, no need for the split block and functions.
28426 	 */
28427 	ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
28428 	ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
28429 	/*
28430 	 * Note that we use the same text-function for both, to prevent
28431 	 * the parser from testing for ignorable whitespace.
28432 	 */
28433 	ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
28434 	ret->schemas_sax.characters = xmlSchemaSAXHandleText;
28435 
28436 	ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
28437 	ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
28438 
28439 	ret->user_data = ctxt;
28440 	*user_data = ctxt;
28441     } else {
28442        /*
28443         * for each callback unused by Schemas initialize it to the Split
28444 	* routine only if non NULL in the user block, this can speed up
28445 	* things at the SAX level.
28446 	*/
28447         if (old_sax->internalSubset != NULL)
28448             ret->schemas_sax.internalSubset = internalSubsetSplit;
28449         if (old_sax->isStandalone != NULL)
28450             ret->schemas_sax.isStandalone = isStandaloneSplit;
28451         if (old_sax->hasInternalSubset != NULL)
28452             ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
28453         if (old_sax->hasExternalSubset != NULL)
28454             ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
28455         if (old_sax->resolveEntity != NULL)
28456             ret->schemas_sax.resolveEntity = resolveEntitySplit;
28457         if (old_sax->getEntity != NULL)
28458             ret->schemas_sax.getEntity = getEntitySplit;
28459         if (old_sax->entityDecl != NULL)
28460             ret->schemas_sax.entityDecl = entityDeclSplit;
28461         if (old_sax->notationDecl != NULL)
28462             ret->schemas_sax.notationDecl = notationDeclSplit;
28463         if (old_sax->attributeDecl != NULL)
28464             ret->schemas_sax.attributeDecl = attributeDeclSplit;
28465         if (old_sax->elementDecl != NULL)
28466             ret->schemas_sax.elementDecl = elementDeclSplit;
28467         if (old_sax->unparsedEntityDecl != NULL)
28468             ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
28469         if (old_sax->setDocumentLocator != NULL)
28470             ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
28471         if (old_sax->startDocument != NULL)
28472             ret->schemas_sax.startDocument = startDocumentSplit;
28473         if (old_sax->endDocument != NULL)
28474             ret->schemas_sax.endDocument = endDocumentSplit;
28475         if (old_sax->processingInstruction != NULL)
28476             ret->schemas_sax.processingInstruction = processingInstructionSplit;
28477         if (old_sax->comment != NULL)
28478             ret->schemas_sax.comment = commentSplit;
28479         if (old_sax->warning != NULL)
28480             ret->schemas_sax.warning = warningSplit;
28481         if (old_sax->error != NULL)
28482             ret->schemas_sax.error = errorSplit;
28483         if (old_sax->fatalError != NULL)
28484             ret->schemas_sax.fatalError = fatalErrorSplit;
28485         if (old_sax->getParameterEntity != NULL)
28486             ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
28487         if (old_sax->externalSubset != NULL)
28488             ret->schemas_sax.externalSubset = externalSubsetSplit;
28489 
28490 	/*
28491 	 * the 6 schemas callback have to go to the splitter functions
28492 	 * Note that we use the same text-function for ignorableWhitespace
28493 	 * if possible, to prevent the parser from testing for ignorable
28494 	 * whitespace.
28495 	 */
28496         ret->schemas_sax.characters = charactersSplit;
28497 	if ((old_sax->ignorableWhitespace != NULL) &&
28498 	    (old_sax->ignorableWhitespace != old_sax->characters))
28499 	    ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
28500 	else
28501 	    ret->schemas_sax.ignorableWhitespace = charactersSplit;
28502         ret->schemas_sax.cdataBlock = cdataBlockSplit;
28503         ret->schemas_sax.reference = referenceSplit;
28504         ret->schemas_sax.startElementNs = startElementNsSplit;
28505         ret->schemas_sax.endElementNs = endElementNsSplit;
28506 
28507 	ret->user_data_ptr = user_data;
28508 	ret->user_data = *user_data;
28509 	*user_data = ret;
28510     }
28511 
28512     /*
28513      * plug the pointers back.
28514      */
28515     *sax = &(ret->schemas_sax);
28516     ctxt->sax = *sax;
28517     ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28518     xmlSchemaPreRun(ctxt);
28519     return(ret);
28520 }
28521 
28522 /**
28523  * xmlSchemaSAXUnplug:
28524  * @plug:  a data structure returned by xmlSchemaSAXPlug
28525  *
28526  * Unplug a SAX based validation layer in a SAX parsing event flow.
28527  * The original pointers used in the call are restored.
28528  *
28529  * Returns 0 in case of success and -1 in case of failure.
28530  */
28531 int
xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)28532 xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
28533 {
28534     xmlSAXHandlerPtr *sax;
28535     void **user_data;
28536 
28537     if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
28538         return(-1);
28539     plug->magic = 0;
28540 
28541     xmlSchemaPostRun(plug->ctxt);
28542     /* restore the data */
28543     sax = plug->user_sax_ptr;
28544     *sax = plug->user_sax;
28545     if (plug->user_sax != NULL) {
28546 	user_data = plug->user_data_ptr;
28547 	*user_data = plug->user_data;
28548     }
28549 
28550     /* free and return */
28551     xmlFree(plug);
28552     return(0);
28553 }
28554 
28555 /**
28556  * xmlSchemaValidateStream:
28557  * @ctxt:  a schema validation context
28558  * @input:  the input to use for reading the data
28559  * @enc:  an optional encoding information
28560  * @sax:  a SAX handler for the resulting events
28561  * @user_data:  the context to provide to the SAX handler.
28562  *
28563  * Validate an input based on a flow of SAX event from the parser
28564  * and forward the events to the @sax handler with the provided @user_data
28565  * the user provided @sax handler must be a SAX2 one.
28566  *
28567  * Returns 0 if the document is schemas valid, a positive error code
28568  *     number otherwise and -1 in case of internal or API error.
28569  */
28570 int
xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,xmlParserInputBufferPtr input,xmlCharEncoding enc,xmlSAXHandlerPtr sax,void * user_data)28571 xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
28572                         xmlParserInputBufferPtr input, xmlCharEncoding enc,
28573                         xmlSAXHandlerPtr sax, void *user_data)
28574 {
28575     xmlSchemaSAXPlugPtr plug = NULL;
28576     xmlSAXHandlerPtr old_sax = NULL;
28577     xmlParserCtxtPtr pctxt = NULL;
28578     xmlParserInputPtr inputStream = NULL;
28579     int ret;
28580 
28581     if ((ctxt == NULL) || (input == NULL))
28582         return (-1);
28583 
28584     /*
28585      * prepare the parser
28586      */
28587     pctxt = xmlNewParserCtxt();
28588     if (pctxt == NULL)
28589         return (-1);
28590     old_sax = pctxt->sax;
28591     pctxt->sax = sax;
28592     pctxt->userData = user_data;
28593 #if 0
28594     if (options)
28595         xmlCtxtUseOptions(pctxt, options);
28596 #endif
28597     pctxt->linenumbers = 1;
28598 
28599     inputStream = xmlNewIOInputStream(pctxt, input, enc);;
28600     if (inputStream == NULL) {
28601         ret = -1;
28602 	goto done;
28603     }
28604     inputPush(pctxt, inputStream);
28605     ctxt->parserCtxt = pctxt;
28606     ctxt->input = input;
28607 
28608     /*
28609      * Plug the validation and launch the parsing
28610      */
28611     plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
28612     if (plug == NULL) {
28613         ret = -1;
28614 	goto done;
28615     }
28616     ctxt->input = input;
28617     ctxt->enc = enc;
28618     ctxt->sax = pctxt->sax;
28619     ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28620     ret = xmlSchemaVStart(ctxt);
28621 
28622     if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
28623 	ret = ctxt->parserCtxt->errNo;
28624 	if (ret == 0)
28625 	    ret = 1;
28626     }
28627 
28628 done:
28629     ctxt->parserCtxt = NULL;
28630     ctxt->sax = NULL;
28631     ctxt->input = NULL;
28632     if (plug != NULL) {
28633         xmlSchemaSAXUnplug(plug);
28634     }
28635     /* cleanup */
28636     if (pctxt != NULL) {
28637 	pctxt->sax = old_sax;
28638 	xmlFreeParserCtxt(pctxt);
28639     }
28640     return (ret);
28641 }
28642 
28643 /**
28644  * xmlSchemaValidateFile:
28645  * @ctxt: a schema validation context
28646  * @filename: the URI of the instance
28647  * @options: a future set of options, currently unused
28648  *
28649  * Do a schemas validation of the given resource, it will use the
28650  * SAX streamable validation internally.
28651  *
28652  * Returns 0 if the document is valid, a positive error code
28653  *     number otherwise and -1 in case of an internal or API error.
28654  */
28655 int
xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,const char * filename,int options ATTRIBUTE_UNUSED)28656 xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
28657                       const char * filename,
28658 		      int options ATTRIBUTE_UNUSED)
28659 {
28660     int ret;
28661     xmlParserInputBufferPtr input;
28662 
28663     if ((ctxt == NULL) || (filename == NULL))
28664         return (-1);
28665 
28666     input = xmlParserInputBufferCreateFilename(filename,
28667 	XML_CHAR_ENCODING_NONE);
28668     if (input == NULL)
28669 	return (-1);
28670     ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
28671 	NULL, NULL);
28672     return (ret);
28673 }
28674 
28675 /**
28676  * xmlSchemaValidCtxtGetParserCtxt:
28677  * @ctxt: a schema validation context
28678  *
28679  * allow access to the parser context of the schema validation context
28680  *
28681  * Returns the parser context of the schema validation context or NULL
28682  *         in case of error.
28683  */
28684 xmlParserCtxtPtr
xmlSchemaValidCtxtGetParserCtxt(xmlSchemaValidCtxtPtr ctxt)28685 xmlSchemaValidCtxtGetParserCtxt(xmlSchemaValidCtxtPtr ctxt)
28686 {
28687     if (ctxt == NULL)
28688         return(NULL);
28689     return (ctxt->parserCtxt);
28690 }
28691 
28692 #define bottom_xmlschemas
28693 #include "elfgcchack.h"
28694 #endif /* LIBXML_SCHEMAS_ENABLED */
28695