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 if (lastNs != NULL)
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 	if ((WXS_IS_BUCKET_IMPMAIN(type)) && (! bkt->imported)) {
10347 	    /*
10348 	    * We included/redefined and then try to import a schema,
10349 	    * but the new location provided for import was different.
10350 	    */
10351 	    if (schemaLocation == NULL)
10352 		schemaLocation = BAD_CAST "in_memory_buffer";
10353 	    if (!xmlStrEqual(schemaLocation,
10354 		bkt->schemaLocation)) {
10355 		xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10356 		    invokingNode, NULL,
10357 		    "The schema document '%s' cannot be imported, since "
10358 		    "it was already included or redefined",
10359 		    schemaLocation, NULL);
10360 		goto exit;
10361 	    }
10362 	} else if ((! WXS_IS_BUCKET_IMPMAIN(type)) && (bkt->imported)) {
10363 	    /*
10364 	    * We imported and then try to include/redefine a schema,
10365 	    * but the new location provided for the include/redefine
10366 	    * was different.
10367 	    */
10368 	    if (schemaLocation == NULL)
10369 		schemaLocation = BAD_CAST "in_memory_buffer";
10370 	    if (!xmlStrEqual(schemaLocation,
10371 		bkt->schemaLocation)) {
10372 		xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10373 		    invokingNode, NULL,
10374 		    "The schema document '%s' cannot be included or "
10375 		    "redefined, since it was already imported",
10376 		    schemaLocation, NULL);
10377 		goto exit;
10378 	    }
10379 	}
10380     }
10381 
10382     if (WXS_IS_BUCKET_IMPMAIN(type)) {
10383 	/*
10384 	* Given that the schemaLocation [attribute] is only a hint, it is open
10385 	* to applications to ignore all but the first <import> for a given
10386 	* namespace, regardless of the �actual value� of schemaLocation, but
10387 	* such a strategy risks missing useful information when new
10388 	* schemaLocations are offered.
10389 	*
10390 	* We will use the first <import> that comes with a location.
10391 	* Further <import>s *with* a location, will result in an error.
10392 	* TODO: Better would be to just report a warning here, but
10393 	* we'll try it this way until someone complains.
10394 	*
10395 	* Schema Document Location Strategy:
10396 	* 3 Based on the namespace name, identify an existing schema document,
10397 	* either as a resource which is an XML document or a <schema> element
10398 	* information item, in some local schema repository;
10399 	* 5 Attempt to resolve the namespace name to locate such a resource.
10400 	*
10401 	* NOTE: (3) and (5) are not supported.
10402 	*/
10403 	if (bkt != NULL) {
10404 	    relation->bucket = bkt;
10405 	    goto exit;
10406 	}
10407 	bkt = xmlSchemaGetSchemaBucketByTNS(pctxt,
10408 	    importNamespace, 1);
10409 
10410 	if (bkt != NULL) {
10411 	    relation->bucket = bkt;
10412 	    if (bkt->schemaLocation == NULL) {
10413 		/* First given location of the schema; load the doc. */
10414 		bkt->schemaLocation = schemaLocation;
10415 	    } else {
10416 		if (!xmlStrEqual(schemaLocation,
10417 		    bkt->schemaLocation)) {
10418 		    /*
10419 		    * Additional location given; just skip it.
10420 		    * URGENT TODO: We should report a warning here.
10421 		    * res = XML_SCHEMAP_SRC_IMPORT;
10422 		    */
10423 		    if (schemaLocation == NULL)
10424 			schemaLocation = BAD_CAST "in_memory_buffer";
10425 
10426 		    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10427 			XML_SCHEMAP_WARN_SKIP_SCHEMA,
10428 			invokingNode, NULL,
10429 			"Skipping import of schema located at '%s' for the "
10430 			"namespace '%s', since this namespace was already "
10431 			"imported with the schema located at '%s'",
10432 			schemaLocation, importNamespace, bkt->schemaLocation);
10433 		}
10434 		goto exit;
10435 	    }
10436 	}
10437 	/*
10438 	* No bucket + first location: load the doc and create a
10439 	* bucket.
10440 	*/
10441     } else {
10442 	/* <include> and <redefine> */
10443 	if (bkt != NULL) {
10444 
10445 	    if ((bkt->origTargetNamespace == NULL) &&
10446 		(bkt->targetNamespace != sourceTargetNamespace)) {
10447 		xmlSchemaBucketPtr chamel;
10448 
10449 		/*
10450 		* Chameleon include/redefine: skip loading only if it was
10451 		* aleady build for the targetNamespace of the including
10452 		* schema.
10453 		*/
10454 		/*
10455 		* URGENT TODO: If the schema is a chameleon-include then copy
10456 		* the components into the including schema and modify the
10457 		* targetNamespace of those components, do nothing otherwise.
10458 		* NOTE: This is currently worked-around by compiling the
10459 		* chameleon for every destinct including targetNamespace; thus
10460 		* not performant at the moment.
10461 		* TODO: Check when the namespace in wildcards for chameleons
10462 		* needs to be converted: before we built wildcard intersections
10463 		* or after.
10464 		*   Answer: after!
10465 		*/
10466 		chamel = xmlSchemaGetChameleonSchemaBucket(pctxt,
10467 		    schemaLocation, sourceTargetNamespace);
10468 		if (chamel != NULL) {
10469 		    /* A fitting chameleon was already parsed; NOP. */
10470 		    relation->bucket = chamel;
10471 		    goto exit;
10472 		}
10473 		/*
10474 		* We need to parse the chameleon again for a different
10475 		* targetNamespace.
10476 		* CHAMELEON TODO: Optimize this by only parsing the
10477 		* chameleon once, and then copying the components to
10478 		* the new targetNamespace.
10479 		*/
10480 		bkt = NULL;
10481 	    } else {
10482 		relation->bucket = bkt;
10483 		goto exit;
10484 	    }
10485 	}
10486     }
10487     if ((bkt != NULL) && (bkt->doc != NULL)) {
10488 	PERROR_INT("xmlSchemaAddSchemaDoc",
10489 	    "trying to load a schema doc, but a doc is already "
10490 	    "assigned to the schema bucket");
10491 	goto exit_failure;
10492     }
10493 
10494 doc_load:
10495     /*
10496     * Load the document.
10497     */
10498     if (schemaDoc != NULL) {
10499 	doc = schemaDoc;
10500 	/* Don' free this one, since it was provided by the caller. */
10501 	preserveDoc = 1;
10502 	/* TODO: Does the context or the doc hold the location? */
10503 	if (schemaDoc->URL != NULL)
10504 	    schemaLocation = xmlDictLookup(pctxt->dict,
10505 		schemaDoc->URL, -1);
10506         else
10507 	    schemaLocation = BAD_CAST "in_memory_buffer";
10508     } else if ((schemaLocation != NULL) || (schemaBuffer != NULL)) {
10509 	xmlParserCtxtPtr parserCtxt;
10510 
10511 	parserCtxt = xmlNewParserCtxt();
10512 	if (parserCtxt == NULL) {
10513 	    xmlSchemaPErrMemory(NULL, "xmlSchemaGetDoc, "
10514 		"allocating a parser context", NULL);
10515 	    goto exit_failure;
10516 	}
10517 	if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
10518 	    /*
10519 	    * TODO: Do we have to burden the schema parser dict with all
10520 	    * the content of the schema doc?
10521 	    */
10522 	    xmlDictFree(parserCtxt->dict);
10523 	    parserCtxt->dict = pctxt->dict;
10524 	    xmlDictReference(parserCtxt->dict);
10525 	}
10526 	if (schemaLocation != NULL) {
10527 	    /* Parse from file. */
10528 	    doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
10529 		NULL, SCHEMAS_PARSE_OPTIONS);
10530 	} else if (schemaBuffer != NULL) {
10531 	    /* Parse from memory buffer. */
10532 	    doc = xmlCtxtReadMemory(parserCtxt, schemaBuffer, schemaBufferLen,
10533 		NULL, NULL, SCHEMAS_PARSE_OPTIONS);
10534 	    schemaLocation = BAD_CAST "in_memory_buffer";
10535 	    if (doc != NULL)
10536 		doc->URL = xmlStrdup(schemaLocation);
10537 	}
10538 	/*
10539 	* For <import>:
10540 	* 2.1 The referent is (a fragment of) a resource which is an
10541 	* XML document (see clause 1.1), which in turn corresponds to
10542 	* a <schema> element information item in a well-formed information
10543 	* set, which in turn corresponds to a valid schema.
10544 	* TODO: (2.1) fragments of XML documents are not supported.
10545 	*
10546 	* 2.2 The referent is a <schema> element information item in
10547 	* a well-formed information set, which in turn corresponds
10548 	* to a valid schema.
10549 	* TODO: (2.2) is not supported.
10550 	*/
10551 	if (doc == NULL) {
10552 	    xmlErrorPtr lerr;
10553 	    lerr = xmlGetLastError();
10554 	    /*
10555 	    * Check if this a parser error, or if the document could
10556 	    * just not be located.
10557 	    * TODO: Try to find specific error codes to react only on
10558 	    * localisation failures.
10559 	    */
10560 	    if ((lerr == NULL) || (lerr->domain != XML_FROM_IO)) {
10561 		/*
10562 		* We assume a parser error here.
10563 		*/
10564 		located = 1;
10565 		/* TODO: Error code ?? */
10566 		res = XML_SCHEMAP_SRC_IMPORT_2_1;
10567 		xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10568 		    invokingNode, NULL,
10569 		    "Failed to parse the XML resource '%s'",
10570 		    schemaLocation, NULL);
10571 	    }
10572 	}
10573 	xmlFreeParserCtxt(parserCtxt);
10574 	if ((doc == NULL) && located)
10575 	    goto exit_error;
10576     } else {
10577 	xmlSchemaPErr(pctxt, NULL,
10578 	    XML_SCHEMAP_NOTHING_TO_PARSE,
10579 	    "No information for parsing was provided with the "
10580 	    "given schema parser context.\n",
10581 	    NULL, NULL);
10582 	goto exit_failure;
10583     }
10584     /*
10585     * Preprocess the document.
10586     */
10587     if (doc != NULL) {
10588 	xmlNodePtr docElem = NULL;
10589 
10590 	located = 1;
10591 	docElem = xmlDocGetRootElement(doc);
10592 	if (docElem == NULL) {
10593 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOROOT,
10594 		invokingNode, NULL,
10595 		"The document '%s' has no document element",
10596 		schemaLocation, NULL);
10597 	    goto exit_error;
10598 	}
10599 	/*
10600 	* Remove all the blank text nodes.
10601 	*/
10602 	xmlSchemaCleanupDoc(pctxt, docElem);
10603 	/*
10604 	* Check the schema's top level element.
10605 	*/
10606 	if (!IS_SCHEMA(docElem, "schema")) {
10607 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOT_SCHEMA,
10608 		invokingNode, NULL,
10609 		"The XML document '%s' is not a schema document",
10610 		schemaLocation, NULL);
10611 	    goto exit_error;
10612 	}
10613 	/*
10614 	* Note that we don't apply a type check for the
10615 	* targetNamespace value here.
10616 	*/
10617 	targetNamespace = xmlSchemaGetProp(pctxt, docElem,
10618 	    "targetNamespace");
10619     }
10620 
10621 /* after_doc_loading: */
10622     if ((bkt == NULL) && located) {
10623 	/* Only create a bucket if the schema was located. */
10624         bkt = xmlSchemaBucketCreate(pctxt, type,
10625 	    targetNamespace);
10626 	if (bkt == NULL)
10627 	    goto exit_failure;
10628     }
10629     if (bkt != NULL) {
10630 	bkt->schemaLocation = schemaLocation;
10631 	bkt->located = located;
10632 	if (doc != NULL) {
10633 	    bkt->doc = doc;
10634 	    bkt->targetNamespace = targetNamespace;
10635 	    bkt->origTargetNamespace = targetNamespace;
10636 	    if (preserveDoc)
10637 		bkt->preserveDoc = 1;
10638 	}
10639 	if (WXS_IS_BUCKET_IMPMAIN(type))
10640 	    bkt->imported++;
10641 	    /*
10642 	    * Add it to the graph of schemas.
10643 	    */
10644 	if (relation != NULL)
10645 	    relation->bucket = bkt;
10646     }
10647 
10648 exit:
10649     /*
10650     * Return the bucket explicitely; this is needed for the
10651     * main schema.
10652     */
10653     if (bucket != NULL)
10654 	*bucket = bkt;
10655     return (0);
10656 
10657 exit_error:
10658     if ((doc != NULL) && (! preserveDoc)) {
10659 	xmlFreeDoc(doc);
10660 	if (bkt != NULL)
10661 	    bkt->doc = NULL;
10662     }
10663     return(pctxt->err);
10664 
10665 exit_failure:
10666     if ((doc != NULL) && (! preserveDoc)) {
10667 	xmlFreeDoc(doc);
10668 	if (bkt != NULL)
10669 	    bkt->doc = NULL;
10670     }
10671     return (-1);
10672 }
10673 
10674 /**
10675  * xmlSchemaParseImport:
10676  * @ctxt:  a schema validation context
10677  * @schema:  the schema being built
10678  * @node:  a subtree containing XML Schema informations
10679  *
10680  * parse a XML schema Import definition
10681  * *WARNING* this interface is highly subject to change
10682  *
10683  * Returns 0 in case of success, a positive error code if
10684  * not valid and -1 in case of an internal error.
10685  */
10686 static int
xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)10687 xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
10688                      xmlNodePtr node)
10689 {
10690     xmlNodePtr child;
10691     const xmlChar *namespaceName = NULL, *schemaLocation = NULL;
10692     const xmlChar *thisTargetNamespace;
10693     xmlAttrPtr attr;
10694     int ret = 0;
10695     xmlSchemaBucketPtr bucket = NULL;
10696 
10697     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10698         return (-1);
10699 
10700     /*
10701     * Check for illegal attributes.
10702     */
10703     attr = node->properties;
10704     while (attr != NULL) {
10705 	if (attr->ns == NULL) {
10706 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10707 		(!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
10708 		(!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10709 		xmlSchemaPIllegalAttrErr(pctxt,
10710 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10711 	    }
10712 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10713 	    xmlSchemaPIllegalAttrErr(pctxt,
10714 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10715 	}
10716 	attr = attr->next;
10717     }
10718     /*
10719     * Extract and validate attributes.
10720     */
10721     if (xmlSchemaPValAttr(pctxt, NULL, node,
10722 	"namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10723 	&namespaceName) != 0) {
10724 	xmlSchemaPSimpleTypeErr(pctxt,
10725 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10726 	    NULL, node,
10727 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10728 	    NULL, namespaceName, NULL, NULL, NULL);
10729 	return (pctxt->err);
10730     }
10731 
10732     if (xmlSchemaPValAttr(pctxt, NULL, node,
10733 	"schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10734 	&schemaLocation) != 0) {
10735 	xmlSchemaPSimpleTypeErr(pctxt,
10736 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10737 	    NULL, node,
10738 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10739 	    NULL, namespaceName, NULL, NULL, NULL);
10740 	return (pctxt->err);
10741     }
10742     /*
10743     * And now for the children...
10744     */
10745     child = node->children;
10746     if (IS_SCHEMA(child, "annotation")) {
10747         /*
10748          * the annotation here is simply discarded ...
10749 	 * TODO: really?
10750          */
10751         child = child->next;
10752     }
10753     if (child != NULL) {
10754 	xmlSchemaPContentErr(pctxt,
10755 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10756 	    NULL, node, child, NULL,
10757 	    "(annotation?)");
10758     }
10759     /*
10760     * Apply additional constraints.
10761     *
10762     * Note that it is important to use the original @targetNamespace
10763     * (or none at all), to rule out imports of schemas _with_ a
10764     * @targetNamespace if the importing schema is a chameleon schema
10765     * (with no @targetNamespace).
10766     */
10767     thisTargetNamespace = WXS_BUCKET(pctxt)->origTargetNamespace;
10768     if (namespaceName != NULL) {
10769 	/*
10770 	* 1.1 If the namespace [attribute] is present, then its �actual value�
10771 	* must not match the �actual value� of the enclosing <schema>'s
10772 	* targetNamespace [attribute].
10773 	*/
10774 	if (xmlStrEqual(thisTargetNamespace, namespaceName)) {
10775 	    xmlSchemaPCustomErr(pctxt,
10776 		XML_SCHEMAP_SRC_IMPORT_1_1,
10777 		NULL, node,
10778 		"The value of the attribute 'namespace' must not match "
10779 		"the target namespace '%s' of the importing schema",
10780 		thisTargetNamespace);
10781 	    return (pctxt->err);
10782 	}
10783     } else {
10784 	/*
10785 	* 1.2 If the namespace [attribute] is not present, then the enclosing
10786 	* <schema> must have a targetNamespace [attribute].
10787 	*/
10788 	if (thisTargetNamespace == NULL) {
10789 	    xmlSchemaPCustomErr(pctxt,
10790 		XML_SCHEMAP_SRC_IMPORT_1_2,
10791 		NULL, node,
10792 		"The attribute 'namespace' must be existent if "
10793 		"the importing schema has no target namespace",
10794 		NULL);
10795 	    return (pctxt->err);
10796 	}
10797     }
10798     /*
10799     * Locate and acquire the schema document.
10800     */
10801     if (schemaLocation != NULL)
10802 	schemaLocation = xmlSchemaBuildAbsoluteURI(pctxt->dict,
10803 	    schemaLocation, node);
10804     ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
10805 	schemaLocation, NULL, NULL, 0, node, thisTargetNamespace,
10806 	namespaceName, &bucket);
10807 
10808     if (ret != 0)
10809 	return(ret);
10810 
10811     /*
10812     * For <import>: "It is *not* an error for the application
10813     * schema reference strategy to fail."
10814     * So just don't parse if no schema document was found.
10815     * Note that we will get no bucket if the schema could not be
10816     * located or if there was no schemaLocation.
10817     */
10818     if ((bucket == NULL) && (schemaLocation != NULL)) {
10819 	xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10820 	    XML_SCHEMAP_WARN_UNLOCATED_SCHEMA,
10821 	    node, NULL,
10822 	    "Failed to locate a schema at location '%s'. "
10823 	    "Skipping the import", schemaLocation, NULL, NULL);
10824     }
10825 
10826     if ((bucket != NULL) && CAN_PARSE_SCHEMA(bucket)) {
10827 	ret = xmlSchemaParseNewDoc(pctxt, schema, bucket);
10828     }
10829 
10830     return (ret);
10831 }
10832 
10833 static int
xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlChar ** schemaLocation,int type)10834 xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,
10835 				     xmlSchemaPtr schema,
10836 				     xmlNodePtr node,
10837 				     xmlChar **schemaLocation,
10838 				     int type)
10839 {
10840     xmlAttrPtr attr;
10841 
10842     if ((pctxt == NULL) || (schema == NULL) || (node == NULL) ||
10843 	(schemaLocation == NULL))
10844         return (-1);
10845 
10846     *schemaLocation = NULL;
10847     /*
10848     * Check for illegal attributes.
10849     * Applies for both <include> and <redefine>.
10850     */
10851     attr = node->properties;
10852     while (attr != NULL) {
10853 	if (attr->ns == NULL) {
10854 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10855 		(!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10856 		xmlSchemaPIllegalAttrErr(pctxt,
10857 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10858 	    }
10859 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10860 	    xmlSchemaPIllegalAttrErr(pctxt,
10861 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10862 	}
10863 	attr = attr->next;
10864     }
10865     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
10866     /*
10867     * Preliminary step, extract the URI-Reference and make an URI
10868     * from the base.
10869     */
10870     /*
10871     * Attribute "schemaLocation" is mandatory.
10872     */
10873     attr = xmlSchemaGetPropNode(node, "schemaLocation");
10874     if (attr != NULL) {
10875         xmlChar *base = NULL;
10876         xmlChar *uri = NULL;
10877 
10878 	if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
10879 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10880 	    (const xmlChar **) schemaLocation) != 0)
10881 	    goto exit_error;
10882 	base = xmlNodeGetBase(node->doc, node);
10883 	if (base == NULL) {
10884 	    uri = xmlBuildURI(*schemaLocation, node->doc->URL);
10885 	} else {
10886 	    uri = xmlBuildURI(*schemaLocation, base);
10887 	    xmlFree(base);
10888 	}
10889 	if (uri == NULL) {
10890 	    PERROR_INT("xmlSchemaParseIncludeOrRedefine",
10891 		"could not build an URI from the schemaLocation")
10892 	    goto exit_failure;
10893 	}
10894 	(*schemaLocation) = (xmlChar *) xmlDictLookup(pctxt->dict, uri, -1);
10895 	xmlFree(uri);
10896     } else {
10897 	xmlSchemaPMissingAttrErr(pctxt,
10898 	    XML_SCHEMAP_S4S_ATTR_MISSING,
10899 	    NULL, node, "schemaLocation", NULL);
10900 	goto exit_error;
10901     }
10902     /*
10903     * Report self-inclusion and self-redefinition.
10904     */
10905     if (xmlStrEqual(*schemaLocation, pctxt->URL)) {
10906 	if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
10907 	    xmlSchemaPCustomErr(pctxt,
10908 		XML_SCHEMAP_SRC_REDEFINE,
10909 		NULL, node,
10910 		"The schema document '%s' cannot redefine itself.",
10911 		*schemaLocation);
10912 	} else {
10913 	    xmlSchemaPCustomErr(pctxt,
10914 		XML_SCHEMAP_SRC_INCLUDE,
10915 		NULL, node,
10916 		"The schema document '%s' cannot include itself.",
10917 		*schemaLocation);
10918 	}
10919 	goto exit_error;
10920     }
10921 
10922     return(0);
10923 exit_error:
10924     return(pctxt->err);
10925 exit_failure:
10926     return(-1);
10927 }
10928 
10929 static int
xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node,int type)10930 xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,
10931 				xmlSchemaPtr schema,
10932 				xmlNodePtr node,
10933 				int type)
10934 {
10935     xmlNodePtr child = NULL;
10936     const xmlChar *schemaLocation = NULL;
10937     int res = 0; /* hasRedefinitions = 0 */
10938     int isChameleon = 0, wasChameleon = 0;
10939     xmlSchemaBucketPtr bucket = NULL;
10940 
10941     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10942         return (-1);
10943 
10944     /*
10945     * Parse attributes. Note that the returned schemaLocation will
10946     * be already converted to an absolute URI.
10947     */
10948     res = xmlSchemaParseIncludeOrRedefineAttrs(pctxt, schema,
10949 	node, (xmlChar **) (&schemaLocation), type);
10950     if (res != 0)
10951 	return(res);
10952     /*
10953     * Load and add the schema document.
10954     */
10955     res = xmlSchemaAddSchemaDoc(pctxt, type, schemaLocation, NULL,
10956 	NULL, 0, node, pctxt->targetNamespace, NULL, &bucket);
10957     if (res != 0)
10958 	return(res);
10959     /*
10960     * If we get no schema bucket back, then this means that the schema
10961     * document could not be located or was broken XML or was not
10962     * a schema document.
10963     */
10964     if ((bucket == NULL) || (bucket->doc == NULL)) {
10965 	if (type == XML_SCHEMA_SCHEMA_INCLUDE) {
10966 	    /*
10967 	    * WARNING for <include>:
10968 	    * We will raise an error if the schema cannot be located
10969 	    * for inclusions, since the that was the feedback from the
10970 	    * schema people. I.e. the following spec piece will *not* be
10971 	    * satisfied:
10972 	    * SPEC src-include: "It is not an error for the �actual value� of the
10973 	    * schemaLocation [attribute] to fail to resolve it all, in which
10974 	    * case no corresponding inclusion is performed.
10975 	    * So do we need a warning report here?"
10976 	    */
10977 	    res = XML_SCHEMAP_SRC_INCLUDE;
10978 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10979 		node, NULL,
10980 		"Failed to load the document '%s' for inclusion",
10981 		schemaLocation, NULL);
10982 	} else {
10983 	    /*
10984 	    * NOTE: This was changed to raise an error even if no redefinitions
10985 	    * are specified.
10986 	    *
10987 	    * SPEC src-redefine (1)
10988 	    * "If there are any element information items among the [children]
10989 	    * other than <annotation> then the �actual value� of the
10990 	    * schemaLocation [attribute] must successfully resolve."
10991 	    * TODO: Ask the WG if a the location has always to resolve
10992 	    * here as well!
10993 	    */
10994 	    res = XML_SCHEMAP_SRC_REDEFINE;
10995 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10996 		node, NULL,
10997 		"Failed to load the document '%s' for redefinition",
10998 		schemaLocation, NULL);
10999 	}
11000     } else {
11001 	/*
11002 	* Check targetNamespace sanity before parsing the new schema.
11003 	* TODO: Note that we won't check further content if the
11004 	* targetNamespace was bad.
11005 	*/
11006 	if (bucket->origTargetNamespace != NULL) {
11007 	    /*
11008 	    * SPEC src-include (2.1)
11009 	    * "SII has a targetNamespace [attribute], and its �actual
11010 	    * value� is identical to the �actual value� of the targetNamespace
11011 	    * [attribute] of SII� (which must have such an [attribute])."
11012 	    */
11013 	    if (pctxt->targetNamespace == NULL) {
11014 		xmlSchemaCustomErr(ACTXT_CAST pctxt,
11015 		    XML_SCHEMAP_SRC_INCLUDE,
11016 		    node, NULL,
11017 		    "The target namespace of the included/redefined schema "
11018 		    "'%s' has to be absent, since the including/redefining "
11019 		    "schema has no target namespace",
11020 		    schemaLocation, NULL);
11021 		goto exit_error;
11022 	    } else if (!xmlStrEqual(bucket->origTargetNamespace,
11023 		pctxt->targetNamespace)) {
11024 		/* TODO: Change error function. */
11025 		xmlSchemaPCustomErrExt(pctxt,
11026 		    XML_SCHEMAP_SRC_INCLUDE,
11027 		    NULL, node,
11028 		    "The target namespace '%s' of the included/redefined "
11029 		    "schema '%s' differs from '%s' of the "
11030 		    "including/redefining schema",
11031 		    bucket->origTargetNamespace, schemaLocation,
11032 		    pctxt->targetNamespace);
11033 		goto exit_error;
11034 	    }
11035 	} else if (pctxt->targetNamespace != NULL) {
11036 	    /*
11037 	    * Chameleons: the original target namespace will
11038 	    * differ from the resulting namespace.
11039 	    */
11040 	    isChameleon = 1;
11041 	    if (bucket->parsed &&
11042 		bucket->origTargetNamespace != NULL) {
11043 		xmlSchemaCustomErr(ACTXT_CAST pctxt,
11044 		    XML_SCHEMAP_SRC_INCLUDE,
11045 		    node, NULL,
11046 		    "The target namespace of the included/redefined schema "
11047 		    "'%s' has to be absent or the same as the "
11048 		    "including/redefining schema's target namespace",
11049 		    schemaLocation, NULL);
11050 		goto exit_error;
11051 	    }
11052 	    bucket->targetNamespace = pctxt->targetNamespace;
11053 	}
11054     }
11055     /*
11056     * Parse the schema.
11057     */
11058     if (bucket && (!bucket->parsed) && (bucket->doc != NULL)) {
11059 	if (isChameleon) {
11060 	    /* TODO: Get rid of this flag on the schema itself. */
11061 	    if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
11062 		schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11063 	    } else
11064 		wasChameleon = 1;
11065 	}
11066 	xmlSchemaParseNewDoc(pctxt, schema, bucket);
11067 	/* Restore chameleon flag. */
11068 	if (isChameleon && (!wasChameleon))
11069 	    schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11070     }
11071     /*
11072     * And now for the children...
11073     */
11074     child = node->children;
11075     if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11076 	/*
11077 	* Parse (simpleType | complexType | group | attributeGroup))*
11078 	*/
11079 	pctxt->redefined = bucket;
11080 	/*
11081 	* How to proceed if the redefined schema was not located?
11082 	*/
11083 	pctxt->isRedefine = 1;
11084 	while (IS_SCHEMA(child, "annotation") ||
11085 	    IS_SCHEMA(child, "simpleType") ||
11086 	    IS_SCHEMA(child, "complexType") ||
11087 	    IS_SCHEMA(child, "group") ||
11088 	    IS_SCHEMA(child, "attributeGroup")) {
11089 	    if (IS_SCHEMA(child, "annotation")) {
11090 		/*
11091 		* TODO: discard or not?
11092 		*/
11093 	    } else if (IS_SCHEMA(child, "simpleType")) {
11094 		xmlSchemaParseSimpleType(pctxt, schema, child, 1);
11095 	    } else if (IS_SCHEMA(child, "complexType")) {
11096 		xmlSchemaParseComplexType(pctxt, schema, child, 1);
11097 		/* hasRedefinitions = 1; */
11098 	    } else if (IS_SCHEMA(child, "group")) {
11099 		/* hasRedefinitions = 1; */
11100 		xmlSchemaParseModelGroupDefinition(pctxt,
11101 		    schema, child);
11102 	    } else if (IS_SCHEMA(child, "attributeGroup")) {
11103 		/* hasRedefinitions = 1; */
11104 		xmlSchemaParseAttributeGroupDefinition(pctxt, schema,
11105 		    child);
11106 	    }
11107 	    child = child->next;
11108 	}
11109 	pctxt->redefined = NULL;
11110 	pctxt->isRedefine = 0;
11111     } else {
11112 	if (IS_SCHEMA(child, "annotation")) {
11113 	    /*
11114 	    * TODO: discard or not?
11115 	    */
11116 	    child = child->next;
11117 	}
11118     }
11119     if (child != NULL) {
11120 	res = XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED;
11121 	if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11122 	    xmlSchemaPContentErr(pctxt, res,
11123 		NULL, node, child, NULL,
11124 		"(annotation | (simpleType | complexType | group | attributeGroup))*");
11125 	} else {
11126 	     xmlSchemaPContentErr(pctxt, res,
11127 		NULL, node, child, NULL,
11128 		"(annotation?)");
11129 	}
11130     }
11131     return(res);
11132 
11133 exit_error:
11134     return(pctxt->err);
11135 }
11136 
11137 static int
xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)11138 xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11139                        xmlNodePtr node)
11140 {
11141     int res;
11142 #ifndef ENABLE_REDEFINE
11143     TODO
11144     return(0);
11145 #endif
11146     res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11147 	XML_SCHEMA_SCHEMA_REDEFINE);
11148     if (res != 0)
11149 	return(res);
11150     return(0);
11151 }
11152 
11153 static int
xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)11154 xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11155                        xmlNodePtr node)
11156 {
11157     int res;
11158 
11159     res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11160 	XML_SCHEMA_SCHEMA_INCLUDE);
11161     if (res != 0)
11162 	return(res);
11163     return(0);
11164 }
11165 
11166 /**
11167  * xmlSchemaParseModelGroup:
11168  * @ctxt:  a schema validation context
11169  * @schema:  the schema being built
11170  * @node:  a subtree containing XML Schema informations
11171  * @type: the "compositor" type
11172  * @particleNeeded: if a a model group with a particle
11173  *
11174  * parse a XML schema Sequence definition.
11175  * Applies parts of:
11176  *   Schema Representation Constraint:
11177  *     Redefinition Constraints and Semantics (src-redefine)
11178  *     (6.1), (6.1.1), (6.1.2)
11179  *
11180  *   Schema Component Constraint:
11181  *     All Group Limited (cos-all-limited) (2)
11182  *     TODO: Actually this should go to component-level checks,
11183  *     but is done here due to performance. Move it to an other layer
11184  *     is schema construction via an API is implemented.
11185  *
11186  * *WARNING* this interface is highly subject to change
11187  *
11188  * Returns -1 in case of error, 0 if the declaration is improper and
11189  *         1 in case of success.
11190  */
11191 static xmlSchemaTreeItemPtr
xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlSchemaTypeType type,int withParticle)11192 xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11193 			 xmlNodePtr node, xmlSchemaTypeType type,
11194 			 int withParticle)
11195 {
11196     xmlSchemaModelGroupPtr item;
11197     xmlSchemaParticlePtr particle = NULL;
11198     xmlNodePtr child = NULL;
11199     xmlAttrPtr attr;
11200     int min = 1, max = 1, isElemRef, hasRefs = 0;
11201 
11202     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11203         return (NULL);
11204     /*
11205     * Create a model group with the given compositor.
11206     */
11207     item = xmlSchemaAddModelGroup(ctxt, schema, type, node);
11208     if (item == NULL)
11209 	return (NULL);
11210 
11211     if (withParticle) {
11212 	if (type == XML_SCHEMA_TYPE_ALL) {
11213 	    min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
11214 	    max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
11215 	} else {
11216 	    /* choice + sequence */
11217 	    min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
11218 	    max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
11219 		"(xs:nonNegativeInteger | unbounded)");
11220 	}
11221 	xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
11222 	/*
11223 	* Create a particle
11224 	*/
11225 	particle = xmlSchemaAddParticle(ctxt, node, min, max);
11226 	if (particle == NULL)
11227 	    return (NULL);
11228 	particle->children = (xmlSchemaTreeItemPtr) item;
11229 	/*
11230 	* Check for illegal attributes.
11231 	*/
11232 	attr = node->properties;
11233 	while (attr != NULL) {
11234 	    if (attr->ns == NULL) {
11235 		if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11236 		    (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
11237 		    (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
11238 		    xmlSchemaPIllegalAttrErr(ctxt,
11239 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11240 		}
11241 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11242 		xmlSchemaPIllegalAttrErr(ctxt,
11243 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11244 	    }
11245 	    attr = attr->next;
11246 	}
11247     } else {
11248 	/*
11249 	* Check for illegal attributes.
11250 	*/
11251 	attr = node->properties;
11252 	while (attr != NULL) {
11253 	    if (attr->ns == NULL) {
11254 		if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
11255 		    xmlSchemaPIllegalAttrErr(ctxt,
11256 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11257 		}
11258 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11259 		xmlSchemaPIllegalAttrErr(ctxt,
11260 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11261 	    }
11262 	    attr = attr->next;
11263 	}
11264     }
11265 
11266     /*
11267     * Extract and validate attributes.
11268     */
11269     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11270     /*
11271     * And now for the children...
11272     */
11273     child = node->children;
11274     if (IS_SCHEMA(child, "annotation")) {
11275         item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
11276         child = child->next;
11277     }
11278     if (type == XML_SCHEMA_TYPE_ALL) {
11279 	xmlSchemaParticlePtr part, last = NULL;
11280 
11281 	while (IS_SCHEMA(child, "element")) {
11282 	    part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
11283 		schema, child, &isElemRef, 0);
11284 	    /*
11285 	    * SPEC cos-all-limited (2)
11286 	    * "The {max occurs} of all the particles in the {particles}
11287 	    * of the ('all') group must be 0 or 1.
11288 	    */
11289 	    if (part != NULL) {
11290 		if (isElemRef)
11291 		    hasRefs++;
11292 		if (part->minOccurs > 1) {
11293 		    xmlSchemaPCustomErr(ctxt,
11294 			XML_SCHEMAP_COS_ALL_LIMITED,
11295 			NULL, child,
11296 			"Invalid value for minOccurs (must be 0 or 1)",
11297 			NULL);
11298 		    /* Reset to 1. */
11299 		    part->minOccurs = 1;
11300 		}
11301 		if (part->maxOccurs > 1) {
11302 		    xmlSchemaPCustomErr(ctxt,
11303 			XML_SCHEMAP_COS_ALL_LIMITED,
11304 			NULL, child,
11305 			"Invalid value for maxOccurs (must be 0 or 1)",
11306 			NULL);
11307 		    /* Reset to 1. */
11308 		    part->maxOccurs = 1;
11309 		}
11310 		if (last == NULL)
11311 		    item->children = (xmlSchemaTreeItemPtr) part;
11312 		else
11313 		    last->next = (xmlSchemaTreeItemPtr) part;
11314 		last = part;
11315 	    }
11316 	    child = child->next;
11317 	}
11318 	if (child != NULL) {
11319 	    xmlSchemaPContentErr(ctxt,
11320 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11321 		NULL, node, child, NULL,
11322 		"(annotation?, (annotation?, element*)");
11323 	}
11324     } else {
11325 	/* choice + sequence */
11326 	xmlSchemaTreeItemPtr part = NULL, last = NULL;
11327 
11328 	while ((IS_SCHEMA(child, "element")) ||
11329 	    (IS_SCHEMA(child, "group")) ||
11330 	    (IS_SCHEMA(child, "any")) ||
11331 	    (IS_SCHEMA(child, "choice")) ||
11332 	    (IS_SCHEMA(child, "sequence"))) {
11333 
11334 	    if (IS_SCHEMA(child, "element")) {
11335 		part = (xmlSchemaTreeItemPtr)
11336 		    xmlSchemaParseElement(ctxt, schema, child, &isElemRef, 0);
11337 		if (part && isElemRef)
11338 		    hasRefs++;
11339 	    } else if (IS_SCHEMA(child, "group")) {
11340 		part =
11341 		    xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11342 		if (part != NULL)
11343 		    hasRefs++;
11344 		/*
11345 		* Handle redefinitions.
11346 		*/
11347 		if (ctxt->isRedefine && ctxt->redef &&
11348 		    (ctxt->redef->item->type == XML_SCHEMA_TYPE_GROUP) &&
11349 		    part && part->children)
11350 		{
11351 		    if ((xmlSchemaGetQNameRefName(part->children) ==
11352 			    ctxt->redef->refName) &&
11353 			(xmlSchemaGetQNameRefTargetNs(part->children) ==
11354 			    ctxt->redef->refTargetNs))
11355 		    {
11356 			/*
11357 			* SPEC src-redefine:
11358 			* (6.1) "If it has a <group> among its contents at
11359 			* some level the �actual value� of whose ref
11360 			* [attribute] is the same as the �actual value� of
11361 			* its own name attribute plus target namespace, then
11362 			* all of the following must be true:"
11363 			* (6.1.1) "It must have exactly one such group."
11364 			*/
11365 			if (ctxt->redefCounter != 0) {
11366 			    xmlChar *str = NULL;
11367 
11368 			    xmlSchemaCustomErr(ACTXT_CAST ctxt,
11369 				XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11370 				"The redefining model group definition "
11371 				"'%s' must not contain more than one "
11372 				"reference to the redefined definition",
11373 				xmlSchemaFormatQName(&str,
11374 				    ctxt->redef->refTargetNs,
11375 				    ctxt->redef->refName),
11376 				NULL);
11377 			    FREE_AND_NULL(str)
11378 			    part = NULL;
11379 			} else if (((WXS_PARTICLE(part))->minOccurs != 1) ||
11380 			    ((WXS_PARTICLE(part))->maxOccurs != 1))
11381 			{
11382 			    xmlChar *str = NULL;
11383 			    /*
11384 			    * SPEC src-redefine:
11385 			    * (6.1.2) "The �actual value� of both that
11386 			    * group's minOccurs and maxOccurs [attribute]
11387 			    * must be 1 (or �absent�).
11388 			    */
11389 			    xmlSchemaCustomErr(ACTXT_CAST ctxt,
11390 				XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11391 				"The redefining model group definition "
11392 				"'%s' must not contain a reference to the "
11393 				"redefined definition with a "
11394 				"maxOccurs/minOccurs other than 1",
11395 				xmlSchemaFormatQName(&str,
11396 				    ctxt->redef->refTargetNs,
11397 				    ctxt->redef->refName),
11398 				NULL);
11399 			    FREE_AND_NULL(str)
11400 			    part = NULL;
11401 			}
11402 			ctxt->redef->reference = WXS_BASIC_CAST part;
11403 			ctxt->redefCounter++;
11404 		    }
11405 		}
11406 	    } else if (IS_SCHEMA(child, "any")) {
11407 		part = (xmlSchemaTreeItemPtr)
11408 		    xmlSchemaParseAny(ctxt, schema, child);
11409 	    } else if (IS_SCHEMA(child, "choice")) {
11410 		part = xmlSchemaParseModelGroup(ctxt, schema, child,
11411 		    XML_SCHEMA_TYPE_CHOICE, 1);
11412 	    } else if (IS_SCHEMA(child, "sequence")) {
11413 		part = xmlSchemaParseModelGroup(ctxt, schema, child,
11414 		    XML_SCHEMA_TYPE_SEQUENCE, 1);
11415 	    }
11416 	    if (part != NULL) {
11417 		if (last == NULL)
11418 		    item->children = part;
11419 		else
11420 		    last->next = part;
11421 		last = part;
11422 	    }
11423 	    child = child->next;
11424 	}
11425 	if (child != NULL) {
11426 	    xmlSchemaPContentErr(ctxt,
11427 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11428 		NULL, node, child, NULL,
11429 		"(annotation?, (element | group | choice | sequence | any)*)");
11430 	}
11431     }
11432     if ((max == 0) && (min == 0))
11433 	return (NULL);
11434     if (hasRefs) {
11435 	/*
11436 	* We need to resolve references.
11437 	*/
11438 	WXS_ADD_PENDING(ctxt, item);
11439     }
11440     if (withParticle)
11441 	return ((xmlSchemaTreeItemPtr) particle);
11442     else
11443 	return ((xmlSchemaTreeItemPtr) item);
11444 }
11445 
11446 /**
11447  * xmlSchemaParseRestriction:
11448  * @ctxt:  a schema validation context
11449  * @schema:  the schema being built
11450  * @node:  a subtree containing XML Schema informations
11451  *
11452  * parse a XML schema Restriction definition
11453  * *WARNING* this interface is highly subject to change
11454  *
11455  * Returns the type definition or NULL in case of error
11456  */
11457 static xmlSchemaTypePtr
xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlSchemaTypeType parentType)11458 xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11459                           xmlNodePtr node, xmlSchemaTypeType parentType)
11460 {
11461     xmlSchemaTypePtr type;
11462     xmlNodePtr child = NULL;
11463     xmlAttrPtr attr;
11464 
11465     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11466         return (NULL);
11467     /* Not a component, don't create it. */
11468     type = ctxt->ctxtType;
11469     type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
11470 
11471     /*
11472     * Check for illegal attributes.
11473     */
11474     attr = node->properties;
11475     while (attr != NULL) {
11476 	if (attr->ns == NULL) {
11477 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11478 		(!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11479 		xmlSchemaPIllegalAttrErr(ctxt,
11480 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11481 	    }
11482 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11483 	    xmlSchemaPIllegalAttrErr(ctxt,
11484 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11485 	}
11486 	attr = attr->next;
11487     }
11488     /*
11489     * Extract and validate attributes.
11490     */
11491     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11492     /*
11493     * Attribute
11494     */
11495     /*
11496     * Extract the base type. The "base" attribute is mandatory if inside
11497     * a complex type or if redefining.
11498     *
11499     * SPEC (1.2) "...otherwise (<restriction> has no <simpleType> "
11500     * among its [children]), the simple type definition which is
11501     * the {content type} of the type definition �resolved� to by
11502     * the �actual value� of the base [attribute]"
11503     */
11504     if (xmlSchemaPValAttrQName(ctxt, schema, NULL, node, "base",
11505 	&(type->baseNs), &(type->base)) == 0)
11506     {
11507 	if ((type->base == NULL) && (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
11508 	    xmlSchemaPMissingAttrErr(ctxt,
11509 		XML_SCHEMAP_S4S_ATTR_MISSING,
11510 		NULL, node, "base", NULL);
11511 	} else if ((ctxt->isRedefine) &&
11512 	    (type->flags & XML_SCHEMAS_TYPE_GLOBAL))
11513 	{
11514 	    if (type->base == NULL) {
11515 		xmlSchemaPMissingAttrErr(ctxt,
11516 		    XML_SCHEMAP_S4S_ATTR_MISSING,
11517 		    NULL, node, "base", NULL);
11518 	    } else if ((! xmlStrEqual(type->base, type->name)) ||
11519 		(! xmlStrEqual(type->baseNs, type->targetNamespace)))
11520 	    {
11521 		xmlChar *str1 = NULL, *str2 = NULL;
11522 		/*
11523 		* REDEFINE: SPEC src-redefine (5)
11524 		* "Within the [children], each <simpleType> must have a
11525 		* <restriction> among its [children] ... the �actual value� of
11526 		* whose base [attribute] must be the same as the �actual value�
11527 		* of its own name attribute plus target namespace;"
11528 		*/
11529 		xmlSchemaPCustomErrExt(ctxt, XML_SCHEMAP_SRC_REDEFINE,
11530 		    NULL, node, "This is a redefinition, but the QName "
11531 		    "value '%s' of the 'base' attribute does not match the "
11532 		    "type's designation '%s'",
11533 		    xmlSchemaFormatQName(&str1, type->baseNs, type->base),
11534 		    xmlSchemaFormatQName(&str2, type->targetNamespace,
11535 			type->name), NULL);
11536 		FREE_AND_NULL(str1);
11537 		FREE_AND_NULL(str2);
11538 		/* Avoid confusion and erase the values. */
11539 		type->base = NULL;
11540 		type->baseNs = NULL;
11541 	    }
11542 	}
11543     }
11544     /*
11545     * And now for the children...
11546     */
11547     child = node->children;
11548     if (IS_SCHEMA(child, "annotation")) {
11549 	/*
11550 	* Add the annotation to the simple type ancestor.
11551 	*/
11552 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11553 	    xmlSchemaParseAnnotation(ctxt, child, 1));
11554         child = child->next;
11555     }
11556     if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
11557 	/*
11558 	* Corresponds to <simpleType><restriction><simpleType>.
11559 	*/
11560 	if (IS_SCHEMA(child, "simpleType")) {
11561 	    if (type->base != NULL) {
11562 		/*
11563 		* src-restriction-base-or-simpleType
11564 		* Either the base [attribute] or the simpleType [child] of the
11565 		* <restriction> element must be present, but not both.
11566 		*/
11567 		xmlSchemaPContentErr(ctxt,
11568 		    XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11569 		    NULL, node, child,
11570 		    "The attribute 'base' and the <simpleType> child are "
11571 		    "mutually exclusive", NULL);
11572 	    } else {
11573 		type->baseType = (xmlSchemaTypePtr)
11574 		    xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11575 	    }
11576 	    child = child->next;
11577 	} else if (type->base == NULL) {
11578 	    xmlSchemaPContentErr(ctxt,
11579 		XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11580 		NULL, node, child,
11581 		"Either the attribute 'base' or a <simpleType> child "
11582 		"must be present", NULL);
11583 	}
11584     } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11585 	/*
11586 	* Corresponds to <complexType><complexContent><restriction>...
11587 	* followed by:
11588 	*
11589 	* Model groups <all>, <choice> and <sequence>.
11590 	*/
11591 	if (IS_SCHEMA(child, "all")) {
11592 	    type->subtypes = (xmlSchemaTypePtr)
11593 		xmlSchemaParseModelGroup(ctxt, schema, child,
11594 		    XML_SCHEMA_TYPE_ALL, 1);
11595 	    child = child->next;
11596 	} else if (IS_SCHEMA(child, "choice")) {
11597 	    type->subtypes = (xmlSchemaTypePtr)
11598 		xmlSchemaParseModelGroup(ctxt,
11599 		    schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
11600 	    child = child->next;
11601 	} else if (IS_SCHEMA(child, "sequence")) {
11602 	    type->subtypes = (xmlSchemaTypePtr)
11603 		xmlSchemaParseModelGroup(ctxt, schema, child,
11604 		    XML_SCHEMA_TYPE_SEQUENCE, 1);
11605 	    child = child->next;
11606 	/*
11607 	* Model group reference <group>.
11608 	*/
11609 	} else if (IS_SCHEMA(child, "group")) {
11610 	    type->subtypes = (xmlSchemaTypePtr)
11611 		xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11612 	    /*
11613 	    * Note that the reference will be resolved in
11614 	    * xmlSchemaResolveTypeReferences();
11615 	    */
11616 	    child = child->next;
11617 	}
11618     } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11619 	/*
11620 	* Corresponds to <complexType><simpleContent><restriction>...
11621 	*
11622 	* "1.1 the simple type definition corresponding to the <simpleType>
11623 	* among the [children] of <restriction> if there is one;"
11624 	*/
11625 	if (IS_SCHEMA(child, "simpleType")) {
11626 	    /*
11627 	    * We will store the to-be-restricted simple type in
11628 	    * type->contentTypeDef *temporarily*.
11629 	    */
11630 	    type->contentTypeDef = (xmlSchemaTypePtr)
11631 		xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11632 	    if ( type->contentTypeDef == NULL)
11633 		return (NULL);
11634 	    child = child->next;
11635 	}
11636     }
11637 
11638     if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
11639 	(parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
11640 	xmlSchemaFacetPtr facet, lastfacet = NULL;
11641 	/*
11642 	* Corresponds to <complexType><simpleContent><restriction>...
11643 	* <simpleType><restriction>...
11644 	*/
11645 
11646 	/*
11647 	* Add the facets to the simple type ancestor.
11648 	*/
11649 	/*
11650 	* TODO: Datatypes: 4.1.3 Constraints on XML Representation of
11651 	* Simple Type Definition Schema Representation Constraint:
11652 	* *Single Facet Value*
11653 	*/
11654 	while ((IS_SCHEMA(child, "minInclusive")) ||
11655 	    (IS_SCHEMA(child, "minExclusive")) ||
11656 	    (IS_SCHEMA(child, "maxInclusive")) ||
11657 	    (IS_SCHEMA(child, "maxExclusive")) ||
11658 	    (IS_SCHEMA(child, "totalDigits")) ||
11659 	    (IS_SCHEMA(child, "fractionDigits")) ||
11660 	    (IS_SCHEMA(child, "pattern")) ||
11661 	    (IS_SCHEMA(child, "enumeration")) ||
11662 	    (IS_SCHEMA(child, "whiteSpace")) ||
11663 	    (IS_SCHEMA(child, "length")) ||
11664 	    (IS_SCHEMA(child, "maxLength")) ||
11665 	    (IS_SCHEMA(child, "minLength"))) {
11666 	    facet = xmlSchemaParseFacet(ctxt, schema, child);
11667 	    if (facet != NULL) {
11668 		if (lastfacet == NULL)
11669 		    type->facets = facet;
11670 		else
11671 		    lastfacet->next = facet;
11672 		lastfacet = facet;
11673 		lastfacet->next = NULL;
11674 	    }
11675 	    child = child->next;
11676 	}
11677 	/*
11678 	* Create links for derivation and validation.
11679 	*/
11680 	if (type->facets != NULL) {
11681 	    xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
11682 
11683 	    facet = type->facets;
11684 	    do {
11685 		facetLink = (xmlSchemaFacetLinkPtr)
11686 		    xmlMalloc(sizeof(xmlSchemaFacetLink));
11687 		if (facetLink == NULL) {
11688 		    xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
11689 		    xmlFree(facetLink);
11690 		    return (NULL);
11691 		}
11692 		facetLink->facet = facet;
11693 		facetLink->next = NULL;
11694 		if (lastFacetLink == NULL)
11695 		    type->facetSet = facetLink;
11696 		else
11697 		    lastFacetLink->next = facetLink;
11698 		lastFacetLink = facetLink;
11699 		facet = facet->next;
11700 	    } while (facet != NULL);
11701 	}
11702     }
11703     if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
11704 	/*
11705 	* Attribute uses/declarations.
11706 	*/
11707 	if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11708 	    (xmlSchemaItemListPtr *) &(type->attrUses),
11709 	    XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
11710 	    return(NULL);
11711 	/*
11712 	* Attribute wildcard.
11713 	*/
11714 	if (IS_SCHEMA(child, "anyAttribute")) {
11715 	    type->attributeWildcard =
11716 		xmlSchemaParseAnyAttribute(ctxt, schema, child);
11717 	    child = child->next;
11718 	}
11719     }
11720     if (child != NULL) {
11721 	if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11722 	    xmlSchemaPContentErr(ctxt,
11723 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11724 		NULL, node, child, NULL,
11725 		"annotation?, (group | all | choice | sequence)?, "
11726 		"((attribute | attributeGroup)*, anyAttribute?))");
11727 	} else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11728 	     xmlSchemaPContentErr(ctxt,
11729 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11730 		NULL, node, child, NULL,
11731 		"(annotation?, (simpleType?, (minExclusive | minInclusive | "
11732 		"maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11733 		"length | minLength | maxLength | enumeration | whiteSpace | "
11734 		"pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
11735 	} else {
11736 	    /* Simple type */
11737 	    xmlSchemaPContentErr(ctxt,
11738 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11739 		NULL, node, child, NULL,
11740 		"(annotation?, (simpleType?, (minExclusive | minInclusive | "
11741 		"maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11742 		"length | minLength | maxLength | enumeration | whiteSpace | "
11743 		"pattern)*))");
11744 	}
11745     }
11746     return (NULL);
11747 }
11748 
11749 /**
11750  * xmlSchemaParseExtension:
11751  * @ctxt:  a schema validation context
11752  * @schema:  the schema being built
11753  * @node:  a subtree containing XML Schema informations
11754  *
11755  * Parses an <extension>, which is found inside a
11756  * <simpleContent> or <complexContent>.
11757  * *WARNING* this interface is highly subject to change.
11758  *
11759  * TODO: Returns the type definition or NULL in case of error
11760  */
11761 static xmlSchemaTypePtr
xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlSchemaTypeType parentType)11762 xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11763                         xmlNodePtr node, xmlSchemaTypeType parentType)
11764 {
11765     xmlSchemaTypePtr type;
11766     xmlNodePtr child = NULL;
11767     xmlAttrPtr attr;
11768 
11769     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11770         return (NULL);
11771     /* Not a component, don't create it. */
11772     type = ctxt->ctxtType;
11773     type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
11774 
11775     /*
11776     * Check for illegal attributes.
11777     */
11778     attr = node->properties;
11779     while (attr != NULL) {
11780 	if (attr->ns == NULL) {
11781 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11782 		(!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11783 		xmlSchemaPIllegalAttrErr(ctxt,
11784 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11785 	    }
11786 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11787 	    xmlSchemaPIllegalAttrErr(ctxt,
11788 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11789 	}
11790 	attr = attr->next;
11791     }
11792 
11793     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11794 
11795     /*
11796     * Attribute "base" - mandatory.
11797     */
11798     if ((xmlSchemaPValAttrQName(ctxt, schema, NULL, node,
11799 	"base", &(type->baseNs), &(type->base)) == 0) &&
11800 	(type->base == NULL)) {
11801 	xmlSchemaPMissingAttrErr(ctxt,
11802 	    XML_SCHEMAP_S4S_ATTR_MISSING,
11803 	    NULL, node, "base", NULL);
11804     }
11805     /*
11806     * And now for the children...
11807     */
11808     child = node->children;
11809     if (IS_SCHEMA(child, "annotation")) {
11810 	/*
11811 	* Add the annotation to the type ancestor.
11812 	*/
11813 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11814 	    xmlSchemaParseAnnotation(ctxt, child, 1));
11815         child = child->next;
11816     }
11817     if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11818 	/*
11819 	* Corresponds to <complexType><complexContent><extension>... and:
11820 	*
11821 	* Model groups <all>, <choice>, <sequence> and <group>.
11822 	*/
11823 	if (IS_SCHEMA(child, "all")) {
11824 	    type->subtypes = (xmlSchemaTypePtr)
11825 		xmlSchemaParseModelGroup(ctxt, schema,
11826 		    child, XML_SCHEMA_TYPE_ALL, 1);
11827 	    child = child->next;
11828 	} else if (IS_SCHEMA(child, "choice")) {
11829 	    type->subtypes = (xmlSchemaTypePtr)
11830 		xmlSchemaParseModelGroup(ctxt, schema,
11831 		    child, XML_SCHEMA_TYPE_CHOICE, 1);
11832 	    child = child->next;
11833 	} else if (IS_SCHEMA(child, "sequence")) {
11834 	    type->subtypes = (xmlSchemaTypePtr)
11835 		xmlSchemaParseModelGroup(ctxt, schema,
11836 		child, XML_SCHEMA_TYPE_SEQUENCE, 1);
11837 	    child = child->next;
11838 	} else if (IS_SCHEMA(child, "group")) {
11839 	    type->subtypes = (xmlSchemaTypePtr)
11840 		xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11841 	    /*
11842 	    * Note that the reference will be resolved in
11843 	    * xmlSchemaResolveTypeReferences();
11844 	    */
11845 	    child = child->next;
11846 	}
11847     }
11848     if (child != NULL) {
11849 	/*
11850 	* Attribute uses/declarations.
11851 	*/
11852 	if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11853 	    (xmlSchemaItemListPtr *) &(type->attrUses),
11854 	    XML_SCHEMA_TYPE_EXTENSION, NULL) == -1)
11855 	    return(NULL);
11856 	/*
11857 	* Attribute wildcard.
11858 	*/
11859 	if (IS_SCHEMA(child, "anyAttribute")) {
11860 	    ctxt->ctxtType->attributeWildcard =
11861 		xmlSchemaParseAnyAttribute(ctxt, schema, child);
11862 	    child = child->next;
11863 	}
11864     }
11865     if (child != NULL) {
11866 	if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11867 	    /* Complex content extension. */
11868 	    xmlSchemaPContentErr(ctxt,
11869 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11870 		NULL, node, child, NULL,
11871 		"(annotation?, ((group | all | choice | sequence)?, "
11872 		"((attribute | attributeGroup)*, anyAttribute?)))");
11873 	} else {
11874 	    /* Simple content extension. */
11875 	    xmlSchemaPContentErr(ctxt,
11876 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11877 		NULL, node, child, NULL,
11878 		"(annotation?, ((attribute | attributeGroup)*, "
11879 		"anyAttribute?))");
11880 	}
11881     }
11882     return (NULL);
11883 }
11884 
11885 /**
11886  * xmlSchemaParseSimpleContent:
11887  * @ctxt:  a schema validation context
11888  * @schema:  the schema being built
11889  * @node:  a subtree containing XML Schema informations
11890  *
11891  * parse a XML schema SimpleContent definition
11892  * *WARNING* this interface is highly subject to change
11893  *
11894  * Returns the type definition or NULL in case of error
11895  */
11896 static int
xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int * hasRestrictionOrExtension)11897 xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
11898                             xmlSchemaPtr schema, xmlNodePtr node,
11899 			    int *hasRestrictionOrExtension)
11900 {
11901     xmlSchemaTypePtr type;
11902     xmlNodePtr child = NULL;
11903     xmlAttrPtr attr;
11904 
11905     if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11906 	(hasRestrictionOrExtension == NULL))
11907         return (-1);
11908     *hasRestrictionOrExtension = 0;
11909     /* Not a component, don't create it. */
11910     type = ctxt->ctxtType;
11911     type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
11912     /*
11913     * Check for illegal attributes.
11914     */
11915     attr = node->properties;
11916     while (attr != NULL) {
11917 	if (attr->ns == NULL) {
11918 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
11919 		xmlSchemaPIllegalAttrErr(ctxt,
11920 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11921 	    }
11922 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11923 	    xmlSchemaPIllegalAttrErr(ctxt,
11924 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11925 	}
11926 	attr = attr->next;
11927     }
11928 
11929     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11930 
11931     /*
11932     * And now for the children...
11933     */
11934     child = node->children;
11935     if (IS_SCHEMA(child, "annotation")) {
11936 	/*
11937 	* Add the annotation to the complex type ancestor.
11938 	*/
11939 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11940 	    xmlSchemaParseAnnotation(ctxt, child, 1));
11941         child = child->next;
11942     }
11943     if (child == NULL) {
11944 	xmlSchemaPContentErr(ctxt,
11945 	    XML_SCHEMAP_S4S_ELEM_MISSING,
11946 	    NULL, node, NULL, NULL,
11947 	    "(annotation?, (restriction | extension))");
11948     }
11949     if (child == NULL) {
11950 	xmlSchemaPContentErr(ctxt,
11951 	    XML_SCHEMAP_S4S_ELEM_MISSING,
11952 	    NULL, node, NULL, NULL,
11953 	    "(annotation?, (restriction | extension))");
11954     }
11955     if (IS_SCHEMA(child, "restriction")) {
11956         xmlSchemaParseRestriction(ctxt, schema, child,
11957 	    XML_SCHEMA_TYPE_SIMPLE_CONTENT);
11958 	(*hasRestrictionOrExtension) = 1;
11959         child = child->next;
11960     } else if (IS_SCHEMA(child, "extension")) {
11961         xmlSchemaParseExtension(ctxt, schema, child,
11962 	    XML_SCHEMA_TYPE_SIMPLE_CONTENT);
11963 	(*hasRestrictionOrExtension) = 1;
11964         child = child->next;
11965     }
11966     if (child != NULL) {
11967 	xmlSchemaPContentErr(ctxt,
11968 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11969 	    NULL, node, child, NULL,
11970 	    "(annotation?, (restriction | extension))");
11971     }
11972     return (0);
11973 }
11974 
11975 /**
11976  * xmlSchemaParseComplexContent:
11977  * @ctxt:  a schema validation context
11978  * @schema:  the schema being built
11979  * @node:  a subtree containing XML Schema informations
11980  *
11981  * parse a XML schema ComplexContent definition
11982  * *WARNING* this interface is highly subject to change
11983  *
11984  * Returns the type definition or NULL in case of error
11985  */
11986 static int
xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int * hasRestrictionOrExtension)11987 xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
11988                              xmlSchemaPtr schema, xmlNodePtr node,
11989 			     int *hasRestrictionOrExtension)
11990 {
11991     xmlSchemaTypePtr type;
11992     xmlNodePtr child = NULL;
11993     xmlAttrPtr attr;
11994 
11995     if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11996 	(hasRestrictionOrExtension == NULL))
11997         return (-1);
11998     *hasRestrictionOrExtension = 0;
11999     /* Not a component, don't create it. */
12000     type = ctxt->ctxtType;
12001     /*
12002     * Check for illegal attributes.
12003     */
12004     attr = node->properties;
12005     while (attr != NULL) {
12006 	if (attr->ns == NULL) {
12007 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
12008 		(!xmlStrEqual(attr->name, BAD_CAST "mixed")))
12009 	    {
12010 		xmlSchemaPIllegalAttrErr(ctxt,
12011 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12012 	    }
12013 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12014 	    xmlSchemaPIllegalAttrErr(ctxt,
12015 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12016 	}
12017 	attr = attr->next;
12018     }
12019 
12020     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12021 
12022     /*
12023     * Set the 'mixed' on the complex type ancestor.
12024     */
12025     if (xmlGetBooleanProp(ctxt, node, "mixed", 0))  {
12026 	if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
12027 	    type->flags |= XML_SCHEMAS_TYPE_MIXED;
12028     }
12029     child = node->children;
12030     if (IS_SCHEMA(child, "annotation")) {
12031 	/*
12032 	* Add the annotation to the complex type ancestor.
12033 	*/
12034 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
12035 	    xmlSchemaParseAnnotation(ctxt, child, 1));
12036         child = child->next;
12037     }
12038     if (child == NULL) {
12039 	xmlSchemaPContentErr(ctxt,
12040 	    XML_SCHEMAP_S4S_ELEM_MISSING,
12041 	    NULL, node, NULL,
12042 	    NULL, "(annotation?, (restriction | extension))");
12043     }
12044     if (child == NULL) {
12045 	xmlSchemaPContentErr(ctxt,
12046 	    XML_SCHEMAP_S4S_ELEM_MISSING,
12047 	    NULL, node, NULL,
12048 	    NULL, "(annotation?, (restriction | extension))");
12049     }
12050     if (IS_SCHEMA(child, "restriction")) {
12051         xmlSchemaParseRestriction(ctxt, schema, child,
12052 	    XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12053 	(*hasRestrictionOrExtension) = 1;
12054         child = child->next;
12055     } else if (IS_SCHEMA(child, "extension")) {
12056         xmlSchemaParseExtension(ctxt, schema, child,
12057 	    XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12058 	(*hasRestrictionOrExtension) = 1;
12059         child = child->next;
12060     }
12061     if (child != NULL) {
12062 	xmlSchemaPContentErr(ctxt,
12063 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12064 	    NULL, node, child,
12065 	    NULL, "(annotation?, (restriction | extension))");
12066     }
12067     return (0);
12068 }
12069 
12070 /**
12071  * xmlSchemaParseComplexType:
12072  * @ctxt:  a schema validation context
12073  * @schema:  the schema being built
12074  * @node:  a subtree containing XML Schema informations
12075  *
12076  * parse a XML schema Complex Type definition
12077  * *WARNING* this interface is highly subject to change
12078  *
12079  * Returns the type definition or NULL in case of error
12080  */
12081 static xmlSchemaTypePtr
xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int topLevel)12082 xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
12083                           xmlNodePtr node, int topLevel)
12084 {
12085     xmlSchemaTypePtr type, ctxtType;
12086     xmlNodePtr child = NULL;
12087     const xmlChar *name = NULL;
12088     xmlAttrPtr attr;
12089     const xmlChar *attrValue;
12090 #ifdef ENABLE_NAMED_LOCALS
12091     char buf[40];
12092 #endif
12093     int final = 0, block = 0, hasRestrictionOrExtension = 0;
12094 
12095 
12096     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
12097         return (NULL);
12098 
12099     ctxtType = ctxt->ctxtType;
12100 
12101     if (topLevel) {
12102 	attr = xmlSchemaGetPropNode(node, "name");
12103 	if (attr == NULL) {
12104 	    xmlSchemaPMissingAttrErr(ctxt,
12105 		XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
12106 	    return (NULL);
12107 	} else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
12108 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
12109 	    return (NULL);
12110 	}
12111     }
12112 
12113     if (topLevel == 0) {
12114 	/*
12115 	* Parse as local complex type definition.
12116 	*/
12117 #ifdef ENABLE_NAMED_LOCALS
12118         snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
12119 	type = xmlSchemaAddType(ctxt, schema,
12120 	    XML_SCHEMA_TYPE_COMPLEX,
12121 	    xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
12122 	    ctxt->targetNamespace, node, 0);
12123 #else
12124 	type = xmlSchemaAddType(ctxt, schema,
12125 	    XML_SCHEMA_TYPE_COMPLEX,
12126 	    NULL, ctxt->targetNamespace, node, 0);
12127 #endif
12128 	if (type == NULL)
12129 	    return (NULL);
12130 	name = type->name;
12131 	type->node = node;
12132 	type->type = XML_SCHEMA_TYPE_COMPLEX;
12133 	/*
12134 	* TODO: We need the target namespace.
12135 	*/
12136     } else {
12137 	/*
12138 	* Parse as global complex type definition.
12139 	*/
12140 	type = xmlSchemaAddType(ctxt, schema,
12141 	    XML_SCHEMA_TYPE_COMPLEX,
12142 	    name, ctxt->targetNamespace, node, 1);
12143 	if (type == NULL)
12144 	    return (NULL);
12145 	type->node = node;
12146 	type->type = XML_SCHEMA_TYPE_COMPLEX;
12147 	type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
12148     }
12149     type->targetNamespace = ctxt->targetNamespace;
12150     /*
12151     * Handle attributes.
12152     */
12153     attr = node->properties;
12154     while (attr != NULL) {
12155 	if (attr->ns == NULL) {
12156 	    if (xmlStrEqual(attr->name, BAD_CAST "id")) {
12157 		/*
12158 		* Attribute "id".
12159 		*/
12160 		xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12161 	    } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
12162 		/*
12163 		* Attribute "mixed".
12164 		*/
12165 		if (xmlSchemaPGetBoolNodeValue(ctxt,
12166 			NULL, (xmlNodePtr) attr))
12167 		    type->flags |= XML_SCHEMAS_TYPE_MIXED;
12168 	    } else if (topLevel) {
12169 		/*
12170 		* Attributes of global complex type definitions.
12171 		*/
12172 		if (xmlStrEqual(attr->name, BAD_CAST "name")) {
12173 		    /* Pass. */
12174 		} else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
12175 		    /*
12176 		    * Attribute "abstract".
12177 		    */
12178 		    if (xmlSchemaPGetBoolNodeValue(ctxt,
12179 			    NULL, (xmlNodePtr) attr))
12180 			type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
12181 		} else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
12182 		    /*
12183 		    * Attribute "final".
12184 		    */
12185 		    attrValue = xmlSchemaGetNodeContent(ctxt,
12186 			(xmlNodePtr) attr);
12187 		    if (xmlSchemaPValAttrBlockFinal(attrValue,
12188 			&(type->flags),
12189 			-1,
12190 			XML_SCHEMAS_TYPE_FINAL_EXTENSION,
12191 			XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
12192 			-1, -1, -1) != 0)
12193 		    {
12194 			xmlSchemaPSimpleTypeErr(ctxt,
12195 			    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12196 			    NULL, (xmlNodePtr) attr, NULL,
12197 			    "(#all | List of (extension | restriction))",
12198 			    attrValue, NULL, NULL, NULL);
12199 		    } else
12200 			final = 1;
12201 		} else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
12202 		    /*
12203 		    * Attribute "block".
12204 		    */
12205 		    attrValue = xmlSchemaGetNodeContent(ctxt,
12206 			(xmlNodePtr) attr);
12207 		    if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
12208 			-1,
12209 			XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
12210 			XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
12211 			-1, -1, -1) != 0) {
12212 			xmlSchemaPSimpleTypeErr(ctxt,
12213 			    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12214 			    NULL, (xmlNodePtr) attr, NULL,
12215 			    "(#all | List of (extension | restriction)) ",
12216 			    attrValue, NULL, NULL, NULL);
12217 		    } else
12218 			block = 1;
12219 		} else {
12220 			xmlSchemaPIllegalAttrErr(ctxt,
12221 			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12222 		}
12223 	    } else {
12224 		xmlSchemaPIllegalAttrErr(ctxt,
12225 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12226 	    }
12227 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12228 	    xmlSchemaPIllegalAttrErr(ctxt,
12229 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12230 	}
12231 	attr = attr->next;
12232     }
12233     if (! block) {
12234 	/*
12235 	* Apply default "block" values.
12236 	*/
12237 	if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
12238 	    type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
12239 	if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
12240 	    type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
12241     }
12242     if (! final) {
12243 	/*
12244 	* Apply default "block" values.
12245 	*/
12246 	if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
12247 	    type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
12248 	if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
12249 	    type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
12250     }
12251     /*
12252     * And now for the children...
12253     */
12254     child = node->children;
12255     if (IS_SCHEMA(child, "annotation")) {
12256         type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
12257         child = child->next;
12258     }
12259     ctxt->ctxtType = type;
12260     if (IS_SCHEMA(child, "simpleContent")) {
12261 	/*
12262 	* <complexType><simpleContent>...
12263 	* 3.4.3 : 2.2
12264 	* Specifying mixed='true' when the <simpleContent>
12265 	* alternative is chosen has no effect
12266 	*/
12267 	if (type->flags & XML_SCHEMAS_TYPE_MIXED)
12268 	    type->flags ^= XML_SCHEMAS_TYPE_MIXED;
12269         xmlSchemaParseSimpleContent(ctxt, schema, child,
12270 	    &hasRestrictionOrExtension);
12271         child = child->next;
12272     } else if (IS_SCHEMA(child, "complexContent")) {
12273 	/*
12274 	* <complexType><complexContent>...
12275 	*/
12276 	type->contentType = XML_SCHEMA_CONTENT_EMPTY;
12277         xmlSchemaParseComplexContent(ctxt, schema, child,
12278 	    &hasRestrictionOrExtension);
12279         child = child->next;
12280     } else {
12281 	/*
12282 	* E.g <complexType><sequence>... or <complexType><attribute>... etc.
12283 	*
12284 	* SPEC
12285 	* "...the third alternative (neither <simpleContent> nor
12286 	* <complexContent>) is chosen. This case is understood as shorthand
12287 	* for complex content restricting the �ur-type definition�, and the
12288 	* details of the mappings should be modified as necessary.
12289 	*/
12290 	type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12291 	type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
12292 	/*
12293 	* Parse model groups.
12294 	*/
12295         if (IS_SCHEMA(child, "all")) {
12296             type->subtypes = (xmlSchemaTypePtr)
12297 		xmlSchemaParseModelGroup(ctxt, schema, child,
12298 		    XML_SCHEMA_TYPE_ALL, 1);
12299             child = child->next;
12300         } else if (IS_SCHEMA(child, "choice")) {
12301             type->subtypes = (xmlSchemaTypePtr)
12302 		xmlSchemaParseModelGroup(ctxt, schema, child,
12303 		    XML_SCHEMA_TYPE_CHOICE, 1);
12304             child = child->next;
12305         } else if (IS_SCHEMA(child, "sequence")) {
12306             type->subtypes = (xmlSchemaTypePtr)
12307 		xmlSchemaParseModelGroup(ctxt, schema, child,
12308 		    XML_SCHEMA_TYPE_SEQUENCE, 1);
12309             child = child->next;
12310         } else if (IS_SCHEMA(child, "group")) {
12311             type->subtypes = (xmlSchemaTypePtr)
12312 		xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
12313 	    /*
12314 	    * Note that the reference will be resolved in
12315 	    * xmlSchemaResolveTypeReferences();
12316 	    */
12317             child = child->next;
12318         }
12319 	/*
12320 	* Parse attribute decls/refs.
12321 	*/
12322         if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
12323 	    (xmlSchemaItemListPtr *) &(type->attrUses),
12324 	    XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
12325 	    return(NULL);
12326 	/*
12327 	* Parse attribute wildcard.
12328 	*/
12329 	if (IS_SCHEMA(child, "anyAttribute")) {
12330 	    type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
12331 	    child = child->next;
12332 	}
12333     }
12334     if (child != NULL) {
12335 	xmlSchemaPContentErr(ctxt,
12336 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12337 	    NULL, node, child,
12338 	    NULL, "(annotation?, (simpleContent | complexContent | "
12339 	    "((group | all | choice | sequence)?, ((attribute | "
12340 	    "attributeGroup)*, anyAttribute?))))");
12341     }
12342     /*
12343     * REDEFINE: SPEC src-redefine (5)
12344     */
12345     if (topLevel && ctxt->isRedefine && (! hasRestrictionOrExtension)) {
12346 	xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
12347 	    NULL, node, "This is a redefinition, thus the "
12348 	    "<complexType> must have a <restriction> or <extension> "
12349 	    "grand-child", NULL);
12350     }
12351     ctxt->ctxtType = ctxtType;
12352     return (type);
12353 }
12354 
12355 /************************************************************************
12356  * 									*
12357  * 			Validating using Schemas			*
12358  * 									*
12359  ************************************************************************/
12360 
12361 /************************************************************************
12362  * 									*
12363  * 			Reading/Writing Schemas				*
12364  * 									*
12365  ************************************************************************/
12366 
12367 #if 0 /* Will be enabled if it is clear what options are needed. */
12368 /**
12369  * xmlSchemaParserCtxtSetOptions:
12370  * @ctxt:	a schema parser context
12371  * @options: a combination of xmlSchemaParserOption
12372  *
12373  * Sets the options to be used during the parse.
12374  *
12375  * Returns 0 in case of success, -1 in case of an
12376  * API error.
12377  */
12378 static int
12379 xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
12380 			      int options)
12381 
12382 {
12383     int i;
12384 
12385     if (ctxt == NULL)
12386 	return (-1);
12387     /*
12388     * WARNING: Change the start value if adding to the
12389     * xmlSchemaParseOption.
12390     */
12391     for (i = 1; i < (int) sizeof(int) * 8; i++) {
12392         if (options & 1<<i) {
12393 	    return (-1);
12394         }
12395     }
12396     ctxt->options = options;
12397     return (0);
12398 }
12399 
12400 /**
12401  * xmlSchemaValidCtxtGetOptions:
12402  * @ctxt: a schema parser context
12403  *
12404  * Returns the option combination of the parser context.
12405  */
12406 static int
12407 xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
12408 
12409 {
12410     if (ctxt == NULL)
12411 	return (-1);
12412     else
12413 	return (ctxt->options);
12414 }
12415 #endif
12416 
12417 /**
12418  * xmlSchemaNewParserCtxt:
12419  * @URL:  the location of the schema
12420  *
12421  * Create an XML Schemas parse context for that file/resource expected
12422  * to contain an XML Schemas file.
12423  *
12424  * Returns the parser context or NULL in case of error
12425  */
12426 xmlSchemaParserCtxtPtr
xmlSchemaNewParserCtxt(const char * URL)12427 xmlSchemaNewParserCtxt(const char *URL)
12428 {
12429     xmlSchemaParserCtxtPtr ret;
12430 
12431     if (URL == NULL)
12432         return (NULL);
12433 
12434     ret = xmlSchemaParserCtxtCreate();
12435     if (ret == NULL)
12436 	return(NULL);
12437     ret->dict = xmlDictCreate();
12438     ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
12439     return (ret);
12440 }
12441 
12442 /**
12443  * xmlSchemaNewMemParserCtxt:
12444  * @buffer:  a pointer to a char array containing the schemas
12445  * @size:  the size of the array
12446  *
12447  * Create an XML Schemas parse context for that memory buffer expected
12448  * to contain an XML Schemas file.
12449  *
12450  * Returns the parser context or NULL in case of error
12451  */
12452 xmlSchemaParserCtxtPtr
xmlSchemaNewMemParserCtxt(const char * buffer,int size)12453 xmlSchemaNewMemParserCtxt(const char *buffer, int size)
12454 {
12455     xmlSchemaParserCtxtPtr ret;
12456 
12457     if ((buffer == NULL) || (size <= 0))
12458         return (NULL);
12459     ret = xmlSchemaParserCtxtCreate();
12460     if (ret == NULL)
12461 	return(NULL);
12462     ret->buffer = buffer;
12463     ret->size = size;
12464     ret->dict = xmlDictCreate();
12465     return (ret);
12466 }
12467 
12468 /**
12469  * xmlSchemaNewDocParserCtxt:
12470  * @doc:  a preparsed document tree
12471  *
12472  * Create an XML Schemas parse context for that document.
12473  * NB. The document may be modified during the parsing process.
12474  *
12475  * Returns the parser context or NULL in case of error
12476  */
12477 xmlSchemaParserCtxtPtr
xmlSchemaNewDocParserCtxt(xmlDocPtr doc)12478 xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
12479 {
12480     xmlSchemaParserCtxtPtr ret;
12481 
12482     if (doc == NULL)
12483       return (NULL);
12484     ret = xmlSchemaParserCtxtCreate();
12485     if (ret == NULL)
12486 	return(NULL);
12487     ret->doc = doc;
12488     ret->dict = xmlDictCreate();
12489     /* The application has responsibility for the document */
12490     ret->preserve = 1;
12491 
12492     return (ret);
12493 }
12494 
12495 /**
12496  * xmlSchemaFreeParserCtxt:
12497  * @ctxt:  the schema parser context
12498  *
12499  * Free the resources associated to the schema parser context
12500  */
12501 void
xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)12502 xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
12503 {
12504     if (ctxt == NULL)
12505         return;
12506     if (ctxt->doc != NULL && !ctxt->preserve)
12507         xmlFreeDoc(ctxt->doc);
12508     if (ctxt->vctxt != NULL) {
12509 	xmlSchemaFreeValidCtxt(ctxt->vctxt);
12510     }
12511     if (ctxt->ownsConstructor && (ctxt->constructor != NULL)) {
12512 	xmlSchemaConstructionCtxtFree(ctxt->constructor);
12513 	ctxt->constructor = NULL;
12514 	ctxt->ownsConstructor = 0;
12515     }
12516     if (ctxt->attrProhibs != NULL)
12517 	xmlSchemaItemListFree(ctxt->attrProhibs);
12518     xmlDictFree(ctxt->dict);
12519     xmlFree(ctxt);
12520 }
12521 
12522 /************************************************************************
12523  *									*
12524  *			Building the content models			*
12525  *									*
12526  ************************************************************************/
12527 
12528 /**
12529  * xmlSchemaBuildContentModelForSubstGroup:
12530  *
12531  * Returns 1 if nillable, 0 otherwise
12532  */
12533 static int
xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,xmlSchemaParticlePtr particle,int counter,xmlAutomataStatePtr end)12534 xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
12535 	xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end)
12536 {
12537     xmlAutomataStatePtr start, tmp;
12538     xmlSchemaElementPtr elemDecl, member;
12539     xmlSchemaSubstGroupPtr substGroup;
12540     int i;
12541     int ret = 0;
12542 
12543     elemDecl = (xmlSchemaElementPtr) particle->children;
12544     /*
12545     * Wrap the substitution group with a CHOICE.
12546     */
12547     start = pctxt->state;
12548     if (end == NULL)
12549 	end = xmlAutomataNewState(pctxt->am);
12550     substGroup = xmlSchemaSubstGroupGet(pctxt, elemDecl);
12551     if (substGroup == NULL) {
12552 	xmlSchemaPErr(pctxt, WXS_ITEM_NODE(particle),
12553 	    XML_SCHEMAP_INTERNAL,
12554 	    "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
12555 	    "declaration is marked having a subst. group but none "
12556 	    "available.\n", elemDecl->name, NULL);
12557 	return(0);
12558     }
12559     if (counter >= 0) {
12560 	/*
12561 	* NOTE that we put the declaration in, even if it's abstract.
12562 	* However, an error will be raised during *validation* if an element
12563 	* information item shall be validated against an abstract element
12564 	* declaration.
12565 	*/
12566 	tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter);
12567         xmlAutomataNewTransition2(pctxt->am, tmp, end,
12568 	            elemDecl->name, elemDecl->targetNamespace, elemDecl);
12569 	/*
12570 	* Add subst. group members.
12571 	*/
12572 	for (i = 0; i < substGroup->members->nbItems; i++) {
12573 	    member = (xmlSchemaElementPtr) substGroup->members->items[i];
12574             xmlAutomataNewTransition2(pctxt->am, tmp, end,
12575 		               member->name, member->targetNamespace, member);
12576 	}
12577     } else if (particle->maxOccurs == 1) {
12578 	/*
12579 	* NOTE that we put the declaration in, even if it's abstract,
12580 	*/
12581 	xmlAutomataNewEpsilon(pctxt->am,
12582 	    xmlAutomataNewTransition2(pctxt->am,
12583 	    start, NULL,
12584 	    elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
12585 	/*
12586 	* Add subst. group members.
12587 	*/
12588 	for (i = 0; i < substGroup->members->nbItems; i++) {
12589 	    member = (xmlSchemaElementPtr) substGroup->members->items[i];
12590 	    /*
12591 	    * NOTE: This fixes bug #341150. xmlAutomataNewOnceTrans2()
12592 	    *  was incorrectly used instead of xmlAutomataNewTransition2()
12593 	    *  (seems like a copy&paste bug from the XML_SCHEMA_TYPE_ALL
12594 	    *  section in xmlSchemaBuildAContentModel() ).
12595 	    * TODO: Check if xmlAutomataNewOnceTrans2() was instead
12596 	    *  intended for the above "counter" section originally. I.e.,
12597 	    *  check xs:all with subst-groups.
12598 	    *
12599 	    * tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL,
12600 	    *	               member->name, member->targetNamespace,
12601 	    *		       1, 1, member);
12602 	    */
12603 	    tmp = xmlAutomataNewTransition2(pctxt->am, start, NULL,
12604 		member->name, member->targetNamespace, member);
12605 	    xmlAutomataNewEpsilon(pctxt->am, tmp, end);
12606 	}
12607     } else {
12608 	xmlAutomataStatePtr hop;
12609 	int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12610 	    UNBOUNDED : particle->maxOccurs - 1;
12611 	int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12612 
12613 	counter =
12614 	    xmlAutomataNewCounter(pctxt->am, minOccurs,
12615 	    maxOccurs);
12616 	hop = xmlAutomataNewState(pctxt->am);
12617 
12618 	xmlAutomataNewEpsilon(pctxt->am,
12619 	    xmlAutomataNewTransition2(pctxt->am,
12620 	    start, NULL,
12621 	    elemDecl->name, elemDecl->targetNamespace, elemDecl),
12622 	    hop);
12623 	/*
12624 	 * Add subst. group members.
12625 	 */
12626 	for (i = 0; i < substGroup->members->nbItems; i++) {
12627 	    member = (xmlSchemaElementPtr) substGroup->members->items[i];
12628 	    xmlAutomataNewEpsilon(pctxt->am,
12629 		xmlAutomataNewTransition2(pctxt->am,
12630 		start, NULL,
12631 		member->name, member->targetNamespace, member),
12632 		hop);
12633 	}
12634 	xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12635 	xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12636     }
12637     if (particle->minOccurs == 0) {
12638 	xmlAutomataNewEpsilon(pctxt->am, start, end);
12639         ret = 1;
12640     }
12641     pctxt->state = end;
12642     return(ret);
12643 }
12644 
12645 /**
12646  * xmlSchemaBuildContentModelForElement:
12647  *
12648  * Returns 1 if nillable, 0 otherwise
12649  */
12650 static int
xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr particle)12651 xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
12652 				     xmlSchemaParticlePtr particle)
12653 {
12654     int ret = 0;
12655 
12656     if (((xmlSchemaElementPtr) particle->children)->flags &
12657 	XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
12658 	/*
12659 	* Substitution groups.
12660 	*/
12661 	ret = xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
12662     } else {
12663 	xmlSchemaElementPtr elemDecl;
12664 	xmlAutomataStatePtr start;
12665 
12666 	elemDecl = (xmlSchemaElementPtr) particle->children;
12667 
12668 	if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
12669 	    return(0);
12670 	if (particle->maxOccurs == 1) {
12671 	    start = ctxt->state;
12672 	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12673 		    elemDecl->name, elemDecl->targetNamespace, elemDecl);
12674 	} else if ((particle->maxOccurs >= UNBOUNDED) &&
12675 	           (particle->minOccurs < 2)) {
12676 	    /* Special case. */
12677 	    start = ctxt->state;
12678 	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12679 		elemDecl->name, elemDecl->targetNamespace, elemDecl);
12680 	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, ctxt->state, ctxt->state,
12681 		elemDecl->name, elemDecl->targetNamespace, elemDecl);
12682 	} else {
12683 	    int counter;
12684 	    int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12685 			    UNBOUNDED : particle->maxOccurs - 1;
12686 	    int minOccurs = particle->minOccurs < 1 ?
12687 			    0 : particle->minOccurs - 1;
12688 
12689 	    start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
12690 	    counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
12691 	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12692 		elemDecl->name, elemDecl->targetNamespace, elemDecl);
12693 	    xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
12694 	    ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
12695 		NULL, counter);
12696 	}
12697 	if (particle->minOccurs == 0) {
12698 	    xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
12699             ret = 1;
12700         }
12701     }
12702     return(ret);
12703 }
12704 
12705 /**
12706  * xmlSchemaBuildAContentModel:
12707  * @ctxt:  the schema parser context
12708  * @particle:  the particle component
12709  * @name:  the complex type's name whose content is being built
12710  *
12711  * Create the automaton for the {content type} of a complex type.
12712  *
12713  * Returns 1 if the content is nillable, 0 otherwise
12714  */
12715 static int
xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,xmlSchemaParticlePtr particle)12716 xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
12717 			    xmlSchemaParticlePtr particle)
12718 {
12719     int ret = 0, tmp2;
12720 
12721     if (particle == NULL) {
12722 	PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL");
12723 	return(1);
12724     }
12725     if (particle->children == NULL) {
12726 	/*
12727 	* Just return in this case. A missing "term" of the particle
12728 	* might arise due to an invalid "term" component.
12729 	*/
12730 	return(1);
12731     }
12732 
12733     switch (particle->children->type) {
12734 	case XML_SCHEMA_TYPE_ANY: {
12735 	    xmlAutomataStatePtr start, end;
12736 	    xmlSchemaWildcardPtr wild;
12737 	    xmlSchemaWildcardNsPtr ns;
12738 
12739 	    wild = (xmlSchemaWildcardPtr) particle->children;
12740 
12741 	    start = pctxt->state;
12742 	    end = xmlAutomataNewState(pctxt->am);
12743 
12744 	    if (particle->maxOccurs == 1) {
12745 		if (wild->any == 1) {
12746 		    /*
12747 		    * We need to add both transitions:
12748 		    *
12749 		    * 1. the {"*", "*"} for elements in a namespace.
12750 		    */
12751 		    pctxt->state =
12752 			xmlAutomataNewTransition2(pctxt->am,
12753 			start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12754 		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12755 		    /*
12756 		    * 2. the {"*"} for elements in no namespace.
12757 		    */
12758 		    pctxt->state =
12759 			xmlAutomataNewTransition2(pctxt->am,
12760 			start, NULL, BAD_CAST "*", NULL, wild);
12761 		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12762 
12763 		} else if (wild->nsSet != NULL) {
12764 		    ns = wild->nsSet;
12765 		    do {
12766 			pctxt->state = start;
12767 			pctxt->state = xmlAutomataNewTransition2(pctxt->am,
12768 			    pctxt->state, NULL, BAD_CAST "*", ns->value, wild);
12769 			xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12770 			ns = ns->next;
12771 		    } while (ns != NULL);
12772 
12773 		} else if (wild->negNsSet != NULL) {
12774 		    pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12775 			start, end, BAD_CAST "*", wild->negNsSet->value,
12776 			wild);
12777 		}
12778 	    } else {
12779 		int counter;
12780 		xmlAutomataStatePtr hop;
12781 		int maxOccurs =
12782 		    particle->maxOccurs == UNBOUNDED ? UNBOUNDED :
12783                                            particle->maxOccurs - 1;
12784 		int minOccurs =
12785 		    particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12786 
12787 		counter = xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12788 		hop = xmlAutomataNewState(pctxt->am);
12789 		if (wild->any == 1) {
12790 		    pctxt->state =
12791 			xmlAutomataNewTransition2(pctxt->am,
12792 			start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12793 		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12794 		    pctxt->state =
12795 			xmlAutomataNewTransition2(pctxt->am,
12796 			start, NULL, BAD_CAST "*", NULL, wild);
12797 		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12798 		} else if (wild->nsSet != NULL) {
12799 		    ns = wild->nsSet;
12800 		    do {
12801 			pctxt->state =
12802 			    xmlAutomataNewTransition2(pctxt->am,
12803 				start, NULL, BAD_CAST "*", ns->value, wild);
12804 			xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12805 			ns = ns->next;
12806 		    } while (ns != NULL);
12807 
12808 		} else if (wild->negNsSet != NULL) {
12809 		    pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12810 			start, hop, BAD_CAST "*", wild->negNsSet->value,
12811 			wild);
12812 		}
12813 		xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12814 		xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12815 	    }
12816 	    if (particle->minOccurs == 0) {
12817 		xmlAutomataNewEpsilon(pctxt->am, start, end);
12818                 ret = 1;
12819 	    }
12820 	    pctxt->state = end;
12821             break;
12822 	}
12823         case XML_SCHEMA_TYPE_ELEMENT:
12824 	    ret = xmlSchemaBuildContentModelForElement(pctxt, particle);
12825 	    break;
12826         case XML_SCHEMA_TYPE_SEQUENCE:{
12827             xmlSchemaTreeItemPtr sub;
12828 
12829             ret = 1;
12830             /*
12831              * If max and min occurances are default (1) then
12832              * simply iterate over the particles of the <sequence>.
12833              */
12834             if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
12835                 sub = particle->children->children;
12836 
12837                 while (sub != NULL) {
12838                     tmp2 = xmlSchemaBuildAContentModel(pctxt,
12839                                         (xmlSchemaParticlePtr) sub);
12840                     if (tmp2 != 1) ret = 0;
12841                     sub = sub->next;
12842                 }
12843             } else {
12844                 xmlAutomataStatePtr oldstate = pctxt->state;
12845 
12846                 if (particle->maxOccurs >= UNBOUNDED) {
12847                     if (particle->minOccurs > 1) {
12848                         xmlAutomataStatePtr tmp;
12849                         int counter;
12850 
12851                         pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12852                             oldstate, NULL);
12853                         oldstate = pctxt->state;
12854 
12855                         counter = xmlAutomataNewCounter(pctxt->am,
12856                             particle->minOccurs - 1, UNBOUNDED);
12857 
12858                         sub = particle->children->children;
12859                         while (sub != NULL) {
12860                             tmp2 = xmlSchemaBuildAContentModel(pctxt,
12861                                             (xmlSchemaParticlePtr) sub);
12862                             if (tmp2 != 1) ret = 0;
12863                             sub = sub->next;
12864                         }
12865                         tmp = pctxt->state;
12866                         xmlAutomataNewCountedTrans(pctxt->am, tmp,
12867                                                    oldstate, counter);
12868                         pctxt->state =
12869                             xmlAutomataNewCounterTrans(pctxt->am, tmp,
12870                                                        NULL, counter);
12871                         if (ret == 1)
12872                             xmlAutomataNewEpsilon(pctxt->am,
12873                                                 oldstate, pctxt->state);
12874 
12875                     } else {
12876                         pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12877                             oldstate, NULL);
12878                         oldstate = pctxt->state;
12879 
12880                         sub = particle->children->children;
12881                         while (sub != NULL) {
12882                             tmp2 = xmlSchemaBuildAContentModel(pctxt,
12883                                         (xmlSchemaParticlePtr) sub);
12884                             if (tmp2 != 1) ret = 0;
12885                             sub = sub->next;
12886                         }
12887                         xmlAutomataNewEpsilon(pctxt->am, pctxt->state,
12888                                               oldstate);
12889                         /*
12890                          * epsilon needed to block previous trans from
12891                          * being allowed to enter back from another
12892                          * construct
12893                          */
12894                         pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12895                                             pctxt->state, NULL);
12896                         if (particle->minOccurs == 0) {
12897                             xmlAutomataNewEpsilon(pctxt->am,
12898                                 oldstate, pctxt->state);
12899                             ret = 1;
12900                         }
12901                     }
12902                 } else if ((particle->maxOccurs > 1)
12903                            || (particle->minOccurs > 1)) {
12904                     xmlAutomataStatePtr tmp;
12905                     int counter;
12906 
12907                     pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12908                         oldstate, NULL);
12909                     oldstate = pctxt->state;
12910 
12911                     counter = xmlAutomataNewCounter(pctxt->am,
12912                         particle->minOccurs - 1,
12913                         particle->maxOccurs - 1);
12914 
12915                     sub = particle->children->children;
12916                     while (sub != NULL) {
12917                         tmp2 = xmlSchemaBuildAContentModel(pctxt,
12918                                         (xmlSchemaParticlePtr) sub);
12919                         if (tmp2 != 1) ret = 0;
12920                         sub = sub->next;
12921                     }
12922                     tmp = pctxt->state;
12923                     xmlAutomataNewCountedTrans(pctxt->am,
12924                         tmp, oldstate, counter);
12925                     pctxt->state =
12926                         xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL,
12927                                                    counter);
12928                     if ((particle->minOccurs == 0) || (ret == 1)) {
12929                         xmlAutomataNewEpsilon(pctxt->am,
12930                                             oldstate, pctxt->state);
12931                         ret = 1;
12932                     }
12933                 } else {
12934                     sub = particle->children->children;
12935                     while (sub != NULL) {
12936                         tmp2 = xmlSchemaBuildAContentModel(pctxt,
12937                                         (xmlSchemaParticlePtr) sub);
12938                         if (tmp2 != 1) ret = 0;
12939                         sub = sub->next;
12940                     }
12941                     if (particle->minOccurs == 0) {
12942                         xmlAutomataNewEpsilon(pctxt->am, oldstate,
12943                                               pctxt->state);
12944                         ret = 1;
12945                     }
12946                 }
12947             }
12948             break;
12949         }
12950         case XML_SCHEMA_TYPE_CHOICE:{
12951             xmlSchemaTreeItemPtr sub;
12952             xmlAutomataStatePtr start, end;
12953 
12954             ret = 0;
12955             start = pctxt->state;
12956             end = xmlAutomataNewState(pctxt->am);
12957 
12958             /*
12959              * iterate over the subtypes and remerge the end with an
12960              * epsilon transition
12961              */
12962             if (particle->maxOccurs == 1) {
12963                 sub = particle->children->children;
12964                 while (sub != NULL) {
12965                     pctxt->state = start;
12966                     tmp2 = xmlSchemaBuildAContentModel(pctxt,
12967                                         (xmlSchemaParticlePtr) sub);
12968                     if (tmp2 == 1) ret = 1;
12969                     xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12970                     sub = sub->next;
12971                 }
12972             } else {
12973                 int counter;
12974                 xmlAutomataStatePtr hop, base;
12975                 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12976                     UNBOUNDED : particle->maxOccurs - 1;
12977                 int minOccurs =
12978                     particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12979 
12980                 /*
12981                  * use a counter to keep track of the number of transtions
12982                  * which went through the choice.
12983                  */
12984                 counter =
12985                     xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12986                 hop = xmlAutomataNewState(pctxt->am);
12987                 base = xmlAutomataNewState(pctxt->am);
12988 
12989                 sub = particle->children->children;
12990                 while (sub != NULL) {
12991                     pctxt->state = base;
12992                     tmp2 = xmlSchemaBuildAContentModel(pctxt,
12993                                         (xmlSchemaParticlePtr) sub);
12994                     if (tmp2 == 1) ret = 1;
12995                     xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12996                     sub = sub->next;
12997                 }
12998                 xmlAutomataNewEpsilon(pctxt->am, start, base);
12999                 xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter);
13000                 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
13001                 if (ret == 1)
13002                     xmlAutomataNewEpsilon(pctxt->am, base, end);
13003             }
13004             if (particle->minOccurs == 0) {
13005                 xmlAutomataNewEpsilon(pctxt->am, start, end);
13006                 ret = 1;
13007             }
13008             pctxt->state = end;
13009             break;
13010         }
13011         case XML_SCHEMA_TYPE_ALL:{
13012             xmlAutomataStatePtr start, tmp;
13013             xmlSchemaParticlePtr sub;
13014             xmlSchemaElementPtr elemDecl;
13015 
13016             ret = 1;
13017 
13018             sub = (xmlSchemaParticlePtr) particle->children->children;
13019             if (sub == NULL)
13020                 break;
13021 
13022             ret = 0;
13023 
13024             start = pctxt->state;
13025             tmp = xmlAutomataNewState(pctxt->am);
13026             xmlAutomataNewEpsilon(pctxt->am, pctxt->state, tmp);
13027             pctxt->state = tmp;
13028             while (sub != NULL) {
13029                 pctxt->state = tmp;
13030 
13031                 elemDecl = (xmlSchemaElementPtr) sub->children;
13032                 if (elemDecl == NULL) {
13033                     PERROR_INT("xmlSchemaBuildAContentModel",
13034                         "<element> particle has no term");
13035                     return(ret);
13036                 };
13037                 /*
13038                 * NOTE: The {max occurs} of all the particles in the
13039                 * {particles} of the group must be 0 or 1; this is
13040                 * already ensured during the parse of the content of
13041                 * <all>.
13042                 */
13043                 if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
13044                     int counter;
13045 
13046                     /*
13047                      * This is an abstract group, we need to share
13048                      * the same counter for all the element transitions
13049                      * derived from the group
13050                      */
13051                     counter = xmlAutomataNewCounter(pctxt->am,
13052                                        sub->minOccurs, sub->maxOccurs);
13053                     xmlSchemaBuildContentModelForSubstGroup(pctxt,
13054                                        sub, counter, pctxt->state);
13055                 } else {
13056                     if ((sub->minOccurs == 1) &&
13057                         (sub->maxOccurs == 1)) {
13058                         xmlAutomataNewOnceTrans2(pctxt->am, pctxt->state,
13059                                                 pctxt->state,
13060                                                 elemDecl->name,
13061                                                 elemDecl->targetNamespace,
13062                                                 1, 1, elemDecl);
13063                     } else if ((sub->minOccurs == 0) &&
13064                         (sub->maxOccurs == 1)) {
13065 
13066                         xmlAutomataNewCountTrans2(pctxt->am, pctxt->state,
13067                                                  pctxt->state,
13068                                                  elemDecl->name,
13069                                                  elemDecl->targetNamespace,
13070                                                  0,
13071                                                  1,
13072                                                  elemDecl);
13073                     }
13074                 }
13075                 sub = (xmlSchemaParticlePtr) sub->next;
13076             }
13077             pctxt->state =
13078                 xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, 0);
13079             if (particle->minOccurs == 0) {
13080                 xmlAutomataNewEpsilon(pctxt->am, start, pctxt->state);
13081                 ret = 1;
13082             }
13083             break;
13084         }
13085 	case XML_SCHEMA_TYPE_GROUP:
13086 	    /*
13087 	    * If we hit a model group definition, then this means that
13088 	    * it was empty, thus was not substituted for the containing
13089 	    * model group. Just do nothing in this case.
13090 	    * TODO: But the group should be substituted and not occur at
13091 	    * all in the content model at this point. Fix this.
13092 	    */
13093             ret = 1;
13094 	    break;
13095         default:
13096 	    xmlSchemaInternalErr2(ACTXT_CAST pctxt,
13097 		"xmlSchemaBuildAContentModel",
13098 		"found unexpected term of type '%s' in content model",
13099 		WXS_ITEM_TYPE_NAME(particle->children), NULL);
13100             return(ret);
13101     }
13102     return(ret);
13103 }
13104 
13105 /**
13106  * xmlSchemaBuildContentModel:
13107  * @ctxt:  the schema parser context
13108  * @type:  the complex type definition
13109  * @name:  the element name
13110  *
13111  * Builds the content model of the complex type.
13112  */
13113 static void
xmlSchemaBuildContentModel(xmlSchemaTypePtr type,xmlSchemaParserCtxtPtr ctxt)13114 xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
13115 			   xmlSchemaParserCtxtPtr ctxt)
13116 {
13117     if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
13118 	(type->contModel != NULL) ||
13119 	((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
13120 	(type->contentType != XML_SCHEMA_CONTENT_MIXED)))
13121 	return;
13122 
13123 #ifdef DEBUG_CONTENT
13124     xmlGenericError(xmlGenericErrorContext,
13125                     "Building content model for %s\n", name);
13126 #endif
13127     ctxt->am = NULL;
13128     ctxt->am = xmlNewAutomata();
13129     if (ctxt->am == NULL) {
13130         xmlGenericError(xmlGenericErrorContext,
13131 	    "Cannot create automata for complex type %s\n", type->name);
13132         return;
13133     }
13134     ctxt->state = xmlAutomataGetInitState(ctxt->am);
13135     /*
13136     * Build the automaton.
13137     */
13138     xmlSchemaBuildAContentModel(ctxt, WXS_TYPE_PARTICLE(type));
13139     xmlAutomataSetFinalState(ctxt->am, ctxt->state);
13140     type->contModel = xmlAutomataCompile(ctxt->am);
13141     if (type->contModel == NULL) {
13142         xmlSchemaPCustomErr(ctxt,
13143 	    XML_SCHEMAP_INTERNAL,
13144 	    WXS_BASIC_CAST type, type->node,
13145 	    "Failed to compile the content model", NULL);
13146     } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
13147         xmlSchemaPCustomErr(ctxt,
13148 	    XML_SCHEMAP_NOT_DETERMINISTIC,
13149 	    /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
13150 	    WXS_BASIC_CAST type, type->node,
13151 	    "The content model is not determinist", NULL);
13152     } else {
13153 #ifdef DEBUG_CONTENT_REGEXP
13154         xmlGenericError(xmlGenericErrorContext,
13155                         "Content model of %s:\n", type->name);
13156         xmlRegexpPrint(stderr, type->contModel);
13157 #endif
13158     }
13159     ctxt->state = NULL;
13160     xmlFreeAutomata(ctxt->am);
13161     ctxt->am = NULL;
13162 }
13163 
13164 /**
13165  * xmlSchemaResolveElementReferences:
13166  * @elem:  the schema element context
13167  * @ctxt:  the schema parser context
13168  *
13169  * Resolves the references of an element declaration
13170  * or particle, which has an element declaration as it's
13171  * term.
13172  */
13173 static void
xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,xmlSchemaParserCtxtPtr ctxt)13174 xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,
13175 				  xmlSchemaParserCtxtPtr ctxt)
13176 {
13177     if ((ctxt == NULL) || (elemDecl == NULL) ||
13178 	((elemDecl != NULL) &&
13179 	(elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
13180         return;
13181     elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
13182 
13183     if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
13184 	xmlSchemaTypePtr type;
13185 
13186 	/* (type definition) ... otherwise the type definition �resolved�
13187 	* to by the �actual value� of the type [attribute] ...
13188 	*/
13189 	type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
13190 	    elemDecl->namedTypeNs);
13191 	if (type == NULL) {
13192 	    xmlSchemaPResCompAttrErr(ctxt,
13193 		XML_SCHEMAP_SRC_RESOLVE,
13194 		WXS_BASIC_CAST elemDecl, elemDecl->node,
13195 		"type", elemDecl->namedType, elemDecl->namedTypeNs,
13196 		XML_SCHEMA_TYPE_BASIC, "type definition");
13197 	} else
13198 	    elemDecl->subtypes = type;
13199     }
13200     if (elemDecl->substGroup != NULL) {
13201 	xmlSchemaElementPtr substHead;
13202 
13203 	/*
13204 	* FIXME TODO: Do we need a new field in _xmlSchemaElement for
13205 	* substitutionGroup?
13206 	*/
13207 	substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
13208 	    elemDecl->substGroupNs);
13209 	if (substHead == NULL) {
13210 	    xmlSchemaPResCompAttrErr(ctxt,
13211 		XML_SCHEMAP_SRC_RESOLVE,
13212 		WXS_BASIC_CAST elemDecl, NULL,
13213 		"substitutionGroup", elemDecl->substGroup,
13214 		elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
13215 	} else {
13216 	    xmlSchemaResolveElementReferences(substHead, ctxt);
13217 	    /*
13218 	    * Set the "substitution group affiliation".
13219 	    * NOTE that now we use the "refDecl" field for this.
13220 	    */
13221 	    WXS_SUBST_HEAD(elemDecl) = substHead;
13222 	    /*
13223 	    * The type definitions is set to:
13224 	    * SPEC "...the {type definition} of the element
13225 	    * declaration �resolved� to by the �actual value�
13226 	    * of the substitutionGroup [attribute], if present"
13227 	    */
13228 	    if (elemDecl->subtypes == NULL)
13229 		elemDecl->subtypes = substHead->subtypes;
13230 	}
13231     }
13232     /*
13233     * SPEC "The definition of anyType serves as the default type definition
13234     * for element declarations whose XML representation does not specify one."
13235     */
13236     if ((elemDecl->subtypes == NULL) &&
13237 	(elemDecl->namedType == NULL) &&
13238 	(elemDecl->substGroup == NULL))
13239 	elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
13240 }
13241 
13242 /**
13243  * xmlSchemaResolveUnionMemberTypes:
13244  * @ctxt:  the schema parser context
13245  * @type:  the schema simple type definition
13246  *
13247  * Checks and builds the "member type definitions" property of the union
13248  * simple type. This handles part (1), part (2) is done in
13249  * xmlSchemaFinishMemberTypeDefinitionsProperty()
13250  *
13251  * Returns -1 in case of an internal error, 0 otherwise.
13252  */
13253 static int
xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)13254 xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
13255 				 xmlSchemaTypePtr type)
13256 {
13257 
13258     xmlSchemaTypeLinkPtr link, lastLink, newLink;
13259     xmlSchemaTypePtr memberType;
13260 
13261     /*
13262     * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
13263     * define the explicit members as the type definitions �resolved�
13264     * to by the items in the �actual value� of the memberTypes [attribute],
13265     * if any, followed by the type definitions corresponding to the
13266     * <simpleType>s among the [children] of <union>, if any."
13267     */
13268     /*
13269     * Resolve references.
13270     */
13271     link = type->memberTypes;
13272     lastLink = NULL;
13273     while (link != NULL) {
13274 	const xmlChar *name, *nsName;
13275 
13276 	name = ((xmlSchemaQNameRefPtr) link->type)->name;
13277 	nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
13278 
13279 	memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
13280 	if ((memberType == NULL) || (! WXS_IS_SIMPLE(memberType))) {
13281 	    xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
13282 		WXS_BASIC_CAST type, type->node, "memberTypes",
13283 		name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
13284 	    /*
13285 	    * Remove the member type link.
13286 	    */
13287 	    if (lastLink == NULL)
13288 		type->memberTypes = link->next;
13289 	    else
13290 		lastLink->next = link->next;
13291 	    newLink = link;
13292 	    link = link->next;
13293 	    xmlFree(newLink);
13294 	} else {
13295 	    link->type = memberType;
13296 	    lastLink = link;
13297 	    link = link->next;
13298 	}
13299     }
13300     /*
13301     * Add local simple types,
13302     */
13303     memberType = type->subtypes;
13304     while (memberType != NULL) {
13305 	link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
13306 	if (link == NULL) {
13307 	    xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
13308 	    return (-1);
13309 	}
13310 	link->type = memberType;
13311 	link->next = NULL;
13312 	if (lastLink == NULL)
13313 	    type->memberTypes = link;
13314 	else
13315 	    lastLink->next = link;
13316 	lastLink = link;
13317 	memberType = memberType->next;
13318     }
13319     return (0);
13320 }
13321 
13322 /**
13323  * xmlSchemaIsDerivedFromBuiltInType:
13324  * @ctxt:  the schema parser context
13325  * @type:  the type definition
13326  * @valType: the value type
13327  *
13328  *
13329  * Returns 1 if the type has the given value type, or
13330  * is derived from such a type.
13331  */
13332 static int
xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type,int valType)13333 xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13334 {
13335     if (type == NULL)
13336 	return (0);
13337     if (WXS_IS_COMPLEX(type))
13338 	return (0);
13339     if (type->type == XML_SCHEMA_TYPE_BASIC) {
13340 	if (type->builtInType == valType)
13341 	    return(1);
13342 	if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13343 	    (type->builtInType == XML_SCHEMAS_ANYTYPE))
13344 	    return (0);
13345 	return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13346     }
13347     return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13348 }
13349 
13350 #if 0
13351 /**
13352  * xmlSchemaIsDerivedFromBuiltInType:
13353  * @ctxt:  the schema parser context
13354  * @type:  the type definition
13355  * @valType: the value type
13356  *
13357  *
13358  * Returns 1 if the type has the given value type, or
13359  * is derived from such a type.
13360  */
13361 static int
13362 xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13363 {
13364     if (type == NULL)
13365 	return (0);
13366     if (WXS_IS_COMPLEX(type))
13367 	return (0);
13368     if (type->type == XML_SCHEMA_TYPE_BASIC) {
13369 	if (type->builtInType == valType)
13370 	    return(1);
13371 	return (0);
13372     } else
13373 	return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13374 
13375     return (0);
13376 }
13377 
13378 static xmlSchemaTypePtr
13379 xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
13380 {
13381     if (type == NULL)
13382 	return (NULL);
13383     if (WXS_IS_COMPLEX(type))
13384 	return (NULL);
13385     if (type->type == XML_SCHEMA_TYPE_BASIC)
13386 	return(type);
13387     return(xmlSchemaQueryBuiltInType(type->subtypes));
13388 }
13389 #endif
13390 
13391 /**
13392  * xmlSchemaGetPrimitiveType:
13393  * @type:  the simpleType definition
13394  *
13395  * Returns the primitive type of the given type or
13396  * NULL in case of error.
13397  */
13398 static xmlSchemaTypePtr
xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)13399 xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
13400 {
13401 
13402     while (type != NULL) {
13403 	/*
13404 	* Note that anySimpleType is actually not a primitive type
13405 	* but we need that here.
13406 	*/
13407 	if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13408 	   (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
13409 	    return (type);
13410 	type = type->baseType;
13411     }
13412 
13413     return (NULL);
13414 }
13415 
13416 #if 0
13417 /**
13418  * xmlSchemaGetBuiltInTypeAncestor:
13419  * @type:  the simpleType definition
13420  *
13421  * Returns the primitive type of the given type or
13422  * NULL in case of error.
13423  */
13424 static xmlSchemaTypePtr
13425 xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
13426 {
13427     if (WXS_IS_LIST(type) || WXS_IS_UNION(type))
13428 	return (0);
13429     while (type != NULL) {
13430 	if (type->type == XML_SCHEMA_TYPE_BASIC)
13431 	    return (type);
13432 	type = type->baseType;
13433     }
13434 
13435     return (NULL);
13436 }
13437 #endif
13438 
13439 /**
13440  * xmlSchemaCloneWildcardNsConstraints:
13441  * @ctxt:  the schema parser context
13442  * @dest:  the destination wildcard
13443  * @source: the source wildcard
13444  *
13445  * Clones the namespace constraints of source
13446  * and assignes them to dest.
13447  * Returns -1 on internal error, 0 otherwise.
13448  */
13449 static int
xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,xmlSchemaWildcardPtr dest,xmlSchemaWildcardPtr source)13450 xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
13451 				    xmlSchemaWildcardPtr dest,
13452 				    xmlSchemaWildcardPtr source)
13453 {
13454     xmlSchemaWildcardNsPtr cur, tmp, last;
13455 
13456     if ((source == NULL) || (dest == NULL))
13457 	return(-1);
13458     dest->any = source->any;
13459     cur = source->nsSet;
13460     last = NULL;
13461     while (cur != NULL) {
13462 	tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13463 	if (tmp == NULL)
13464 	    return(-1);
13465 	tmp->value = cur->value;
13466 	if (last == NULL)
13467 	    dest->nsSet = tmp;
13468 	else
13469 	    last->next = tmp;
13470 	last = tmp;
13471 	cur = cur->next;
13472     }
13473     if (dest->negNsSet != NULL)
13474 	xmlSchemaFreeWildcardNsSet(dest->negNsSet);
13475     if (source->negNsSet != NULL) {
13476 	dest->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13477 	if (dest->negNsSet == NULL)
13478 	    return(-1);
13479 	dest->negNsSet->value = source->negNsSet->value;
13480     } else
13481 	dest->negNsSet = NULL;
13482     return(0);
13483 }
13484 
13485 /**
13486  * xmlSchemaUnionWildcards:
13487  * @ctxt:  the schema parser context
13488  * @completeWild:  the first wildcard
13489  * @curWild: the second wildcard
13490  *
13491  * Unions the namespace constraints of the given wildcards.
13492  * @completeWild will hold the resulting union.
13493  * Returns a positive error code on failure, -1 in case of an
13494  * internal error, 0 otherwise.
13495  */
13496 static int
xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,xmlSchemaWildcardPtr completeWild,xmlSchemaWildcardPtr curWild)13497 xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
13498 			    xmlSchemaWildcardPtr completeWild,
13499 			    xmlSchemaWildcardPtr curWild)
13500 {
13501     xmlSchemaWildcardNsPtr cur, curB, tmp;
13502 
13503     /*
13504     * 1 If O1 and O2 are the same value, then that value must be the
13505     * value.
13506     */
13507     if ((completeWild->any == curWild->any) &&
13508 	((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13509 	((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13510 
13511 	if ((completeWild->negNsSet == NULL) ||
13512 	    (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13513 
13514 	    if (completeWild->nsSet != NULL) {
13515 		int found = 0;
13516 
13517 		/*
13518 		* Check equality of sets.
13519 		*/
13520 		cur = completeWild->nsSet;
13521 		while (cur != NULL) {
13522 		    found = 0;
13523 		    curB = curWild->nsSet;
13524 		    while (curB != NULL) {
13525 			if (cur->value == curB->value) {
13526 			    found = 1;
13527 			    break;
13528 			}
13529 			curB = curB->next;
13530 		    }
13531 		    if (!found)
13532 			break;
13533 		    cur = cur->next;
13534 		}
13535 		if (found)
13536 		    return(0);
13537 	    } else
13538 		return(0);
13539 	}
13540     }
13541     /*
13542     * 2 If either O1 or O2 is any, then any must be the value
13543     */
13544     if (completeWild->any != curWild->any) {
13545 	if (completeWild->any == 0) {
13546 	    completeWild->any = 1;
13547 	    if (completeWild->nsSet != NULL) {
13548 		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13549 		completeWild->nsSet = NULL;
13550 	    }
13551 	    if (completeWild->negNsSet != NULL) {
13552 		xmlFree(completeWild->negNsSet);
13553 		completeWild->negNsSet = NULL;
13554 	    }
13555 	}
13556 	return (0);
13557     }
13558     /*
13559     * 3 If both O1 and O2 are sets of (namespace names or �absent�),
13560     * then the union of those sets must be the value.
13561     */
13562     if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13563 	int found;
13564 	xmlSchemaWildcardNsPtr start;
13565 
13566 	cur = curWild->nsSet;
13567 	start = completeWild->nsSet;
13568 	while (cur != NULL) {
13569 	    found = 0;
13570 	    curB = start;
13571 	    while (curB != NULL) {
13572 		if (cur->value == curB->value) {
13573 		    found = 1;
13574 		    break;
13575 		}
13576 		curB = curB->next;
13577 	    }
13578 	    if (!found) {
13579 		tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13580 		if (tmp == NULL)
13581 		    return (-1);
13582 		tmp->value = cur->value;
13583 		tmp->next = completeWild->nsSet;
13584 		completeWild->nsSet = tmp;
13585 	    }
13586 	    cur = cur->next;
13587 	}
13588 
13589 	return(0);
13590     }
13591     /*
13592     * 4 If the two are negations of different values (namespace names
13593     * or �absent�), then a pair of not and �absent� must be the value.
13594     */
13595     if ((completeWild->negNsSet != NULL) &&
13596 	(curWild->negNsSet != NULL) &&
13597 	(completeWild->negNsSet->value != curWild->negNsSet->value)) {
13598 	completeWild->negNsSet->value = NULL;
13599 
13600 	return(0);
13601     }
13602     /*
13603      * 5.
13604      */
13605     if (((completeWild->negNsSet != NULL) &&
13606 	(completeWild->negNsSet->value != NULL) &&
13607 	(curWild->nsSet != NULL)) ||
13608 	((curWild->negNsSet != NULL) &&
13609 	(curWild->negNsSet->value != NULL) &&
13610 	(completeWild->nsSet != NULL))) {
13611 
13612 	int nsFound, absentFound = 0;
13613 
13614 	if (completeWild->nsSet != NULL) {
13615 	    cur = completeWild->nsSet;
13616 	    curB = curWild->negNsSet;
13617 	} else {
13618 	    cur = curWild->nsSet;
13619 	    curB = completeWild->negNsSet;
13620 	}
13621 	nsFound = 0;
13622 	while (cur != NULL) {
13623 	    if (cur->value == NULL)
13624 		absentFound = 1;
13625 	    else if (cur->value == curB->value)
13626 		nsFound = 1;
13627 	    if (nsFound && absentFound)
13628 		break;
13629 	    cur = cur->next;
13630 	}
13631 
13632 	if (nsFound && absentFound) {
13633 	    /*
13634 	    * 5.1 If the set S includes both the negated namespace
13635 	    * name and �absent�, then any must be the value.
13636 	    */
13637 	    completeWild->any = 1;
13638 	    if (completeWild->nsSet != NULL) {
13639 		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13640 		completeWild->nsSet = NULL;
13641 	    }
13642 	    if (completeWild->negNsSet != NULL) {
13643 		xmlFree(completeWild->negNsSet);
13644 		completeWild->negNsSet = NULL;
13645 	    }
13646 	} else if (nsFound && (!absentFound)) {
13647 	    /*
13648 	    * 5.2 If the set S includes the negated namespace name
13649 	    * but not �absent�, then a pair of not and �absent� must
13650 	    * be the value.
13651 	    */
13652 	    if (completeWild->nsSet != NULL) {
13653 		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13654 		completeWild->nsSet = NULL;
13655 	    }
13656 	    if (completeWild->negNsSet == NULL) {
13657 		completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13658 		if (completeWild->negNsSet == NULL)
13659 		    return (-1);
13660 	    }
13661 	    completeWild->negNsSet->value = NULL;
13662 	} else if ((!nsFound) && absentFound) {
13663 	    /*
13664 	    * 5.3 If the set S includes �absent� but not the negated
13665 	    * namespace name, then the union is not expressible.
13666 	    */
13667 	    xmlSchemaPErr(ctxt, completeWild->node,
13668 		XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
13669 		"The union of the wilcard is not expressible.\n",
13670 		NULL, NULL);
13671 	    return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
13672 	} else if ((!nsFound) && (!absentFound)) {
13673 	    /*
13674 	    * 5.4 If the set S does not include either the negated namespace
13675 	    * name or �absent�, then whichever of O1 or O2 is a pair of not
13676 	    * and a namespace name must be the value.
13677 	    */
13678 	    if (completeWild->negNsSet == NULL) {
13679 		if (completeWild->nsSet != NULL) {
13680 		    xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13681 		    completeWild->nsSet = NULL;
13682 		}
13683 		completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13684 		if (completeWild->negNsSet == NULL)
13685 		    return (-1);
13686 		completeWild->negNsSet->value = curWild->negNsSet->value;
13687 	    }
13688 	}
13689 	return (0);
13690     }
13691     /*
13692      * 6.
13693      */
13694     if (((completeWild->negNsSet != NULL) &&
13695 	(completeWild->negNsSet->value == NULL) &&
13696 	(curWild->nsSet != NULL)) ||
13697 	((curWild->negNsSet != NULL) &&
13698 	(curWild->negNsSet->value == NULL) &&
13699 	(completeWild->nsSet != NULL))) {
13700 
13701 	if (completeWild->nsSet != NULL) {
13702 	    cur = completeWild->nsSet;
13703 	} else {
13704 	    cur = curWild->nsSet;
13705 	}
13706 	while (cur != NULL) {
13707 	    if (cur->value == NULL) {
13708 		/*
13709 		* 6.1 If the set S includes �absent�, then any must be the
13710 		* value.
13711 		*/
13712 		completeWild->any = 1;
13713 		if (completeWild->nsSet != NULL) {
13714 		    xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13715 		    completeWild->nsSet = NULL;
13716 		}
13717 		if (completeWild->negNsSet != NULL) {
13718 		    xmlFree(completeWild->negNsSet);
13719 		    completeWild->negNsSet = NULL;
13720 		}
13721 		return (0);
13722 	    }
13723 	    cur = cur->next;
13724 	}
13725 	if (completeWild->negNsSet == NULL) {
13726 	    /*
13727 	    * 6.2 If the set S does not include �absent�, then a pair of not
13728 	    * and �absent� must be the value.
13729 	    */
13730 	    if (completeWild->nsSet != NULL) {
13731 		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13732 		completeWild->nsSet = NULL;
13733 	    }
13734 	    completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13735 	    if (completeWild->negNsSet == NULL)
13736 		return (-1);
13737 	    completeWild->negNsSet->value = NULL;
13738 	}
13739 	return (0);
13740     }
13741     return (0);
13742 
13743 }
13744 
13745 /**
13746  * xmlSchemaIntersectWildcards:
13747  * @ctxt:  the schema parser context
13748  * @completeWild:  the first wildcard
13749  * @curWild: the second wildcard
13750  *
13751  * Intersects the namespace constraints of the given wildcards.
13752  * @completeWild will hold the resulting intersection.
13753  * Returns a positive error code on failure, -1 in case of an
13754  * internal error, 0 otherwise.
13755  */
13756 static int
xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,xmlSchemaWildcardPtr completeWild,xmlSchemaWildcardPtr curWild)13757 xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
13758 			    xmlSchemaWildcardPtr completeWild,
13759 			    xmlSchemaWildcardPtr curWild)
13760 {
13761     xmlSchemaWildcardNsPtr cur, curB, prev,  tmp;
13762 
13763     /*
13764     * 1 If O1 and O2 are the same value, then that value must be the
13765     * value.
13766     */
13767     if ((completeWild->any == curWild->any) &&
13768 	((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13769 	((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13770 
13771 	if ((completeWild->negNsSet == NULL) ||
13772 	    (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13773 
13774 	    if (completeWild->nsSet != NULL) {
13775 		int found = 0;
13776 
13777 		/*
13778 		* Check equality of sets.
13779 		*/
13780 		cur = completeWild->nsSet;
13781 		while (cur != NULL) {
13782 		    found = 0;
13783 		    curB = curWild->nsSet;
13784 		    while (curB != NULL) {
13785 			if (cur->value == curB->value) {
13786 			    found = 1;
13787 			    break;
13788 			}
13789 			curB = curB->next;
13790 		    }
13791 		    if (!found)
13792 			break;
13793 		    cur = cur->next;
13794 		}
13795 		if (found)
13796 		    return(0);
13797 	    } else
13798 		return(0);
13799 	}
13800     }
13801     /*
13802     * 2 If either O1 or O2 is any, then the other must be the value.
13803     */
13804     if ((completeWild->any != curWild->any) && (completeWild->any)) {
13805 	if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13806 	    return(-1);
13807 	return(0);
13808     }
13809     /*
13810     * 3 If either O1 or O2 is a pair of not and a value (a namespace
13811     * name or �absent�) and the other is a set of (namespace names or
13812     * �absent�), then that set, minus the negated value if it was in
13813     * the set, minus �absent� if it was in the set, must be the value.
13814     */
13815     if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
13816 	((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
13817 	const xmlChar *neg;
13818 
13819 	if (completeWild->nsSet == NULL) {
13820 	    neg = completeWild->negNsSet->value;
13821 	    if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13822 		return(-1);
13823 	} else
13824 	    neg = curWild->negNsSet->value;
13825 	/*
13826 	* Remove absent and negated.
13827 	*/
13828 	prev = NULL;
13829 	cur = completeWild->nsSet;
13830 	while (cur != NULL) {
13831 	    if (cur->value == NULL) {
13832 		if (prev == NULL)
13833 		    completeWild->nsSet = cur->next;
13834 		else
13835 		    prev->next = cur->next;
13836 		xmlFree(cur);
13837 		break;
13838 	    }
13839 	    prev = cur;
13840 	    cur = cur->next;
13841 	}
13842 	if (neg != NULL) {
13843 	    prev = NULL;
13844 	    cur = completeWild->nsSet;
13845 	    while (cur != NULL) {
13846 		if (cur->value == neg) {
13847 		    if (prev == NULL)
13848 			completeWild->nsSet = cur->next;
13849 		    else
13850 			prev->next = cur->next;
13851 		    xmlFree(cur);
13852 		    break;
13853 		}
13854 		prev = cur;
13855 		cur = cur->next;
13856 	    }
13857 	}
13858 
13859 	return(0);
13860     }
13861     /*
13862     * 4 If both O1 and O2 are sets of (namespace names or �absent�),
13863     * then the intersection of those sets must be the value.
13864     */
13865     if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13866 	int found;
13867 
13868 	cur = completeWild->nsSet;
13869 	prev = NULL;
13870 	while (cur != NULL) {
13871 	    found = 0;
13872 	    curB = curWild->nsSet;
13873 	    while (curB != NULL) {
13874 		if (cur->value == curB->value) {
13875 		    found = 1;
13876 		    break;
13877 		}
13878 		curB = curB->next;
13879 	    }
13880 	    if (!found) {
13881 		if (prev == NULL)
13882 		    completeWild->nsSet = cur->next;
13883 		else
13884 		    prev->next = cur->next;
13885 		tmp = cur->next;
13886 		xmlFree(cur);
13887 		cur = tmp;
13888 		continue;
13889 	    }
13890 	    prev = cur;
13891 	    cur = cur->next;
13892 	}
13893 
13894 	return(0);
13895     }
13896     /* 5 If the two are negations of different namespace names,
13897     * then the intersection is not expressible
13898     */
13899     if ((completeWild->negNsSet != NULL) &&
13900 	(curWild->negNsSet != NULL) &&
13901 	(completeWild->negNsSet->value != curWild->negNsSet->value) &&
13902 	(completeWild->negNsSet->value != NULL) &&
13903 	(curWild->negNsSet->value != NULL)) {
13904 
13905 	xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
13906 	    "The intersection of the wilcard is not expressible.\n",
13907 	    NULL, NULL);
13908 	return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
13909     }
13910     /*
13911     * 6 If the one is a negation of a namespace name and the other
13912     * is a negation of �absent�, then the one which is the negation
13913     * of a namespace name must be the value.
13914     */
13915     if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
13916 	(completeWild->negNsSet->value != curWild->negNsSet->value) &&
13917 	(completeWild->negNsSet->value == NULL)) {
13918 	completeWild->negNsSet->value =  curWild->negNsSet->value;
13919     }
13920     return(0);
13921 }
13922 
13923 /**
13924  * xmlSchemaIsWildcardNsConstraintSubset:
13925  * @ctxt:  the schema parser context
13926  * @sub:  the first wildcard
13927  * @super: the second wildcard
13928  *
13929  * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
13930  *
13931  * Returns 0 if the namespace constraint of @sub is an intensional
13932  * subset of @super, 1 otherwise.
13933  */
13934 static int
xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,xmlSchemaWildcardPtr super)13935 xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
13936 			  xmlSchemaWildcardPtr super)
13937 {
13938     /*
13939     * 1 super must be any.
13940     */
13941     if (super->any)
13942 	return (0);
13943     /*
13944     * 2.1 sub must be a pair of not and a namespace name or �absent�.
13945     * 2.2 super must be a pair of not and the same value.
13946     */
13947     if ((sub->negNsSet != NULL) &&
13948 	(super->negNsSet != NULL) &&
13949 	(sub->negNsSet->value == sub->negNsSet->value))
13950 	return (0);
13951     /*
13952     * 3.1 sub must be a set whose members are either namespace names or �absent�.
13953     */
13954     if (sub->nsSet != NULL) {
13955 	/*
13956 	* 3.2.1 super must be the same set or a superset thereof.
13957 	*/
13958 	if (super->nsSet != NULL) {
13959 	    xmlSchemaWildcardNsPtr cur, curB;
13960 	    int found = 0;
13961 
13962 	    cur = sub->nsSet;
13963 	    while (cur != NULL) {
13964 		found = 0;
13965 		curB = super->nsSet;
13966 		while (curB != NULL) {
13967 		    if (cur->value == curB->value) {
13968 			found = 1;
13969 			break;
13970 		    }
13971 		    curB = curB->next;
13972 		}
13973 		if (!found)
13974 		    return (1);
13975 		cur = cur->next;
13976 	    }
13977 	    if (found)
13978 		return (0);
13979 	} else if (super->negNsSet != NULL) {
13980 	    xmlSchemaWildcardNsPtr cur;
13981 	    /*
13982 	    * 3.2.2 super must be a pair of not and a namespace name or
13983 	    * �absent� and that value must not be in sub's set.
13984 	    */
13985 	    cur = sub->nsSet;
13986 	    while (cur != NULL) {
13987 		if (cur->value == super->negNsSet->value)
13988 		    return (1);
13989 		cur = cur->next;
13990 	    }
13991 	    return (0);
13992 	}
13993     }
13994     return (1);
13995 }
13996 
13997 static int
xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse,int * fixed,const xmlChar ** value,xmlSchemaValPtr * val)13998 xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse,
13999 				     int *fixed,
14000 				     const xmlChar **value,
14001 				     xmlSchemaValPtr *val)
14002 {
14003     *fixed = 0;
14004     *value = NULL;
14005     if (val != 0)
14006 	*val = NULL;
14007 
14008     if (attruse->defValue != NULL) {
14009 	*value = attruse->defValue;
14010 	if (val != NULL)
14011 	    *val = attruse->defVal;
14012 	if (attruse->flags & XML_SCHEMA_ATTR_USE_FIXED)
14013 	    *fixed = 1;
14014 	return(1);
14015     } else if ((attruse->attrDecl != NULL) &&
14016 	(attruse->attrDecl->defValue != NULL)) {
14017 	*value = attruse->attrDecl->defValue;
14018 	if (val != NULL)
14019 	    *val = attruse->attrDecl->defVal;
14020 	if (attruse->attrDecl->flags & XML_SCHEMAS_ATTR_FIXED)
14021 	    *fixed = 1;
14022 	return(1);
14023     }
14024     return(0);
14025 }
14026 /**
14027  * xmlSchemaCheckCVCWildcardNamespace:
14028  * @wild:  the wildcard
14029  * @ns:  the namespace
14030  *
14031  * Validation Rule: Wildcard allows Namespace Name
14032  * (cvc-wildcard-namespace)
14033  *
14034  * Returns 0 if the given namespace matches the wildcard,
14035  * 1 otherwise and -1 on API errors.
14036  */
14037 static int
xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,const xmlChar * ns)14038 xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
14039 				   const xmlChar* ns)
14040 {
14041     if (wild == NULL)
14042 	return(-1);
14043 
14044     if (wild->any)
14045 	return(0);
14046     else if (wild->nsSet != NULL) {
14047 	xmlSchemaWildcardNsPtr cur;
14048 
14049 	cur = wild->nsSet;
14050 	while (cur != NULL) {
14051 	    if (xmlStrEqual(cur->value, ns))
14052 		return(0);
14053 	    cur = cur->next;
14054 	}
14055     } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
14056 	(!xmlStrEqual(wild->negNsSet->value, ns)))
14057 	return(0);
14058 
14059     return(1);
14060 }
14061 
14062 #define XML_SCHEMA_ACTION_DERIVE 0
14063 #define XML_SCHEMA_ACTION_REDEFINE 1
14064 
14065 #define WXS_ACTION_STR(a) \
14066 ((a) == XML_SCHEMA_ACTION_DERIVE) ? (const xmlChar *) "base" : (const xmlChar *) "redefined"
14067 
14068 /*
14069 * Schema Component Constraint:
14070 *   Derivation Valid (Restriction, Complex)
14071 *   derivation-ok-restriction (2) - (4)
14072 *
14073 * ATTENTION:
14074 * In XML Schema 1.1 this will be:
14075 * Validation Rule:
14076 *     Checking complex type subsumption (practicalSubsumption) (1, 2 and 3)
14077 *
14078 */
14079 static int
xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt,int action,xmlSchemaBasicItemPtr item,xmlSchemaBasicItemPtr baseItem,xmlSchemaItemListPtr uses,xmlSchemaItemListPtr baseUses,xmlSchemaWildcardPtr wild,xmlSchemaWildcardPtr baseWild)14080 xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt,
14081 				       int action,
14082 				       xmlSchemaBasicItemPtr item,
14083 				       xmlSchemaBasicItemPtr baseItem,
14084 				       xmlSchemaItemListPtr uses,
14085 				       xmlSchemaItemListPtr baseUses,
14086 				       xmlSchemaWildcardPtr wild,
14087 				       xmlSchemaWildcardPtr baseWild)
14088 {
14089     xmlSchemaAttributeUsePtr cur = NULL, bcur;
14090     int i, j, found; /* err = 0; */
14091     const xmlChar *bEffValue;
14092     int effFixed;
14093 
14094     if (uses != NULL) {
14095 	for (i = 0; i < uses->nbItems; i++) {
14096 	    cur = uses->items[i];
14097 	    found = 0;
14098 	    if (baseUses == NULL)
14099 		goto not_found;
14100 	    for (j = 0; j < baseUses->nbItems; j++) {
14101 		bcur = baseUses->items[j];
14102 		if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14103 			WXS_ATTRUSE_DECL_NAME(bcur)) &&
14104 		    (WXS_ATTRUSE_DECL_TNS(cur) ==
14105 			WXS_ATTRUSE_DECL_TNS(bcur)))
14106 		{
14107 		    /*
14108 		    * (2.1) "If there is an attribute use in the {attribute
14109 		    * uses} of the {base type definition} (call this B) whose
14110 		    * {attribute declaration} has the same {name} and {target
14111 		    * namespace}, then  all of the following must be true:"
14112 		    */
14113 		    found = 1;
14114 
14115 		    if ((cur->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
14116 			(bcur->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED))
14117 		    {
14118 			xmlChar *str = NULL;
14119 			/*
14120 			* (2.1.1) "one of the following must be true:"
14121 			* (2.1.1.1) "B's {required} is false."
14122 			* (2.1.1.2) "R's {required} is true."
14123 			*/
14124 			xmlSchemaPAttrUseErr4(pctxt,
14125 			    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
14126 			    WXS_ITEM_NODE(item), item, cur,
14127 			    "The 'optional' attribute use is inconsistent "
14128 			    "with the corresponding 'required' attribute use of "
14129 			    "the %s %s",
14130 			    WXS_ACTION_STR(action),
14131 			    xmlSchemaGetComponentDesignation(&str, baseItem),
14132 			    NULL, NULL);
14133 			FREE_AND_NULL(str);
14134 			/* err = pctxt->err; */
14135 		    } else if (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
14136 			WXS_ATTRUSE_TYPEDEF(cur),
14137 			WXS_ATTRUSE_TYPEDEF(bcur), 0) != 0)
14138 		    {
14139 			xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
14140 
14141 			/*
14142 			* SPEC (2.1.2) "R's {attribute declaration}'s
14143 			* {type definition} must be validly derived from
14144 			* B's {type definition} given the empty set as
14145 			* defined in Type Derivation OK (Simple) (�3.14.6)."
14146 			*/
14147 			xmlSchemaPAttrUseErr4(pctxt,
14148 			    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
14149 			    WXS_ITEM_NODE(item), item, cur,
14150 			    "The attribute declaration's %s "
14151 			    "is not validly derived from "
14152 			    "the corresponding %s of the "
14153 			    "attribute declaration in the %s %s",
14154 			    xmlSchemaGetComponentDesignation(&strA,
14155 				WXS_ATTRUSE_TYPEDEF(cur)),
14156 			    xmlSchemaGetComponentDesignation(&strB,
14157 				WXS_ATTRUSE_TYPEDEF(bcur)),
14158 			    WXS_ACTION_STR(action),
14159 			    xmlSchemaGetComponentDesignation(&strC, baseItem));
14160 			    /* xmlSchemaGetComponentDesignation(&str, baseItem), */
14161 			FREE_AND_NULL(strA);
14162 			FREE_AND_NULL(strB);
14163 			FREE_AND_NULL(strC);
14164 			/* err = pctxt->err; */
14165 		    } else {
14166 			/*
14167 			* 2.1.3 [Definition:]  Let the effective value
14168 			* constraint of an attribute use be its {value
14169 			* constraint}, if present, otherwise its {attribute
14170 			* declaration}'s {value constraint} .
14171 			*/
14172 			xmlSchemaGetEffectiveValueConstraint(bcur,
14173 			    &effFixed, &bEffValue, NULL);
14174 			/*
14175 			* 2.1.3 ... one of the following must be true
14176 			*
14177 			* 2.1.3.1 B's �effective value constraint� is
14178 			* �absent� or default.
14179 			*/
14180 			if ((bEffValue != NULL) &&
14181 			    (effFixed == 1)) {
14182 			    const xmlChar *rEffValue = NULL;
14183 
14184 			    xmlSchemaGetEffectiveValueConstraint(bcur,
14185 				&effFixed, &rEffValue, NULL);
14186 			    /*
14187 			    * 2.1.3.2 R's �effective value constraint� is
14188 			    * fixed with the same string as B's.
14189 			    * MAYBE TODO: Compare the computed values.
14190 			    *       Hmm, it says "same string" so
14191 			    *       string-equality might really be sufficient.
14192 			    */
14193 			    if ((effFixed == 0) ||
14194 				(! WXS_ARE_DEFAULT_STR_EQUAL(rEffValue, bEffValue)))
14195 			    {
14196 				xmlChar *str = NULL;
14197 
14198 				xmlSchemaPAttrUseErr4(pctxt,
14199 				    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
14200 				    WXS_ITEM_NODE(item), item, cur,
14201 				    "The effective value constraint of the "
14202 				    "attribute use is inconsistent with "
14203 				    "its correspondent in the %s %s",
14204 				    WXS_ACTION_STR(action),
14205 				    xmlSchemaGetComponentDesignation(&str,
14206 					baseItem),
14207 				    NULL, NULL);
14208 				FREE_AND_NULL(str);
14209 				/* err = pctxt->err; */
14210 			    }
14211 			}
14212 		    }
14213 		    break;
14214 		}
14215 	    }
14216 not_found:
14217 	    if (!found) {
14218 		/*
14219 		* (2.2) "otherwise the {base type definition} must have an
14220 		* {attribute wildcard} and the {target namespace} of the
14221 		* R's {attribute declaration} must be �valid� with respect
14222 		* to that wildcard, as defined in Wildcard allows Namespace
14223 		* Name (�3.10.4)."
14224 		*/
14225 		if ((baseWild == NULL) ||
14226 		    (xmlSchemaCheckCVCWildcardNamespace(baseWild,
14227 		    (WXS_ATTRUSE_DECL(cur))->targetNamespace) != 0))
14228 		{
14229 		    xmlChar *str = NULL;
14230 
14231 		    xmlSchemaPAttrUseErr4(pctxt,
14232 			XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
14233 			WXS_ITEM_NODE(item), item, cur,
14234 			"Neither a matching attribute use, "
14235 			"nor a matching wildcard exists in the %s %s",
14236 			WXS_ACTION_STR(action),
14237 			xmlSchemaGetComponentDesignation(&str, baseItem),
14238 			NULL, NULL);
14239 		    FREE_AND_NULL(str);
14240 		    /* err = pctxt->err; */
14241 		}
14242 	    }
14243 	}
14244     }
14245     /*
14246     * SPEC derivation-ok-restriction (3):
14247     * (3) "For each attribute use in the {attribute uses} of the {base type
14248     * definition} whose {required} is true, there must be an attribute
14249     * use with an {attribute declaration} with the same {name} and
14250     * {target namespace} as its {attribute declaration} in the {attribute
14251     * uses} of the complex type definition itself whose {required} is true.
14252     */
14253     if (baseUses != NULL) {
14254 	for (j = 0; j < baseUses->nbItems; j++) {
14255 	    bcur = baseUses->items[j];
14256 	    if (bcur->occurs != XML_SCHEMAS_ATTR_USE_REQUIRED)
14257 		continue;
14258 	    found = 0;
14259 	    if (uses != NULL) {
14260 		for (i = 0; i < uses->nbItems; i++) {
14261 		    cur = uses->items[i];
14262 		    if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14263 			WXS_ATTRUSE_DECL_NAME(bcur)) &&
14264 			(WXS_ATTRUSE_DECL_TNS(cur) ==
14265 			WXS_ATTRUSE_DECL_TNS(bcur))) {
14266 			found = 1;
14267 			break;
14268 		    }
14269 		}
14270 	    }
14271 	    if (!found) {
14272 		xmlChar *strA = NULL, *strB = NULL;
14273 
14274 		xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14275 		    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
14276 		    NULL, item,
14277 		    "A matching attribute use for the "
14278 		    "'required' %s of the %s %s is missing",
14279 		    xmlSchemaGetComponentDesignation(&strA, bcur),
14280 		    WXS_ACTION_STR(action),
14281 		    xmlSchemaGetComponentDesignation(&strB, baseItem),
14282 		    NULL);
14283 		FREE_AND_NULL(strA);
14284 		FREE_AND_NULL(strB);
14285 	    }
14286 	}
14287     }
14288     /*
14289     * derivation-ok-restriction (4)
14290     */
14291     if (wild != NULL) {
14292 	/*
14293 	* (4) "If there is an {attribute wildcard}, all of the
14294 	* following must be true:"
14295 	*/
14296 	if (baseWild == NULL) {
14297 	    xmlChar *str = NULL;
14298 
14299 	    /*
14300 	    * (4.1) "The {base type definition} must also have one."
14301 	    */
14302 	    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14303 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
14304 		NULL, item,
14305 		"The %s has an attribute wildcard, "
14306 		"but the %s %s '%s' does not have one",
14307 		WXS_ITEM_TYPE_NAME(item),
14308 		WXS_ACTION_STR(action),
14309 		WXS_ITEM_TYPE_NAME(baseItem),
14310 		xmlSchemaGetComponentQName(&str, baseItem));
14311 	    FREE_AND_NULL(str);
14312 	    return(pctxt->err);
14313 	} else if ((baseWild->any == 0) &&
14314 		xmlSchemaCheckCOSNSSubset(wild, baseWild))
14315 	{
14316 	    xmlChar *str = NULL;
14317 	    /*
14318 	    * (4.2) "The complex type definition's {attribute wildcard}'s
14319 	    * {namespace constraint} must be a subset of the {base type
14320 	    * definition}'s {attribute wildcard}'s {namespace constraint},
14321 	    * as defined by Wildcard Subset (�3.10.6)."
14322 	    */
14323 	    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14324 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
14325 		NULL, item,
14326 		"The attribute wildcard is not a valid "
14327 		"subset of the wildcard in the %s %s '%s'",
14328 		WXS_ACTION_STR(action),
14329 		WXS_ITEM_TYPE_NAME(baseItem),
14330 		xmlSchemaGetComponentQName(&str, baseItem),
14331 		NULL);
14332 	    FREE_AND_NULL(str);
14333 	    return(pctxt->err);
14334 	}
14335 	/* 4.3 Unless the {base type definition} is the �ur-type
14336 	* definition�, the complex type definition's {attribute
14337 	* wildcard}'s {process contents} must be identical to or
14338 	* stronger than the {base type definition}'s {attribute
14339 	* wildcard}'s {process contents}, where strict is stronger
14340 	* than lax is stronger than skip.
14341 	*/
14342 	if ((! WXS_IS_ANYTYPE(baseItem)) &&
14343 	    (wild->processContents < baseWild->processContents)) {
14344 	    xmlChar *str = NULL;
14345 	    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14346 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
14347 		NULL, baseItem,
14348 		"The {process contents} of the attribute wildcard is "
14349 		"weaker than the one in the %s %s '%s'",
14350 		WXS_ACTION_STR(action),
14351 		WXS_ITEM_TYPE_NAME(baseItem),
14352 		xmlSchemaGetComponentQName(&str, baseItem),
14353 		NULL);
14354 	    FREE_AND_NULL(str)
14355 		return(pctxt->err);
14356 	}
14357     }
14358     return(0);
14359 }
14360 
14361 
14362 static int
14363 xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
14364 				  xmlSchemaBasicItemPtr item,
14365 				  xmlSchemaWildcardPtr *completeWild,
14366 				  xmlSchemaItemListPtr list,
14367 				  xmlSchemaItemListPtr prohibs);
14368 /**
14369  * xmlSchemaFixupTypeAttributeUses:
14370  * @ctxt:  the schema parser context
14371  * @type:  the complex type definition
14372  *
14373  *
14374  * Builds the wildcard and the attribute uses on the given complex type.
14375  * Returns -1 if an internal error occurs, 0 otherwise.
14376  *
14377  * ATTENTION TODO: Experimantally this uses pointer comparisons for
14378  * strings, so recheck this if we start to hardcode some schemata, since
14379  * they might not be in the same dict.
14380  * NOTE: It is allowed to "extend" the xs:anyType type.
14381  */
14382 static int
xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)14383 xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt,
14384 				  xmlSchemaTypePtr type)
14385 {
14386     xmlSchemaTypePtr baseType = NULL;
14387     xmlSchemaAttributeUsePtr use;
14388     xmlSchemaItemListPtr uses, baseUses, prohibs = NULL;
14389 
14390     if (type->baseType == NULL) {
14391 	PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14392 	    "no base type");
14393         return (-1);
14394     }
14395     baseType = type->baseType;
14396     if (WXS_IS_TYPE_NOT_FIXED(baseType))
14397 	if (xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt) == -1)
14398 	    return(-1);
14399 
14400     uses = type->attrUses;
14401     baseUses = baseType->attrUses;
14402     /*
14403     * Expand attribute group references. And build the 'complete'
14404     * wildcard, i.e. intersect multiple wildcards.
14405     * Move attribute prohibitions into a separate list.
14406     */
14407     if (uses != NULL) {
14408 	if (WXS_IS_RESTRICTION(type)) {
14409 	    /*
14410 	    * This one will transfer all attr. prohibitions
14411 	    * into pctxt->attrProhibs.
14412 	    */
14413 	    if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14414 		WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14415 		pctxt->attrProhibs) == -1)
14416 	    {
14417 		PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14418 		"failed to expand attributes");
14419 	    }
14420 	    if (pctxt->attrProhibs->nbItems != 0)
14421 		prohibs = pctxt->attrProhibs;
14422 	} else {
14423 	    if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14424 		WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14425 		NULL) == -1)
14426 	    {
14427 		PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14428 		"failed to expand attributes");
14429 	    }
14430 	}
14431     }
14432     /*
14433     * Inherit the attribute uses of the base type.
14434     */
14435     if (baseUses != NULL) {
14436 	int i, j;
14437 	xmlSchemaAttributeUseProhibPtr pro;
14438 
14439 	if (WXS_IS_RESTRICTION(type)) {
14440 	    int usesCount;
14441 	    xmlSchemaAttributeUsePtr tmp;
14442 
14443 	    if (uses != NULL)
14444 		usesCount = uses->nbItems;
14445 	    else
14446 		usesCount = 0;
14447 
14448 	    /* Restriction. */
14449 	    for (i = 0; i < baseUses->nbItems; i++) {
14450 		use = baseUses->items[i];
14451 		if (prohibs) {
14452 		    /*
14453 		    * Filter out prohibited uses.
14454 		    */
14455 		    for (j = 0; j < prohibs->nbItems; j++) {
14456 			pro = prohibs->items[j];
14457 			if ((WXS_ATTRUSE_DECL_NAME(use) == pro->name) &&
14458 			    (WXS_ATTRUSE_DECL_TNS(use) ==
14459 				pro->targetNamespace))
14460 			{
14461 			    goto inherit_next;
14462 			}
14463 		    }
14464 		}
14465 		if (usesCount) {
14466 		    /*
14467 		    * Filter out existing uses.
14468 		    */
14469 		    for (j = 0; j < usesCount; j++) {
14470 			tmp = uses->items[j];
14471 			if ((WXS_ATTRUSE_DECL_NAME(use) ==
14472 				WXS_ATTRUSE_DECL_NAME(tmp)) &&
14473 			    (WXS_ATTRUSE_DECL_TNS(use) ==
14474 				WXS_ATTRUSE_DECL_TNS(tmp)))
14475 			{
14476 			    goto inherit_next;
14477 			}
14478 		    }
14479 		}
14480 		if (uses == NULL) {
14481 		    type->attrUses = xmlSchemaItemListCreate();
14482 		    if (type->attrUses == NULL)
14483 			goto exit_failure;
14484 		    uses = type->attrUses;
14485 		}
14486 		xmlSchemaItemListAddSize(uses, 2, use);
14487 inherit_next: {}
14488 	    }
14489 	} else {
14490 	    /* Extension. */
14491 	    for (i = 0; i < baseUses->nbItems; i++) {
14492 		use = baseUses->items[i];
14493 		if (uses == NULL) {
14494 		    type->attrUses = xmlSchemaItemListCreate();
14495 		    if (type->attrUses == NULL)
14496 			goto exit_failure;
14497 		    uses = type->attrUses;
14498 		}
14499 		xmlSchemaItemListAddSize(uses, baseUses->nbItems, use);
14500 	    }
14501 	}
14502     }
14503     /*
14504     * Shrink attr. uses.
14505     */
14506     if (uses) {
14507 	if (uses->nbItems == 0) {
14508 	    xmlSchemaItemListFree(uses);
14509 	    type->attrUses = NULL;
14510 	}
14511 	/*
14512 	* TODO: We could shrink the size of the array
14513 	* to fit the actual number of items.
14514 	*/
14515     }
14516     /*
14517     * Compute the complete wildcard.
14518     */
14519     if (WXS_IS_EXTENSION(type)) {
14520 	if (baseType->attributeWildcard != NULL) {
14521 	    /*
14522 	    * (3.2.2.1) "If the �base wildcard� is non-�absent�, then
14523 	    * the appropriate case among the following:"
14524 	    */
14525 	    if (type->attributeWildcard != NULL) {
14526 		/*
14527 		* Union the complete wildcard with the base wildcard.
14528 		* SPEC {attribute wildcard}
14529 		* (3.2.2.1.2) "otherwise a wildcard whose {process contents}
14530 		* and {annotation} are those of the �complete wildcard�,
14531 		* and whose {namespace constraint} is the intensional union
14532 		* of the {namespace constraint} of the �complete wildcard�
14533 		* and of the �base wildcard�, as defined in Attribute
14534 		* Wildcard Union (�3.10.6)."
14535 		*/
14536 		if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
14537 		    baseType->attributeWildcard) == -1)
14538 		    goto exit_failure;
14539 	    } else {
14540 		/*
14541 		* (3.2.2.1.1) "If the �complete wildcard� is �absent�,
14542 		* then the �base wildcard�."
14543 		*/
14544 		type->attributeWildcard = baseType->attributeWildcard;
14545 	    }
14546 	} else {
14547 	    /*
14548 	    * (3.2.2.2) "otherwise (the �base wildcard� is �absent�) the
14549 	    * �complete wildcard"
14550 	    * NOOP
14551 	    */
14552 	}
14553     } else {
14554 	/*
14555 	* SPEC {attribute wildcard}
14556 	* (3.1) "If the <restriction> alternative is chosen, then the
14557 	* �complete wildcard�;"
14558 	* NOOP
14559 	*/
14560     }
14561 
14562     return (0);
14563 
14564 exit_failure:
14565     return(-1);
14566 }
14567 
14568 /**
14569  * xmlSchemaTypeFinalContains:
14570  * @schema:  the schema
14571  * @type:  the type definition
14572  * @final: the final
14573  *
14574  * Evaluates if a type definition contains the given "final".
14575  * This does take "finalDefault" into account as well.
14576  *
14577  * Returns 1 if the type does containt the given "final",
14578  * 0 otherwise.
14579  */
14580 static int
xmlSchemaTypeFinalContains(xmlSchemaTypePtr type,int final)14581 xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
14582 {
14583     if (type == NULL)
14584 	return (0);
14585     if (type->flags & final)
14586 	return (1);
14587     else
14588 	return (0);
14589 }
14590 
14591 /**
14592  * xmlSchemaGetUnionSimpleTypeMemberTypes:
14593  * @type:  the Union Simple Type
14594  *
14595  * Returns a list of member types of @type if existing,
14596  * returns NULL otherwise.
14597  */
14598 static xmlSchemaTypeLinkPtr
xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)14599 xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
14600 {
14601     while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
14602 	if (type->memberTypes != NULL)
14603 	    return (type->memberTypes);
14604 	else
14605 	    type = type->baseType;
14606     }
14607     return (NULL);
14608 }
14609 
14610 /**
14611  * xmlSchemaGetParticleTotalRangeMin:
14612  * @particle: the particle
14613  *
14614  * Schema Component Constraint: Effective Total Range
14615  * (all and sequence) + (choice)
14616  *
14617  * Returns the minimun Effective Total Range.
14618  */
14619 static int
xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)14620 xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
14621 {
14622     if ((particle->children == NULL) ||
14623 	(particle->minOccurs == 0))
14624 	return (0);
14625     if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14626 	int min = -1, cur;
14627 	xmlSchemaParticlePtr part =
14628 	    (xmlSchemaParticlePtr) particle->children->children;
14629 
14630 	if (part == NULL)
14631 	    return (0);
14632 	while (part != NULL) {
14633 	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14634 		(part->children->type == XML_SCHEMA_TYPE_ANY))
14635 		cur = part->minOccurs;
14636 	    else
14637 		cur = xmlSchemaGetParticleTotalRangeMin(part);
14638 	    if (cur == 0)
14639 		return (0);
14640 	    if ((min > cur) || (min == -1))
14641 		min = cur;
14642 	    part = (xmlSchemaParticlePtr) part->next;
14643 	}
14644 	return (particle->minOccurs * min);
14645     } else {
14646 	/* <all> and <sequence> */
14647 	int sum = 0;
14648 	xmlSchemaParticlePtr part =
14649 	    (xmlSchemaParticlePtr) particle->children->children;
14650 
14651 	if (part == NULL)
14652 	    return (0);
14653 	do {
14654 	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14655 		(part->children->type == XML_SCHEMA_TYPE_ANY))
14656 		sum += part->minOccurs;
14657 	    else
14658 		sum += xmlSchemaGetParticleTotalRangeMin(part);
14659 	    part = (xmlSchemaParticlePtr) part->next;
14660 	} while (part != NULL);
14661 	return (particle->minOccurs * sum);
14662     }
14663 }
14664 
14665 #if 0
14666 /**
14667  * xmlSchemaGetParticleTotalRangeMax:
14668  * @particle: the particle
14669  *
14670  * Schema Component Constraint: Effective Total Range
14671  * (all and sequence) + (choice)
14672  *
14673  * Returns the maximum Effective Total Range.
14674  */
14675 static int
14676 xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
14677 {
14678     if ((particle->children == NULL) ||
14679 	(particle->children->children == NULL))
14680 	return (0);
14681     if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14682 	int max = -1, cur;
14683 	xmlSchemaParticlePtr part =
14684 	    (xmlSchemaParticlePtr) particle->children->children;
14685 
14686 	for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14687 	    if (part->children == NULL)
14688 		continue;
14689 	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14690 		(part->children->type == XML_SCHEMA_TYPE_ANY))
14691 		cur = part->maxOccurs;
14692 	    else
14693 		cur = xmlSchemaGetParticleTotalRangeMax(part);
14694 	    if (cur == UNBOUNDED)
14695 		return (UNBOUNDED);
14696 	    if ((max < cur) || (max == -1))
14697 		max = cur;
14698 	}
14699 	/* TODO: Handle overflows? */
14700 	return (particle->maxOccurs * max);
14701     } else {
14702 	/* <all> and <sequence> */
14703 	int sum = 0, cur;
14704 	xmlSchemaParticlePtr part =
14705 	    (xmlSchemaParticlePtr) particle->children->children;
14706 
14707 	for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14708 	    if (part->children == NULL)
14709 		continue;
14710 	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14711 		(part->children->type == XML_SCHEMA_TYPE_ANY))
14712 		cur = part->maxOccurs;
14713 	    else
14714 		cur = xmlSchemaGetParticleTotalRangeMax(part);
14715 	    if (cur == UNBOUNDED)
14716 		return (UNBOUNDED);
14717 	    if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
14718 		return (UNBOUNDED);
14719 	    sum += cur;
14720 	}
14721 	/* TODO: Handle overflows? */
14722 	return (particle->maxOccurs * sum);
14723     }
14724 }
14725 #endif
14726 
14727 /**
14728  * xmlSchemaIsParticleEmptiable:
14729  * @particle: the particle
14730  *
14731  * Schema Component Constraint: Particle Emptiable
14732  * Checks whether the given particle is emptiable.
14733  *
14734  * Returns 1 if emptiable, 0 otherwise.
14735  */
14736 static int
xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)14737 xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
14738 {
14739     /*
14740     * SPEC (1) "Its {min occurs} is 0."
14741     */
14742     if ((particle == NULL) || (particle->minOccurs == 0) ||
14743 	(particle->children == NULL))
14744 	return (1);
14745     /*
14746     * SPEC (2) "Its {term} is a group and the minimum part of the
14747     * effective total range of that group, [...] is 0."
14748     */
14749     if (WXS_IS_MODEL_GROUP(particle->children)) {
14750 	if (xmlSchemaGetParticleTotalRangeMin(particle) == 0)
14751 	    return (1);
14752     }
14753     return (0);
14754 }
14755 
14756 /**
14757  * xmlSchemaCheckCOSSTDerivedOK:
14758  * @actxt: a context
14759  * @type:  the derived simple type definition
14760  * @baseType:  the base type definition
14761  * @subset: the subset of ('restriction', ect.)
14762  *
14763  * Schema Component Constraint:
14764  * Type Derivation OK (Simple) (cos-st-derived-OK)
14765  *
14766  * Checks wheter @type can be validly
14767  * derived from @baseType.
14768  *
14769  * Returns 0 on success, an positive error code otherwise.
14770  */
14771 static int
xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,xmlSchemaTypePtr type,xmlSchemaTypePtr baseType,int subset)14772 xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
14773 			     xmlSchemaTypePtr type,
14774 			     xmlSchemaTypePtr baseType,
14775 			     int subset)
14776 {
14777     /*
14778     * 1 They are the same type definition.
14779     * TODO: The identy check might have to be more complex than this.
14780     */
14781     if (type == baseType)
14782 	return (0);
14783     /*
14784     * 2.1 restriction is not in the subset, or in the {final}
14785     * of its own {base type definition};
14786     *
14787     * NOTE that this will be used also via "xsi:type".
14788     *
14789     * TODO: Revise this, it looks strange. How can the "type"
14790     * not be fixed or *in* fixing?
14791     */
14792     if (WXS_IS_TYPE_NOT_FIXED(type))
14793 	if (xmlSchemaTypeFixup(type, actxt) == -1)
14794 	    return(-1);
14795     if (WXS_IS_TYPE_NOT_FIXED(baseType))
14796 	if (xmlSchemaTypeFixup(baseType, actxt) == -1)
14797 	    return(-1);
14798     if ((subset & SUBSET_RESTRICTION) ||
14799 	(xmlSchemaTypeFinalContains(type->baseType,
14800 	    XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
14801 	return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
14802     }
14803     /* 2.2 */
14804     if (type->baseType == baseType) {
14805 	/*
14806 	* 2.2.1 D's �base type definition� is B.
14807 	*/
14808 	return (0);
14809     }
14810     /*
14811     * 2.2.2 D's �base type definition� is not the �ur-type definition�
14812     * and is validly derived from B given the subset, as defined by this
14813     * constraint.
14814     */
14815     if ((! WXS_IS_ANYTYPE(type->baseType)) &&
14816 	(xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
14817 	    baseType, subset) == 0)) {
14818 	return (0);
14819     }
14820     /*
14821     * 2.2.3 D's {variety} is list or union and B is the �simple ur-type
14822     * definition�.
14823     */
14824     if (WXS_IS_ANY_SIMPLE_TYPE(baseType) &&
14825 	(WXS_IS_LIST(type) || WXS_IS_UNION(type))) {
14826 	return (0);
14827     }
14828     /*
14829     * 2.2.4 B's {variety} is union and D is validly derived from a type
14830     * definition in B's {member type definitions} given the subset, as
14831     * defined by this constraint.
14832     *
14833     * NOTE: This seems not to involve built-in types, since there is no
14834     * built-in Union Simple Type.
14835     */
14836     if (WXS_IS_UNION(baseType)) {
14837 	xmlSchemaTypeLinkPtr cur;
14838 
14839 	cur = baseType->memberTypes;
14840 	while (cur != NULL) {
14841 	    if (WXS_IS_TYPE_NOT_FIXED(cur->type))
14842 		if (xmlSchemaTypeFixup(cur->type, actxt) == -1)
14843 		    return(-1);
14844 	    if (xmlSchemaCheckCOSSTDerivedOK(actxt,
14845 		    type, cur->type, subset) == 0)
14846 	    {
14847 		/*
14848 		* It just has to be validly derived from at least one
14849 		* member-type.
14850 		*/
14851 		return (0);
14852 	    }
14853 	    cur = cur->next;
14854 	}
14855     }
14856     return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
14857 }
14858 
14859 /**
14860  * xmlSchemaCheckTypeDefCircularInternal:
14861  * @pctxt:  the schema parser context
14862  * @ctxtType:  the type definition
14863  * @ancestor: an ancestor of @ctxtType
14864  *
14865  * Checks st-props-correct (2) + ct-props-correct (3).
14866  * Circular type definitions are not allowed.
14867  *
14868  * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
14869  * circular, 0 otherwise.
14870  */
14871 static int
xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr ctxtType,xmlSchemaTypePtr ancestor)14872 xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
14873 			   xmlSchemaTypePtr ctxtType,
14874 			   xmlSchemaTypePtr ancestor)
14875 {
14876     int ret;
14877 
14878     if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
14879 	return (0);
14880 
14881     if (ctxtType == ancestor) {
14882 	xmlSchemaPCustomErr(pctxt,
14883 	    XML_SCHEMAP_ST_PROPS_CORRECT_2,
14884 	    WXS_BASIC_CAST ctxtType, WXS_ITEM_NODE(ctxtType),
14885 	    "The definition is circular", NULL);
14886 	return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
14887     }
14888     if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
14889 	/*
14890 	* Avoid inifinite recursion on circular types not yet checked.
14891 	*/
14892 	return (0);
14893     }
14894     ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
14895     ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
14896 	ancestor->baseType);
14897     ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
14898     return (ret);
14899 }
14900 
14901 /**
14902  * xmlSchemaCheckTypeDefCircular:
14903  * @item:  the complex/simple type definition
14904  * @ctxt:  the parser context
14905  * @name:  the name
14906  *
14907  * Checks for circular type definitions.
14908  */
14909 static void
xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,xmlSchemaParserCtxtPtr ctxt)14910 xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
14911 			      xmlSchemaParserCtxtPtr ctxt)
14912 {
14913     if ((item == NULL) ||
14914 	(item->type == XML_SCHEMA_TYPE_BASIC) ||
14915 	(item->baseType == NULL))
14916 	return;
14917     xmlSchemaCheckTypeDefCircularInternal(ctxt, item,
14918 	item->baseType);
14919 }
14920 
14921 /*
14922 * Simple Type Definition Representation OK (src-simple-type) 4
14923 *
14924 * "4 Circular union type definition is disallowed. That is, if the
14925 * <union> alternative is chosen, there must not be any entries in the
14926 * memberTypes [attribute] at any depth which resolve to the component
14927 * corresponding to the <simpleType>."
14928 *
14929 * Note that this should work on the *representation* of a component,
14930 * thus assumes any union types in the member types not being yet
14931 * substituted. At this stage we need the variety of the types
14932 * to be already computed.
14933 */
14934 static int
xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr ctxType,xmlSchemaTypeLinkPtr members)14935 xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,
14936 					xmlSchemaTypePtr ctxType,
14937 					xmlSchemaTypeLinkPtr members)
14938 {
14939     xmlSchemaTypeLinkPtr member;
14940     xmlSchemaTypePtr memberType;
14941 
14942     member = members;
14943     while (member != NULL) {
14944 	memberType = member->type;
14945 	while ((memberType != NULL) &&
14946 	    (memberType->type != XML_SCHEMA_TYPE_BASIC)) {
14947 	    if (memberType == ctxType) {
14948 		xmlSchemaPCustomErr(pctxt,
14949 		    XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
14950 		    WXS_BASIC_CAST ctxType, NULL,
14951 		    "The union type definition is circular", NULL);
14952 		return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
14953 	    }
14954 	    if ((WXS_IS_UNION(memberType)) &&
14955 		((memberType->flags & XML_SCHEMAS_TYPE_MARKED) == 0))
14956 	    {
14957 		int res;
14958 		memberType->flags |= XML_SCHEMAS_TYPE_MARKED;
14959 		res = xmlSchemaCheckUnionTypeDefCircularRecur(pctxt,
14960 		    ctxType,
14961 		    xmlSchemaGetUnionSimpleTypeMemberTypes(memberType));
14962 		memberType->flags ^= XML_SCHEMAS_TYPE_MARKED;
14963 		if (res != 0)
14964 		    return(res);
14965 	    }
14966 	    memberType = memberType->baseType;
14967 	}
14968 	member = member->next;
14969     }
14970     return(0);
14971 }
14972 
14973 static int
xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)14974 xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,
14975 				   xmlSchemaTypePtr type)
14976 {
14977     if (! WXS_IS_UNION(type))
14978 	return(0);
14979     return(xmlSchemaCheckUnionTypeDefCircularRecur(pctxt, type,
14980 	type->memberTypes));
14981 }
14982 
14983 /**
14984  * xmlSchemaResolveTypeReferences:
14985  * @item:  the complex/simple type definition
14986  * @ctxt:  the parser context
14987  * @name:  the name
14988  *
14989  * Resolvese type definition references
14990  */
14991 static void
xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,xmlSchemaParserCtxtPtr ctxt)14992 xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,
14993 			 xmlSchemaParserCtxtPtr ctxt)
14994 {
14995     if (typeDef == NULL)
14996 	return;
14997 
14998     /*
14999     * Resolve the base type.
15000     */
15001     if (typeDef->baseType == NULL) {
15002 	typeDef->baseType = xmlSchemaGetType(ctxt->schema,
15003 	    typeDef->base, typeDef->baseNs);
15004 	if (typeDef->baseType == NULL) {
15005 	    xmlSchemaPResCompAttrErr(ctxt,
15006 		XML_SCHEMAP_SRC_RESOLVE,
15007 		WXS_BASIC_CAST typeDef, typeDef->node,
15008 		"base", typeDef->base, typeDef->baseNs,
15009 		XML_SCHEMA_TYPE_SIMPLE, NULL);
15010 	    return;
15011 	}
15012     }
15013     if (WXS_IS_SIMPLE(typeDef)) {
15014 	if (WXS_IS_UNION(typeDef)) {
15015 	    /*
15016 	    * Resolve the memberTypes.
15017 	    */
15018 	    xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
15019 	    return;
15020 	} else if (WXS_IS_LIST(typeDef)) {
15021 	    /*
15022 	    * Resolve the itemType.
15023 	    */
15024 	    if ((typeDef->subtypes == NULL) && (typeDef->base != NULL)) {
15025 
15026 		typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
15027 		    typeDef->base, typeDef->baseNs);
15028 
15029 		if ((typeDef->subtypes == NULL) ||
15030 		    (! WXS_IS_SIMPLE(typeDef->subtypes)))
15031 		{
15032 		    typeDef->subtypes = NULL;
15033 		    xmlSchemaPResCompAttrErr(ctxt,
15034 			XML_SCHEMAP_SRC_RESOLVE,
15035 			WXS_BASIC_CAST typeDef, typeDef->node,
15036 			"itemType", typeDef->base, typeDef->baseNs,
15037 			XML_SCHEMA_TYPE_SIMPLE, NULL);
15038 		}
15039 	    }
15040 	    return;
15041 	}
15042     }
15043     /*
15044     * The ball of letters below means, that if we have a particle
15045     * which has a QName-helper component as its {term}, we want
15046     * to resolve it...
15047     */
15048     else if ((WXS_TYPE_CONTENTTYPE(typeDef) != NULL) &&
15049 	((WXS_TYPE_CONTENTTYPE(typeDef))->type ==
15050 	    XML_SCHEMA_TYPE_PARTICLE) &&
15051 	(WXS_TYPE_PARTICLE_TERM(typeDef) != NULL) &&
15052 	((WXS_TYPE_PARTICLE_TERM(typeDef))->type ==
15053 	    XML_SCHEMA_EXTRA_QNAMEREF))
15054     {
15055 	xmlSchemaQNameRefPtr ref =
15056 	    WXS_QNAME_CAST WXS_TYPE_PARTICLE_TERM(typeDef);
15057 	xmlSchemaModelGroupDefPtr groupDef;
15058 
15059 	/*
15060 	* URGENT TODO: Test this.
15061 	*/
15062 	WXS_TYPE_PARTICLE_TERM(typeDef) = NULL;
15063 	/*
15064 	* Resolve the MG definition reference.
15065 	*/
15066 	groupDef =
15067 	    WXS_MODEL_GROUPDEF_CAST xmlSchemaGetNamedComponent(ctxt->schema,
15068 		ref->itemType, ref->name, ref->targetNamespace);
15069 	if (groupDef == NULL) {
15070 	    xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
15071 		NULL, WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)),
15072 		"ref", ref->name, ref->targetNamespace, ref->itemType,
15073 		NULL);
15074 	    /* Remove the particle. */
15075 	    WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15076 	} else if (WXS_MODELGROUPDEF_MODEL(groupDef) == NULL)
15077 	    /* Remove the particle. */
15078 	    WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15079 	else {
15080 	    /*
15081 	    * Assign the MG definition's {model group} to the
15082 	    * particle's {term}.
15083 	    */
15084 	    WXS_TYPE_PARTICLE_TERM(typeDef) = WXS_MODELGROUPDEF_MODEL(groupDef);
15085 
15086 	    if (WXS_MODELGROUPDEF_MODEL(groupDef)->type == XML_SCHEMA_TYPE_ALL) {
15087 		/*
15088 		* SPEC cos-all-limited (1.2)
15089 		* "1.2 the {term} property of a particle with
15090 		* {max occurs}=1 which is part of a pair which constitutes
15091 		* the {content type} of a complex type definition."
15092 		*/
15093 		if ((WXS_TYPE_PARTICLE(typeDef))->maxOccurs != 1) {
15094 		    xmlSchemaCustomErr(ACTXT_CAST ctxt,
15095 			/* TODO: error code */
15096 			XML_SCHEMAP_COS_ALL_LIMITED,
15097 			WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)), NULL,
15098 			"The particle's {max occurs} must be 1, since the "
15099 			"reference resolves to an 'all' model group",
15100 			NULL, NULL);
15101 		}
15102 	    }
15103 	}
15104     }
15105 }
15106 
15107 
15108 
15109 /**
15110  * xmlSchemaCheckSTPropsCorrect:
15111  * @ctxt:  the schema parser context
15112  * @type:  the simple type definition
15113  *
15114  * Checks st-props-correct.
15115  *
15116  * Returns 0 if the properties are correct,
15117  * if not, a positive error code and -1 on internal
15118  * errors.
15119  */
15120 static int
xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)15121 xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
15122 			     xmlSchemaTypePtr type)
15123 {
15124     xmlSchemaTypePtr baseType = type->baseType;
15125     xmlChar *str = NULL;
15126 
15127     /* STATE: error funcs converted. */
15128     /*
15129     * Schema Component Constraint: Simple Type Definition Properties Correct
15130     *
15131     * NOTE: This is somehow redundant, since we actually built a simple type
15132     * to have all the needed information; this acts as an self test.
15133     */
15134     /* Base type: If the datatype has been �derived� by �restriction�
15135     * then the Simple Type Definition component from which it is �derived�,
15136     * otherwise the Simple Type Definition for anySimpleType (�4.1.6).
15137     */
15138     if (baseType == NULL) {
15139 	/*
15140 	* TODO: Think about: "modulo the impact of Missing
15141 	* Sub-components (�5.3)."
15142 	*/
15143 	xmlSchemaPCustomErr(ctxt,
15144 	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15145 	    WXS_BASIC_CAST type, NULL,
15146 	    "No base type existent", NULL);
15147 	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15148 
15149     }
15150     if (! WXS_IS_SIMPLE(baseType)) {
15151 	xmlSchemaPCustomErr(ctxt,
15152 	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15153 	    WXS_BASIC_CAST type, NULL,
15154 	    "The base type '%s' is not a simple type",
15155 	    xmlSchemaGetComponentQName(&str, baseType));
15156 	FREE_AND_NULL(str)
15157 	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15158     }
15159     if ( (WXS_IS_LIST(type) || WXS_IS_UNION(type)) &&
15160 	 (WXS_IS_RESTRICTION(type) == 0) &&
15161 	 (! WXS_IS_ANY_SIMPLE_TYPE(baseType))) {
15162 	xmlSchemaPCustomErr(ctxt,
15163 	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15164 	    WXS_BASIC_CAST type, NULL,
15165 	    "A type, derived by list or union, must have "
15166 	    "the simple ur-type definition as base type, not '%s'",
15167 	    xmlSchemaGetComponentQName(&str, baseType));
15168 	FREE_AND_NULL(str)
15169 	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15170     }
15171     /*
15172     * Variety: One of {atomic, list, union}.
15173     */
15174     if ((! WXS_IS_ATOMIC(type)) && (! WXS_IS_UNION(type)) &&
15175 	(! WXS_IS_LIST(type))) {
15176 	xmlSchemaPCustomErr(ctxt,
15177 	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15178 	    WXS_BASIC_CAST type, NULL,
15179 	    "The variety is absent", NULL);
15180 	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15181     }
15182     /* TODO: Finish this. Hmm, is this finished? */
15183 
15184     /*
15185     * 3 The {final} of the {base type definition} must not contain restriction.
15186     */
15187     if (xmlSchemaTypeFinalContains(baseType,
15188 	XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15189 	xmlSchemaPCustomErr(ctxt,
15190 	    XML_SCHEMAP_ST_PROPS_CORRECT_3,
15191 	    WXS_BASIC_CAST type, NULL,
15192 	    "The 'final' of its base type '%s' must not contain "
15193 	    "'restriction'",
15194 	    xmlSchemaGetComponentQName(&str, baseType));
15195 	FREE_AND_NULL(str)
15196 	return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
15197     }
15198 
15199     /*
15200     * 2 All simple type definitions must be derived ultimately from the �simple
15201     * ur-type definition (so� circular definitions are disallowed). That is, it
15202     * must be possible to reach a built-in primitive datatype or the �simple
15203     * ur-type definition� by repeatedly following the {base type definition}.
15204     *
15205     * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
15206     */
15207     return (0);
15208 }
15209 
15210 /**
15211  * xmlSchemaCheckCOSSTRestricts:
15212  * @ctxt:  the schema parser context
15213  * @type:  the simple type definition
15214  *
15215  * Schema Component Constraint:
15216  * Derivation Valid (Restriction, Simple) (cos-st-restricts)
15217 
15218  * Checks if the given @type (simpleType) is derived validly by restriction.
15219  * STATUS:
15220  *
15221  * Returns -1 on internal errors, 0 if the type is validly derived,
15222  * a positive error code otherwise.
15223  */
15224 static int
xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)15225 xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
15226 			     xmlSchemaTypePtr type)
15227 {
15228     xmlChar *str = NULL;
15229 
15230     if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
15231 	PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15232 	    "given type is not a user-derived simpleType");
15233 	return (-1);
15234     }
15235 
15236     if (WXS_IS_ATOMIC(type)) {
15237 	xmlSchemaTypePtr primitive;
15238 	/*
15239 	* 1.1 The {base type definition} must be an atomic simple
15240 	* type definition or a built-in primitive datatype.
15241 	*/
15242 	if (! WXS_IS_ATOMIC(type->baseType)) {
15243 	    xmlSchemaPCustomErr(pctxt,
15244 		XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
15245 		WXS_BASIC_CAST type, NULL,
15246 		"The base type '%s' is not an atomic simple type",
15247 		xmlSchemaGetComponentQName(&str, type->baseType));
15248 	    FREE_AND_NULL(str)
15249 	    return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
15250 	}
15251 	/* 1.2 The {final} of the {base type definition} must not contain
15252 	* restriction.
15253 	*/
15254 	/* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
15255 	if (xmlSchemaTypeFinalContains(type->baseType,
15256 	    XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15257 	    xmlSchemaPCustomErr(pctxt,
15258 		XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
15259 		WXS_BASIC_CAST type, NULL,
15260 		"The final of its base type '%s' must not contain 'restriction'",
15261 		xmlSchemaGetComponentQName(&str, type->baseType));
15262 	    FREE_AND_NULL(str)
15263 	    return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
15264 	}
15265 
15266 	/*
15267 	* 1.3.1 DF must be an allowed constraining facet for the {primitive
15268 	* type definition}, as specified in the appropriate subsection of 3.2
15269 	* Primitive datatypes.
15270 	*/
15271 	if (type->facets != NULL) {
15272 	    xmlSchemaFacetPtr facet;
15273 	    int ok = 1;
15274 
15275 	    primitive = xmlSchemaGetPrimitiveType(type);
15276 	    if (primitive == NULL) {
15277 		PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15278 		    "failed to get primitive type");
15279 		return (-1);
15280 	    }
15281 	    facet = type->facets;
15282 	    do {
15283 		if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
15284 		    ok = 0;
15285 		    xmlSchemaPIllegalFacetAtomicErr(pctxt,
15286 			XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
15287 			type, primitive, facet);
15288 		}
15289 		facet = facet->next;
15290 	    } while (facet != NULL);
15291 	    if (ok == 0)
15292 		return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
15293 	}
15294 	/*
15295 	* SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
15296 	* of the {base type definition} (call this BF),then the DF's {value}
15297 	* must be a valid restriction of BF's {value} as defined in
15298 	* [XML Schemas: Datatypes]."
15299 	*
15300 	* NOTE (1.3.2) Facet derivation constraints are currently handled in
15301 	* xmlSchemaDeriveAndValidateFacets()
15302 	*/
15303     } else if (WXS_IS_LIST(type)) {
15304 	xmlSchemaTypePtr itemType = NULL;
15305 
15306 	itemType = type->subtypes;
15307 	if ((itemType == NULL) || (! WXS_IS_SIMPLE(itemType))) {
15308 	    PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15309 		"failed to evaluate the item type");
15310 	    return (-1);
15311 	}
15312 	if (WXS_IS_TYPE_NOT_FIXED(itemType))
15313 	    xmlSchemaTypeFixup(itemType, ACTXT_CAST pctxt);
15314 	/*
15315 	* 2.1 The {item type definition} must have a {variety} of atomic or
15316 	* union (in which case all the {member type definitions}
15317 	* must be atomic).
15318 	*/
15319 	if ((! WXS_IS_ATOMIC(itemType)) &&
15320 	    (! WXS_IS_UNION(itemType))) {
15321 	    xmlSchemaPCustomErr(pctxt,
15322 		XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15323 		WXS_BASIC_CAST type, NULL,
15324 		"The item type '%s' does not have a variety of atomic or union",
15325 		xmlSchemaGetComponentQName(&str, itemType));
15326 	    FREE_AND_NULL(str)
15327 	    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15328 	} else if (WXS_IS_UNION(itemType)) {
15329 	    xmlSchemaTypeLinkPtr member;
15330 
15331 	    member = itemType->memberTypes;
15332 	    while (member != NULL) {
15333 		if (! WXS_IS_ATOMIC(member->type)) {
15334 		    xmlSchemaPCustomErr(pctxt,
15335 			XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15336 			WXS_BASIC_CAST type, NULL,
15337 			"The item type is a union type, but the "
15338 			"member type '%s' of this item type is not atomic",
15339 			xmlSchemaGetComponentQName(&str, member->type));
15340 		    FREE_AND_NULL(str)
15341 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15342 		}
15343 		member = member->next;
15344 	    }
15345 	}
15346 
15347 	if (WXS_IS_ANY_SIMPLE_TYPE(type->baseType)) {
15348 	    xmlSchemaFacetPtr facet;
15349 	    /*
15350 	    * This is the case if we have: <simpleType><list ..
15351 	    */
15352 	    /*
15353 	    * 2.3.1
15354 	    * 2.3.1.1 The {final} of the {item type definition} must not
15355 	    * contain list.
15356 	    */
15357 	    if (xmlSchemaTypeFinalContains(itemType,
15358 		XML_SCHEMAS_TYPE_FINAL_LIST)) {
15359 		xmlSchemaPCustomErr(pctxt,
15360 		    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
15361 		    WXS_BASIC_CAST type, NULL,
15362 		    "The final of its item type '%s' must not contain 'list'",
15363 		    xmlSchemaGetComponentQName(&str, itemType));
15364 		FREE_AND_NULL(str)
15365 		return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
15366 	    }
15367 	    /*
15368 	    * 2.3.1.2 The {facets} must only contain the whiteSpace
15369 	    * facet component.
15370 	    * OPTIMIZE TODO: the S4S already disallows any facet
15371 	    * to be specified.
15372 	    */
15373 	    if (type->facets != NULL) {
15374 		facet = type->facets;
15375 		do {
15376 		    if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
15377 			xmlSchemaPIllegalFacetListUnionErr(pctxt,
15378 			    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
15379 			    type, facet);
15380 			return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
15381 		    }
15382 		    facet = facet->next;
15383 		} while (facet != NULL);
15384 	    }
15385 	    /*
15386 	    * MAYBE TODO: (Hmm, not really) Datatypes states:
15387 	    * A �list� datatype can be �derived� from an �atomic� datatype
15388 	    * whose �lexical space� allows space (such as string or anyURI)or
15389 	    * a �union� datatype any of whose {member type definitions}'s
15390 	    * �lexical space� allows space.
15391 	    */
15392 	} else {
15393 	    /*
15394 	    * This is the case if we have: <simpleType><restriction ...
15395 	    * I.e. the variety of "list" is inherited.
15396 	    */
15397 	    /*
15398 	    * 2.3.2
15399 	    * 2.3.2.1 The {base type definition} must have a {variety} of list.
15400 	    */
15401 	    if (! WXS_IS_LIST(type->baseType)) {
15402 		xmlSchemaPCustomErr(pctxt,
15403 		    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
15404 		    WXS_BASIC_CAST type, NULL,
15405 		    "The base type '%s' must be a list type",
15406 		    xmlSchemaGetComponentQName(&str, type->baseType));
15407 		FREE_AND_NULL(str)
15408 		return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
15409 	    }
15410 	    /*
15411 	    * 2.3.2.2 The {final} of the {base type definition} must not
15412 	    * contain restriction.
15413 	    */
15414 	    if (xmlSchemaTypeFinalContains(type->baseType,
15415 		XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15416 		xmlSchemaPCustomErr(pctxt,
15417 		    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
15418 		    WXS_BASIC_CAST type, NULL,
15419 		    "The 'final' of the base type '%s' must not contain 'restriction'",
15420 		    xmlSchemaGetComponentQName(&str, type->baseType));
15421 		FREE_AND_NULL(str)
15422 		return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
15423 	    }
15424 	    /*
15425 	    * 2.3.2.3 The {item type definition} must be validly derived
15426 	    * from the {base type definition}'s {item type definition} given
15427 	    * the empty set, as defined in Type Derivation OK (Simple) (�3.14.6).
15428 	    */
15429 	    {
15430 		xmlSchemaTypePtr baseItemType;
15431 
15432 		baseItemType = type->baseType->subtypes;
15433 		if ((baseItemType == NULL) || (! WXS_IS_SIMPLE(baseItemType))) {
15434 		    PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15435 			"failed to eval the item type of a base type");
15436 		    return (-1);
15437 		}
15438 		if ((itemType != baseItemType) &&
15439 		    (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt, itemType,
15440 			baseItemType, 0) != 0)) {
15441 		    xmlChar *strBIT = NULL, *strBT = NULL;
15442 		    xmlSchemaPCustomErrExt(pctxt,
15443 			XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
15444 			WXS_BASIC_CAST type, NULL,
15445 			"The item type '%s' is not validly derived from "
15446 			"the item type '%s' of the base type '%s'",
15447 			xmlSchemaGetComponentQName(&str, itemType),
15448 			xmlSchemaGetComponentQName(&strBIT, baseItemType),
15449 			xmlSchemaGetComponentQName(&strBT, type->baseType));
15450 
15451 		    FREE_AND_NULL(str)
15452 		    FREE_AND_NULL(strBIT)
15453 		    FREE_AND_NULL(strBT)
15454 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
15455 		}
15456 	    }
15457 
15458 	    if (type->facets != NULL) {
15459 		xmlSchemaFacetPtr facet;
15460 		int ok = 1;
15461 		/*
15462 		* 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
15463 		* and enumeration facet components are allowed among the {facets}.
15464 		*/
15465 		facet = type->facets;
15466 		do {
15467 		    switch (facet->type) {
15468 			case XML_SCHEMA_FACET_LENGTH:
15469 			case XML_SCHEMA_FACET_MINLENGTH:
15470 			case XML_SCHEMA_FACET_MAXLENGTH:
15471 			case XML_SCHEMA_FACET_WHITESPACE:
15472 			    /*
15473 			    * TODO: 2.5.1.2 List datatypes
15474 			    * The value of �whiteSpace� is fixed to the value collapse.
15475 			    */
15476 			case XML_SCHEMA_FACET_PATTERN:
15477 			case XML_SCHEMA_FACET_ENUMERATION:
15478 			    break;
15479 			default: {
15480 			    xmlSchemaPIllegalFacetListUnionErr(pctxt,
15481 				XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
15482 				type, facet);
15483 			    /*
15484 			    * We could return, but it's nicer to report all
15485 			    * invalid facets.
15486 			    */
15487 			    ok = 0;
15488 			}
15489 		    }
15490 		    facet = facet->next;
15491 		} while (facet != NULL);
15492 		if (ok == 0)
15493 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
15494 		/*
15495 		* SPEC (2.3.2.5) (same as 1.3.2)
15496 		*
15497 		* NOTE (2.3.2.5) This is currently done in
15498 		* xmlSchemaDeriveAndValidateFacets()
15499 		*/
15500 	    }
15501 	}
15502     } else if (WXS_IS_UNION(type)) {
15503 	/*
15504 	* 3.1 The {member type definitions} must all have {variety} of
15505 	* atomic or list.
15506 	*/
15507 	xmlSchemaTypeLinkPtr member;
15508 
15509 	member = type->memberTypes;
15510 	while (member != NULL) {
15511 	    if (WXS_IS_TYPE_NOT_FIXED(member->type))
15512 		xmlSchemaTypeFixup(member->type, ACTXT_CAST pctxt);
15513 
15514 	    if ((! WXS_IS_ATOMIC(member->type)) &&
15515 		(! WXS_IS_LIST(member->type))) {
15516 		xmlSchemaPCustomErr(pctxt,
15517 		    XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
15518 		    WXS_BASIC_CAST type, NULL,
15519 		    "The member type '%s' is neither an atomic, nor a list type",
15520 		    xmlSchemaGetComponentQName(&str, member->type));
15521 		FREE_AND_NULL(str)
15522 		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
15523 	    }
15524 	    member = member->next;
15525 	}
15526 	/*
15527 	* 3.3.1 If the {base type definition} is the �simple ur-type
15528 	* definition�
15529 	*/
15530 	if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
15531 	    /*
15532 	    * 3.3.1.1 All of the {member type definitions} must have a
15533 	    * {final} which does not contain union.
15534 	    */
15535 	    member = type->memberTypes;
15536 	    while (member != NULL) {
15537 		if (xmlSchemaTypeFinalContains(member->type,
15538 		    XML_SCHEMAS_TYPE_FINAL_UNION)) {
15539 		    xmlSchemaPCustomErr(pctxt,
15540 			XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
15541 			WXS_BASIC_CAST type, NULL,
15542 			"The 'final' of member type '%s' contains 'union'",
15543 			xmlSchemaGetComponentQName(&str, member->type));
15544 		    FREE_AND_NULL(str)
15545 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
15546 		}
15547 		member = member->next;
15548 	    }
15549 	    /*
15550 	    * 3.3.1.2 The {facets} must be empty.
15551 	    */
15552 	    if (type->facetSet != NULL) {
15553 		xmlSchemaPCustomErr(pctxt,
15554 		    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
15555 		    WXS_BASIC_CAST type, NULL,
15556 		    "No facets allowed", NULL);
15557 		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
15558 	    }
15559 	} else {
15560 	    /*
15561 	    * 3.3.2.1 The {base type definition} must have a {variety} of union.
15562 	    * I.e. the variety of "list" is inherited.
15563 	    */
15564 	    if (! WXS_IS_UNION(type->baseType)) {
15565 		xmlSchemaPCustomErr(pctxt,
15566 		    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
15567 		    WXS_BASIC_CAST type, NULL,
15568 		    "The base type '%s' is not a union type",
15569 		    xmlSchemaGetComponentQName(&str, type->baseType));
15570 		FREE_AND_NULL(str)
15571 		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
15572 	    }
15573 	    /*
15574 	    * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
15575 	    */
15576 	    if (xmlSchemaTypeFinalContains(type->baseType,
15577 		XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15578 		xmlSchemaPCustomErr(pctxt,
15579 		    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
15580 		    WXS_BASIC_CAST type, NULL,
15581 		    "The 'final' of its base type '%s' must not contain 'restriction'",
15582 		    xmlSchemaGetComponentQName(&str, type->baseType));
15583 		FREE_AND_NULL(str)
15584 		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
15585 	    }
15586 	    /*
15587 	    * 3.3.2.3 The {member type definitions}, in order, must be validly
15588 	    * derived from the corresponding type definitions in the {base
15589 	    * type definition}'s {member type definitions} given the empty set,
15590 	    * as defined in Type Derivation OK (Simple) (�3.14.6).
15591 	    */
15592 	    {
15593 		xmlSchemaTypeLinkPtr baseMember;
15594 
15595 		/*
15596 		* OPTIMIZE: if the type is restricting, it has no local defined
15597 		* member types and inherits the member types of the base type;
15598 		* thus a check for equality can be skipped.
15599 		*/
15600 		/*
15601 		* Even worse: I cannot see a scenario where a restricting
15602 		* union simple type can have other member types as the member
15603 		* types of it's base type. This check seems not necessary with
15604 		* respect to the derivation process in libxml2.
15605 		* But necessary if constructing types with an API.
15606 		*/
15607 		if (type->memberTypes != NULL) {
15608 		    member = type->memberTypes;
15609 		    baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
15610 		    if ((member == NULL) && (baseMember != NULL)) {
15611 			PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15612 			    "different number of member types in base");
15613 		    }
15614 		    while (member != NULL) {
15615 			if (baseMember == NULL) {
15616 			    PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15617 			    "different number of member types in base");
15618 			} else if ((member->type != baseMember->type) &&
15619 			    (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
15620 				member->type, baseMember->type, 0) != 0)) {
15621 			    xmlChar *strBMT = NULL, *strBT = NULL;
15622 
15623 			    xmlSchemaPCustomErrExt(pctxt,
15624 				XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
15625 				WXS_BASIC_CAST type, NULL,
15626 				"The member type %s is not validly "
15627 				"derived from its corresponding member "
15628 				"type %s of the base type %s",
15629 				xmlSchemaGetComponentQName(&str, member->type),
15630 				xmlSchemaGetComponentQName(&strBMT, baseMember->type),
15631 				xmlSchemaGetComponentQName(&strBT, type->baseType));
15632 			    FREE_AND_NULL(str)
15633 			    FREE_AND_NULL(strBMT)
15634 			    FREE_AND_NULL(strBT)
15635 			    return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
15636 			}
15637 			member = member->next;
15638                         if (baseMember != NULL)
15639                             baseMember = baseMember->next;
15640 		    }
15641 		}
15642 	    }
15643 	    /*
15644 	    * 3.3.2.4 Only pattern and enumeration facet components are
15645 	    * allowed among the {facets}.
15646 	    */
15647 	    if (type->facets != NULL) {
15648 		xmlSchemaFacetPtr facet;
15649 		int ok = 1;
15650 
15651 		facet = type->facets;
15652 		do {
15653 		    if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
15654 			(facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
15655 			xmlSchemaPIllegalFacetListUnionErr(pctxt,
15656 				XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
15657 				type, facet);
15658 			ok = 0;
15659 		    }
15660 		    facet = facet->next;
15661 		} while (facet != NULL);
15662 		if (ok == 0)
15663 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
15664 
15665 	    }
15666 	    /*
15667 	    * SPEC (3.3.2.5) (same as 1.3.2)
15668 	    *
15669 	    * NOTE (3.3.2.5) This is currently done in
15670 	    * xmlSchemaDeriveAndValidateFacets()
15671 	    */
15672 	}
15673     }
15674 
15675     return (0);
15676 }
15677 
15678 /**
15679  * xmlSchemaCheckSRCSimpleType:
15680  * @ctxt:  the schema parser context
15681  * @type:  the simple type definition
15682  *
15683  * Checks crc-simple-type constraints.
15684  *
15685  * Returns 0 if the constraints are satisfied,
15686  * if not a positive error code and -1 on internal
15687  * errors.
15688  */
15689 #if 0
15690 static int
15691 xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
15692 			    xmlSchemaTypePtr type)
15693 {
15694     /*
15695     * src-simple-type.1 The corresponding simple type definition, if any,
15696     * must satisfy the conditions set out in Constraints on Simple Type
15697     * Definition Schema Components (�3.14.6).
15698     */
15699     if (WXS_IS_RESTRICTION(type)) {
15700 	/*
15701 	* src-simple-type.2 "If the <restriction> alternative is chosen,
15702 	* either it must have a base [attribute] or a <simpleType> among its
15703 	* [children], but not both."
15704 	* NOTE: This is checked in the parse function of <restriction>.
15705 	*/
15706 	/*
15707 	*
15708 	*/
15709     } else if (WXS_IS_LIST(type)) {
15710 	/* src-simple-type.3 "If the <list> alternative is chosen, either it must have
15711 	* an itemType [attribute] or a <simpleType> among its [children],
15712 	* but not both."
15713 	*
15714 	* NOTE: This is checked in the parse function of <list>.
15715 	*/
15716     } else if (WXS_IS_UNION(type)) {
15717 	/*
15718 	* src-simple-type.4 is checked in xmlSchemaCheckUnionTypeDefCircular().
15719 	*/
15720     }
15721     return (0);
15722 }
15723 #endif
15724 
15725 static int
xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)15726 xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
15727 {
15728    if (ctxt->vctxt == NULL) {
15729 	ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
15730 	if (ctxt->vctxt == NULL) {
15731 	    xmlSchemaPErr(ctxt, NULL,
15732 		XML_SCHEMAP_INTERNAL,
15733 		"Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
15734 		"failed to create a temp. validation context.\n",
15735 		NULL, NULL);
15736 	    return (-1);
15737 	}
15738 	/* TODO: Pass user data. */
15739 	xmlSchemaSetValidErrors(ctxt->vctxt,
15740 	    ctxt->error, ctxt->warning, ctxt->errCtxt);
15741 	xmlSchemaSetValidStructuredErrors(ctxt->vctxt,
15742 	    ctxt->serror, ctxt->errCtxt);
15743     }
15744     return (0);
15745 }
15746 
15747 static int
15748 xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
15749 			     xmlNodePtr node,
15750 			     xmlSchemaTypePtr type,
15751 			     const xmlChar *value,
15752 			     xmlSchemaValPtr *retVal,
15753 			     int fireErrors,
15754 			     int normalize,
15755 			     int isNormalized);
15756 
15757 /**
15758  * xmlSchemaParseCheckCOSValidDefault:
15759  * @pctxt:  the schema parser context
15760  * @type:  the simple type definition
15761  * @value: the default value
15762  * @node: an optional node (the holder of the value)
15763  *
15764  * Schema Component Constraint: Element Default Valid (Immediate)
15765  * (cos-valid-default)
15766  * This will be used by the parser only. For the validator there's
15767  * an other version.
15768  *
15769  * Returns 0 if the constraints are satisfied,
15770  * if not, a positive error code and -1 on internal
15771  * errors.
15772  */
15773 static int
xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,xmlNodePtr node,xmlSchemaTypePtr type,const xmlChar * value,xmlSchemaValPtr * val)15774 xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
15775 				   xmlNodePtr node,
15776 				   xmlSchemaTypePtr type,
15777 				   const xmlChar *value,
15778 				   xmlSchemaValPtr *val)
15779 {
15780     int ret = 0;
15781 
15782     /*
15783     * cos-valid-default:
15784     * Schema Component Constraint: Element Default Valid (Immediate)
15785     * For a string to be a valid default with respect to a type
15786     * definition the appropriate case among the following must be true:
15787     */
15788     if WXS_IS_COMPLEX(type) {
15789 	/*
15790 	* Complex type.
15791 	*
15792 	* SPEC (2.1) "its {content type} must be a simple type definition
15793 	* or mixed."
15794 	* SPEC (2.2.2) "If the {content type} is mixed, then the {content
15795 	* type}'s particle must be �emptiable� as defined by
15796 	* Particle Emptiable (�3.9.6)."
15797 	*/
15798 	if ((! WXS_HAS_SIMPLE_CONTENT(type)) &&
15799 	    ((! WXS_HAS_MIXED_CONTENT(type)) || (! WXS_EMPTIABLE(type)))) {
15800 	    /* NOTE that this covers (2.2.2) as well. */
15801 	    xmlSchemaPCustomErr(pctxt,
15802 		XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
15803 		WXS_BASIC_CAST type, type->node,
15804 		"For a string to be a valid default, the type definition "
15805 		"must be a simple type or a complex type with mixed content "
15806 		"and a particle emptiable", NULL);
15807 	    return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
15808 	}
15809     }
15810     /*
15811     * 1 If the type definition is a simple type definition, then the string
15812     * must be �valid� with respect to that definition as defined by String
15813     * Valid (�3.14.4).
15814     *
15815     * AND
15816     *
15817     * 2.2.1 If the {content type} is a simple type definition, then the
15818     * string must be �valid� with respect to that simple type definition
15819     * as defined by String Valid (�3.14.4).
15820     */
15821     if (WXS_IS_SIMPLE(type))
15822 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15823 	    type, value, val, 1, 1, 0);
15824     else if (WXS_HAS_SIMPLE_CONTENT(type))
15825 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15826 	    type->contentTypeDef, value, val, 1, 1, 0);
15827     else
15828 	return (ret);
15829 
15830     if (ret < 0) {
15831 	PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
15832 	    "calling xmlSchemaVCheckCVCSimpleType()");
15833     }
15834 
15835     return (ret);
15836 }
15837 
15838 /**
15839  * xmlSchemaCheckCTPropsCorrect:
15840  * @ctxt:  the schema parser context
15841  * @type:  the complex type definition
15842  *
15843  *.(4.6) Constraints on Complex Type Definition Schema Components
15844  * Schema Component Constraint:
15845  * Complex Type Definition Properties Correct (ct-props-correct)
15846  * STATUS: (seems) complete
15847  *
15848  * Returns 0 if the constraints are satisfied, a positive
15849  * error code if not and -1 if an internal error occured.
15850  */
15851 static int
xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)15852 xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
15853 			     xmlSchemaTypePtr type)
15854 {
15855     /*
15856     * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
15857     *
15858     * SPEC (1) "The values of the properties of a complex type definition must
15859     * be as described in the property tableau in The Complex Type Definition
15860     * Schema Component (�3.4.1), modulo the impact of Missing
15861     * Sub-components (�5.3)."
15862     */
15863     if ((type->baseType != NULL) &&
15864 	(WXS_IS_SIMPLE(type->baseType)) &&
15865 	(WXS_IS_EXTENSION(type) == 0)) {
15866 	/*
15867 	* SPEC (2) "If the {base type definition} is a simple type definition,
15868 	* the {derivation method} must be extension."
15869 	*/
15870 	xmlSchemaCustomErr(ACTXT_CAST pctxt,
15871 	    XML_SCHEMAP_SRC_CT_1,
15872 	    NULL, WXS_BASIC_CAST type,
15873 	    "If the base type is a simple type, the derivation method must be "
15874 	    "'extension'", NULL, NULL);
15875 	return (XML_SCHEMAP_SRC_CT_1);
15876     }
15877     /*
15878     * SPEC (3) "Circular definitions are disallowed, except for the �ur-type
15879     * definition�. That is, it must be possible to reach the �ur-type
15880     * definition by repeatedly following the {base type definition}."
15881     *
15882     * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
15883     */
15884     /*
15885     * NOTE that (4) and (5) need the following:
15886     *   - attribute uses need to be already inherited (apply attr. prohibitions)
15887     *   - attribute group references need to be expanded already
15888     *   - simple types need to be typefixed already
15889     */
15890     if (type->attrUses &&
15891 	(((xmlSchemaItemListPtr) type->attrUses)->nbItems > 1))
15892     {
15893 	xmlSchemaItemListPtr uses = (xmlSchemaItemListPtr) type->attrUses;
15894 	xmlSchemaAttributeUsePtr use, tmp;
15895 	int i, j, hasId = 0;
15896 
15897 	for (i = uses->nbItems -1; i >= 0; i--) {
15898 	    use = uses->items[i];
15899 
15900 	    /*
15901 	    * SPEC ct-props-correct
15902 	    * (4) "Two distinct attribute declarations in the
15903 	    * {attribute uses} must not have identical {name}s and
15904 	    * {target namespace}s."
15905 	    */
15906 	    if (i > 0) {
15907 		for (j = i -1; j >= 0; j--) {
15908 		    tmp = uses->items[j];
15909 		    if ((WXS_ATTRUSE_DECL_NAME(use) ==
15910 			WXS_ATTRUSE_DECL_NAME(tmp)) &&
15911 			(WXS_ATTRUSE_DECL_TNS(use) ==
15912 			WXS_ATTRUSE_DECL_TNS(tmp)))
15913 		    {
15914 			xmlChar *str = NULL;
15915 
15916 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
15917 			    XML_SCHEMAP_AG_PROPS_CORRECT,
15918 			    NULL, WXS_BASIC_CAST type,
15919 			    "Duplicate %s",
15920 			    xmlSchemaGetComponentDesignation(&str, use),
15921 			    NULL);
15922 			FREE_AND_NULL(str);
15923 			/*
15924 			* Remove the duplicate.
15925 			*/
15926 			if (xmlSchemaItemListRemove(uses, i) == -1)
15927 			    goto exit_failure;
15928 			goto next_use;
15929 		    }
15930 		}
15931 	    }
15932 	    /*
15933 	    * SPEC ct-props-correct
15934 	    * (5) "Two distinct attribute declarations in the
15935 	    * {attribute uses} must not have {type definition}s which
15936 	    * are or are derived from ID."
15937 	    */
15938 	    if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
15939 		if (xmlSchemaIsDerivedFromBuiltInType(
15940 		    WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
15941 		{
15942 		    if (hasId) {
15943 			xmlChar *str = NULL;
15944 
15945 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
15946 			    XML_SCHEMAP_AG_PROPS_CORRECT,
15947 			    NULL, WXS_BASIC_CAST type,
15948 			    "There must not exist more than one attribute "
15949 			    "declaration of type 'xs:ID' "
15950 			    "(or derived from 'xs:ID'). The %s violates this "
15951 			    "constraint",
15952 			    xmlSchemaGetComponentDesignation(&str, use),
15953 			    NULL);
15954 			FREE_AND_NULL(str);
15955 			if (xmlSchemaItemListRemove(uses, i) == -1)
15956 			    goto exit_failure;
15957 		    }
15958 
15959 		    hasId = 1;
15960 		}
15961 	    }
15962 next_use: {}
15963 	}
15964     }
15965     return (0);
15966 exit_failure:
15967     return(-1);
15968 }
15969 
15970 static int
xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,xmlSchemaTypePtr typeB)15971 xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
15972 		       xmlSchemaTypePtr typeB)
15973 {
15974     /*
15975     * TODO: This should implement component-identity
15976     * in the future.
15977     */
15978     if ((typeA == NULL) || (typeB == NULL))
15979 	return (0);
15980     return (typeA == typeB);
15981 }
15982 
15983 /**
15984  * xmlSchemaCheckCOSCTDerivedOK:
15985  * @ctxt:  the schema parser context
15986  * @type:  the to-be derived complex type definition
15987  * @baseType:  the base complex type definition
15988  * @set: the given set
15989  *
15990  * Schema Component Constraint:
15991  * Type Derivation OK (Complex) (cos-ct-derived-ok)
15992  *
15993  * STATUS: completed
15994  *
15995  * Returns 0 if the constraints are satisfied, or 1
15996  * if not.
15997  */
15998 static int
xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,xmlSchemaTypePtr type,xmlSchemaTypePtr baseType,int set)15999 xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16000 			     xmlSchemaTypePtr type,
16001 			     xmlSchemaTypePtr baseType,
16002 			     int set)
16003 {
16004     int equal = xmlSchemaAreEqualTypes(type, baseType);
16005     /* TODO: Error codes. */
16006     /*
16007     * SPEC "For a complex type definition (call it D, for derived)
16008     * to be validly derived from a type definition (call this
16009     * B, for base) given a subset of {extension, restriction}
16010     * all of the following must be true:"
16011     */
16012     if (! equal) {
16013 	/*
16014 	* SPEC (1) "If B and D are not the same type definition, then the
16015 	* {derivation method} of D must not be in the subset."
16016 	*/
16017 	if (((set & SUBSET_EXTENSION) && (WXS_IS_EXTENSION(type))) ||
16018 	    ((set & SUBSET_RESTRICTION) && (WXS_IS_RESTRICTION(type))))
16019 	    return (1);
16020     } else {
16021 	/*
16022 	* SPEC (2.1) "B and D must be the same type definition."
16023 	*/
16024 	return (0);
16025     }
16026     /*
16027     * SPEC (2.2) "B must be D's {base type definition}."
16028     */
16029     if (type->baseType == baseType)
16030 	return (0);
16031     /*
16032     * SPEC (2.3.1) "D's {base type definition} must not be the �ur-type
16033     * definition�."
16034     */
16035     if (WXS_IS_ANYTYPE(type->baseType))
16036 	return (1);
16037 
16038     if (WXS_IS_COMPLEX(type->baseType)) {
16039 	/*
16040 	* SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
16041 	* must be validly derived from B given the subset as defined by this
16042 	* constraint."
16043 	*/
16044 	return (xmlSchemaCheckCOSCTDerivedOK(actxt, type->baseType,
16045 	    baseType, set));
16046     } else {
16047 	/*
16048 	* SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
16049 	* must be validly derived from B given the subset as defined in Type
16050 	* Derivation OK (Simple) (�3.14.6).
16051 	*/
16052 	return (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
16053 	    baseType, set));
16054     }
16055 }
16056 
16057 /**
16058  * xmlSchemaCheckCOSDerivedOK:
16059  * @type:  the derived simple type definition
16060  * @baseType:  the base type definition
16061  *
16062  * Calls:
16063  * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
16064  *
16065  * Checks wheter @type can be validly derived from @baseType.
16066  *
16067  * Returns 0 on success, an positive error code otherwise.
16068  */
16069 static int
xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt,xmlSchemaTypePtr type,xmlSchemaTypePtr baseType,int set)16070 xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16071 			   xmlSchemaTypePtr type,
16072 			   xmlSchemaTypePtr baseType,
16073 			   int set)
16074 {
16075     if (WXS_IS_SIMPLE(type))
16076 	return (xmlSchemaCheckCOSSTDerivedOK(actxt, type, baseType, set));
16077     else
16078 	return (xmlSchemaCheckCOSCTDerivedOK(actxt, type, baseType, set));
16079 }
16080 
16081 /**
16082  * xmlSchemaCheckCOSCTExtends:
16083  * @ctxt:  the schema parser context
16084  * @type:  the complex type definition
16085  *
16086  * (3.4.6) Constraints on Complex Type Definition Schema Components
16087  * Schema Component Constraint:
16088  * Derivation Valid (Extension) (cos-ct-extends)
16089  *
16090  * STATUS:
16091  *   missing:
16092  *     (1.5)
16093  *     (1.4.3.2.2.2) "Particle Valid (Extension)"
16094  *
16095  * Returns 0 if the constraints are satisfied, a positive
16096  * error code if not and -1 if an internal error occured.
16097  */
16098 static int
xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)16099 xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
16100 			   xmlSchemaTypePtr type)
16101 {
16102     xmlSchemaTypePtr base = type->baseType;
16103     /*
16104     * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
16105     * temporarily only.
16106     */
16107     /*
16108     * SPEC (1) "If the {base type definition} is a complex type definition,
16109     * then all of the following must be true:"
16110     */
16111     if (WXS_IS_COMPLEX(base)) {
16112 	/*
16113 	* SPEC (1.1) "The {final} of the {base type definition} must not
16114 	* contain extension."
16115 	*/
16116 	if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16117 	    xmlSchemaPCustomErr(ctxt,
16118 		XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16119 		WXS_BASIC_CAST type, NULL,
16120 		"The 'final' of the base type definition "
16121 		"contains 'extension'", NULL);
16122 	    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16123 	}
16124 
16125 	/*
16126 	* ATTENTION: The constrains (1.2) and (1.3) are not applied,
16127 	* since they are automatically satisfied through the
16128 	* inheriting mechanism.
16129 	* Note that even if redefining components, the inheriting mechanism
16130 	* is used.
16131 	*/
16132 #if 0
16133 	/*
16134 	* SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
16135 	* uses}
16136 	* of the complex type definition itself, that is, for every attribute
16137 	* use in the {attribute uses} of the {base type definition}, there
16138 	* must be an attribute use in the {attribute uses} of the complex
16139 	* type definition itself whose {attribute declaration} has the same
16140 	* {name}, {target namespace} and {type definition} as its attribute
16141 	* declaration"
16142 	*/
16143 	if (base->attrUses != NULL) {
16144 	    int i, j, found;
16145 	    xmlSchemaAttributeUsePtr use, buse;
16146 
16147 	    for (i = 0; i < (WXS_LIST_CAST base->attrUses)->nbItems; i ++) {
16148 		buse = (WXS_LIST_CAST base->attrUses)->items[i];
16149 		found = 0;
16150 		if (type->attrUses != NULL) {
16151 		    use = (WXS_LIST_CAST type->attrUses)->items[j];
16152 		    for (j = 0; j < (WXS_LIST_CAST type->attrUses)->nbItems; j ++)
16153 		    {
16154 			if ((WXS_ATTRUSE_DECL_NAME(use) ==
16155 				WXS_ATTRUSE_DECL_NAME(buse)) &&
16156 			    (WXS_ATTRUSE_DECL_TNS(use) ==
16157 				WXS_ATTRUSE_DECL_TNS(buse)) &&
16158 			    (WXS_ATTRUSE_TYPEDEF(use) ==
16159 				WXS_ATTRUSE_TYPEDEF(buse))
16160 			{
16161 			    found = 1;
16162 			    break;
16163 			}
16164 		    }
16165 		}
16166 		if (! found) {
16167 		    xmlChar *str = NULL;
16168 
16169 		    xmlSchemaCustomErr(ACTXT_CAST ctxt,
16170 			XML_SCHEMAP_COS_CT_EXTENDS_1_2,
16171 			NULL, WXS_BASIC_CAST type,
16172 			/*
16173 			* TODO: The report does not indicate that also the
16174 			* type needs to be the same.
16175 			*/
16176 			"This type is missing a matching correspondent "
16177 			"for its {base type}'s %s in its {attribute uses}",
16178 			xmlSchemaGetComponentDesignation(&str,
16179 			    buse->children),
16180 			NULL);
16181 		    FREE_AND_NULL(str)
16182 		}
16183 	    }
16184 	}
16185 	/*
16186 	* SPEC (1.3) "If it has an {attribute wildcard}, the complex type
16187 	* definition must also have one, and the base type definition's
16188 	* {attribute  wildcard}'s {namespace constraint} must be a subset
16189 	* of the complex  type definition's {attribute wildcard}'s {namespace
16190 	* constraint}, as defined by Wildcard Subset (�3.10.6)."
16191 	*/
16192 
16193 	/*
16194 	* MAYBE TODO: Enable if ever needed. But this will be needed only
16195 	* if created the type via a schema construction API.
16196 	*/
16197 	if (base->attributeWildcard != NULL) {
16198 	    if (type->attributeWilcard == NULL) {
16199 		xmlChar *str = NULL;
16200 
16201 		xmlSchemaCustomErr(ACTXT_CAST pctxt,
16202 		    XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16203 		    NULL, type,
16204 		    "The base %s has an attribute wildcard, "
16205 		    "but this type is missing an attribute wildcard",
16206 		    xmlSchemaGetComponentDesignation(&str, base));
16207 		FREE_AND_NULL(str)
16208 
16209 	    } else if (xmlSchemaCheckCOSNSSubset(
16210 		base->attributeWildcard, type->attributeWildcard))
16211 	    {
16212 		xmlChar *str = NULL;
16213 
16214 		xmlSchemaCustomErr(ACTXT_CAST pctxt,
16215 		    XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16216 		    NULL, type,
16217 		    "The attribute wildcard is not a valid "
16218 		    "superset of the one in the base %s",
16219 		    xmlSchemaGetComponentDesignation(&str, base));
16220 		FREE_AND_NULL(str)
16221 	    }
16222 	}
16223 #endif
16224 	/*
16225 	* SPEC (1.4) "One of the following must be true:"
16226 	*/
16227 	if ((type->contentTypeDef != NULL) &&
16228 	    (type->contentTypeDef == base->contentTypeDef)) {
16229 	    /*
16230 	    * SPEC (1.4.1) "The {content type} of the {base type definition}
16231 	    * and the {content type} of the complex type definition itself
16232 	    * must be the same simple type definition"
16233 	    * PASS
16234 	    */
16235 	} else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
16236 	    (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
16237 	    /*
16238 	    * SPEC (1.4.2) "The {content type} of both the {base type
16239 	    * definition} and the complex type definition itself must
16240 	    * be empty."
16241 	    * PASS
16242 	    */
16243 	} else {
16244 	    /*
16245 	    * SPEC (1.4.3) "All of the following must be true:"
16246 	    */
16247 	    if (type->subtypes == NULL) {
16248 		/*
16249 		* SPEC 1.4.3.1 The {content type} of the complex type
16250 		* definition itself must specify a particle.
16251 		*/
16252 		xmlSchemaPCustomErr(ctxt,
16253 		    XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16254 		    WXS_BASIC_CAST type, NULL,
16255 		    "The content type must specify a particle", NULL);
16256 		return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16257 	    }
16258 	    /*
16259 	    * SPEC (1.4.3.2) "One of the following must be true:"
16260 	    */
16261 	    if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16262 		/*
16263 		* SPEC (1.4.3.2.1) "The {content type} of the {base type
16264 		* definition} must be empty.
16265 		* PASS
16266 		*/
16267 	    } else {
16268 		/*
16269 		* SPEC (1.4.3.2.2) "All of the following must be true:"
16270 		*/
16271 		if ((type->contentType != base->contentType) ||
16272 		    ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
16273 		    (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
16274 		    /*
16275 		    * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
16276 		    * or both must be element-only."
16277 		    */
16278 		    xmlSchemaPCustomErr(ctxt,
16279 			XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16280 			WXS_BASIC_CAST type, NULL,
16281 			"The content type of both, the type and its base "
16282 			"type, must either 'mixed' or 'element-only'", NULL);
16283 		    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16284 		}
16285 		/*
16286 		* URGENT TODO SPEC (1.4.3.2.2.2) "The particle of the
16287 		* complex type definition must be a �valid extension�
16288 		* of the {base type definition}'s particle, as defined
16289 		* in Particle Valid (Extension) (�3.9.6)."
16290 		*
16291 		* NOTE that we won't check "Particle Valid (Extension)",
16292 		* since it is ensured by the derivation process in
16293 		* xmlSchemaTypeFixup(). We need to implement this when heading
16294 		* for a construction API
16295 		* TODO: !! This is needed to be checked if redefining a type !!
16296 		*/
16297 	    }
16298 	    /*
16299 	    * URGENT TODO (1.5)
16300 	    */
16301 	}
16302     } else {
16303 	/*
16304 	* SPEC (2) "If the {base type definition} is a simple type definition,
16305 	* then all of the following must be true:"
16306 	*/
16307 	if (type->contentTypeDef != base) {
16308 	    /*
16309 	    * SPEC (2.1) "The {content type} must be the same simple type
16310 	    * definition."
16311 	    */
16312 	    xmlSchemaPCustomErr(ctxt,
16313 		XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16314 		WXS_BASIC_CAST type, NULL,
16315 		"The content type must be the simple base type", NULL);
16316 	    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16317 	}
16318 	if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16319 	    /*
16320 	    * SPEC (2.2) "The {final} of the {base type definition} must not
16321 	    * contain extension"
16322 	    * NOTE that this is the same as (1.1).
16323 	    */
16324 	    xmlSchemaPCustomErr(ctxt,
16325 		XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16326 		WXS_BASIC_CAST type, NULL,
16327 		"The 'final' of the base type definition "
16328 		"contains 'extension'", NULL);
16329 	    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16330 	}
16331     }
16332     return (0);
16333 }
16334 
16335 /**
16336  * xmlSchemaCheckDerivationOKRestriction:
16337  * @ctxt:  the schema parser context
16338  * @type:  the complex type definition
16339  *
16340  * (3.4.6) Constraints on Complex Type Definition Schema Components
16341  * Schema Component Constraint:
16342  * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
16343  *
16344  * STATUS:
16345  *   missing:
16346  *     (5.4.2) ???
16347  *
16348  * ATTENTION:
16349  * In XML Schema 1.1 this will be:
16350  * Validation Rule: Checking complex type subsumption
16351  *
16352  * Returns 0 if the constraints are satisfied, a positive
16353  * error code if not and -1 if an internal error occured.
16354  */
16355 static int
xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)16356 xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
16357 				      xmlSchemaTypePtr type)
16358 {
16359     xmlSchemaTypePtr base;
16360 
16361     /*
16362     * TODO: Correct the error code; XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1 is used
16363     * temporarily only.
16364     */
16365     base = type->baseType;
16366     if (! WXS_IS_COMPLEX(base)) {
16367 	xmlSchemaCustomErr(ACTXT_CAST ctxt,
16368 	    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16369 	    type->node, WXS_BASIC_CAST type,
16370 	    "The base type must be a complex type", NULL, NULL);
16371 	return(ctxt->err);
16372     }
16373     if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
16374 	/*
16375 	* SPEC (1) "The {base type definition} must be a complex type
16376 	* definition whose {final} does not contain restriction."
16377 	*/
16378 	xmlSchemaCustomErr(ACTXT_CAST ctxt,
16379 	    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16380 	    type->node, WXS_BASIC_CAST type,
16381 	    "The 'final' of the base type definition "
16382 	    "contains 'restriction'", NULL, NULL);
16383 	return (ctxt->err);
16384     }
16385     /*
16386     * SPEC (2), (3) and (4)
16387     * Those are handled in a separate function, since the
16388     * same constraints are needed for redefinition of
16389     * attribute groups as well.
16390     */
16391     if (xmlSchemaCheckDerivationOKRestriction2to4(ctxt,
16392 	XML_SCHEMA_ACTION_DERIVE,
16393 	WXS_BASIC_CAST type, WXS_BASIC_CAST base,
16394 	type->attrUses, base->attrUses,
16395 	type->attributeWildcard,
16396 	base->attributeWildcard) == -1)
16397     {
16398 	return(-1);
16399     }
16400     /*
16401     * SPEC (5) "One of the following must be true:"
16402     */
16403     if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
16404 	/*
16405 	* SPEC (5.1) "The {base type definition} must be the
16406 	* �ur-type definition�."
16407 	* PASS
16408 	*/
16409     } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16410 	    (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16411 	/*
16412 	* SPEC (5.2.1) "The {content type} of the complex type definition
16413 	* must be a simple type definition"
16414 	*
16415 	* SPEC (5.2.2) "One of the following must be true:"
16416 	*/
16417 	if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16418 	    (base->contentType == XML_SCHEMA_CONTENT_BASIC))
16419 	{
16420 	    int err;
16421 	    /*
16422 	    * SPEC (5.2.2.1) "The {content type} of the {base type
16423 	    * definition} must be a simple type definition from which
16424 	    * the {content type} is validly derived given the empty
16425 	    * set as defined in Type Derivation OK (Simple) (�3.14.6)."
16426 	    *
16427 	    * ATTENTION TODO: This seems not needed if the type implicitely
16428 	    * derived from the base type.
16429 	    *
16430 	    */
16431 	    err = xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST ctxt,
16432 		type->contentTypeDef, base->contentTypeDef, 0);
16433 	    if (err != 0) {
16434 		xmlChar *strA = NULL, *strB = NULL;
16435 
16436 		if (err == -1)
16437 		    return(-1);
16438 		xmlSchemaCustomErr(ACTXT_CAST ctxt,
16439 		    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16440 		    NULL, WXS_BASIC_CAST type,
16441 		    "The {content type} %s is not validly derived from the "
16442 		    "base type's {content type} %s",
16443 		    xmlSchemaGetComponentDesignation(&strA,
16444 			type->contentTypeDef),
16445 		    xmlSchemaGetComponentDesignation(&strB,
16446 			base->contentTypeDef));
16447 		FREE_AND_NULL(strA);
16448 		FREE_AND_NULL(strB);
16449 		return(ctxt->err);
16450 	    }
16451 	} else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16452 	    (xmlSchemaIsParticleEmptiable(
16453 		(xmlSchemaParticlePtr) base->subtypes))) {
16454 	    /*
16455 	    * SPEC (5.2.2.2) "The {base type definition} must be mixed
16456 	    * and have a particle which is �emptiable� as defined in
16457 	    * Particle Emptiable (�3.9.6)."
16458 	    * PASS
16459 	    */
16460 	} else {
16461 	    xmlSchemaPCustomErr(ctxt,
16462 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16463 		WXS_BASIC_CAST type, NULL,
16464 		"The content type of the base type must be either "
16465 		"a simple type or 'mixed' and an emptiable particle", NULL);
16466 	    return (ctxt->err);
16467 	}
16468     } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16469 	/*
16470 	* SPEC (5.3.1) "The {content type} of the complex type itself must
16471 	* be empty"
16472 	*/
16473 	if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16474 	    /*
16475 	    * SPEC (5.3.2.1) "The {content type} of the {base type
16476 	    * definition} must also be empty."
16477 	    * PASS
16478 	    */
16479 	} else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16480 	    (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
16481 	    xmlSchemaIsParticleEmptiable(
16482 		(xmlSchemaParticlePtr) base->subtypes)) {
16483 	    /*
16484 	    * SPEC (5.3.2.2) "The {content type} of the {base type
16485 	    * definition} must be elementOnly or mixed and have a particle
16486 	    * which is �emptiable� as defined in Particle Emptiable (�3.9.6)."
16487 	    * PASS
16488 	    */
16489 	} else {
16490 	    xmlSchemaPCustomErr(ctxt,
16491 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16492 		WXS_BASIC_CAST type, NULL,
16493 		"The content type of the base type must be either "
16494 		"empty or 'mixed' (or 'elements-only') and an emptiable "
16495 		"particle", NULL);
16496 	    return (ctxt->err);
16497 	}
16498     } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16499 	WXS_HAS_MIXED_CONTENT(type)) {
16500 	/*
16501 	* SPEC (5.4.1.1) "The {content type} of the complex type definition
16502 	* itself must be element-only"
16503 	*/
16504 	if (WXS_HAS_MIXED_CONTENT(type) && (! WXS_HAS_MIXED_CONTENT(base))) {
16505 	    /*
16506 	    * SPEC (5.4.1.2) "The {content type} of the complex type
16507 	    * definition itself and of the {base type definition} must be
16508 	    * mixed"
16509 	    */
16510 	    xmlSchemaPCustomErr(ctxt,
16511 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16512 		WXS_BASIC_CAST type, NULL,
16513 		"If the content type is 'mixed', then the content type of the "
16514 		"base type must also be 'mixed'", NULL);
16515 	    return (ctxt->err);
16516 	}
16517 	/*
16518 	* SPEC (5.4.2) "The particle of the complex type definition itself
16519 	* must be a �valid restriction� of the particle of the {content
16520 	* type} of the {base type definition} as defined in Particle Valid
16521 	* (Restriction) (�3.9.6).
16522 	*
16523 	* URGENT TODO: (5.4.2)
16524 	*/
16525     } else {
16526 	xmlSchemaPCustomErr(ctxt,
16527 	    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16528 	    WXS_BASIC_CAST type, NULL,
16529 	    "The type is not a valid restriction of its base type", NULL);
16530 	return (ctxt->err);
16531     }
16532     return (0);
16533 }
16534 
16535 /**
16536  * xmlSchemaCheckCTComponent:
16537  * @ctxt:  the schema parser context
16538  * @type:  the complex type definition
16539  *
16540  * (3.4.6) Constraints on Complex Type Definition Schema Components
16541  *
16542  * Returns 0 if the constraints are satisfied, a positive
16543  * error code if not and -1 if an internal error occured.
16544  */
16545 static int
xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)16546 xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
16547 			  xmlSchemaTypePtr type)
16548 {
16549     int ret;
16550     /*
16551     * Complex Type Definition Properties Correct
16552     */
16553     ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
16554     if (ret != 0)
16555 	return (ret);
16556     if (WXS_IS_EXTENSION(type))
16557 	ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
16558     else
16559 	ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
16560     return (ret);
16561 }
16562 
16563 /**
16564  * xmlSchemaCheckSRCCT:
16565  * @ctxt:  the schema parser context
16566  * @type:  the complex type definition
16567  *
16568  * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
16569  * Schema Representation Constraint:
16570  * Complex Type Definition Representation OK (src-ct)
16571  *
16572  * Returns 0 if the constraints are satisfied, a positive
16573  * error code if not and -1 if an internal error occured.
16574  */
16575 static int
xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)16576 xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
16577 		    xmlSchemaTypePtr type)
16578 {
16579     xmlSchemaTypePtr base;
16580     int ret = 0;
16581 
16582     /*
16583     * TODO: Adjust the error codes here, as I used
16584     * XML_SCHEMAP_SRC_CT_1 only yet.
16585     */
16586     base = type->baseType;
16587     if (! WXS_HAS_SIMPLE_CONTENT(type)) {
16588 	/*
16589 	* 1 If the <complexContent> alternative is chosen, the type definition
16590 	* �resolved� to by the �actual value� of the base [attribute]
16591 	* must be a complex type definition;
16592 	*/
16593 	if (! WXS_IS_COMPLEX(base)) {
16594 	    xmlChar *str = NULL;
16595 	    xmlSchemaPCustomErr(ctxt,
16596 		XML_SCHEMAP_SRC_CT_1,
16597 		WXS_BASIC_CAST type, type->node,
16598 		"If using <complexContent>, the base type is expected to be "
16599 		"a complex type. The base type '%s' is a simple type",
16600 		xmlSchemaFormatQName(&str, base->targetNamespace,
16601 		base->name));
16602 	    FREE_AND_NULL(str)
16603 	    return (XML_SCHEMAP_SRC_CT_1);
16604 	}
16605     } else {
16606 	/*
16607 	* SPEC
16608 	* 2 If the <simpleContent> alternative is chosen, all of the
16609 	* following must be true:
16610 	* 2.1 The type definition �resolved� to by the �actual value� of the
16611 	* base [attribute] must be one of the following:
16612 	*/
16613 	if (WXS_IS_SIMPLE(base)) {
16614 	    if (WXS_IS_EXTENSION(type) == 0) {
16615 		xmlChar *str = NULL;
16616 		/*
16617 		* 2.1.3 only if the <extension> alternative is also
16618 		* chosen, a simple type definition.
16619 		*/
16620 		/* TODO: Change error code to ..._SRC_CT_2_1_3. */
16621 		xmlSchemaPCustomErr(ctxt,
16622 		    XML_SCHEMAP_SRC_CT_1,
16623 		    WXS_BASIC_CAST type, NULL,
16624 		    "If using <simpleContent> and <restriction>, the base "
16625 		    "type must be a complex type. The base type '%s' is "
16626 		    "a simple type",
16627 		    xmlSchemaFormatQName(&str, base->targetNamespace,
16628 			base->name));
16629 		FREE_AND_NULL(str)
16630 		return (XML_SCHEMAP_SRC_CT_1);
16631 	    }
16632 	} else {
16633 	    /* Base type is a complex type. */
16634 	    if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16635 		(base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16636 		/*
16637 		* 2.1.1 a complex type definition whose {content type} is a
16638 		* simple type definition;
16639 		* PASS
16640 		*/
16641 		if (base->contentTypeDef == NULL) {
16642 		    xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
16643 			WXS_BASIC_CAST type, NULL,
16644 			"Internal error: xmlSchemaCheckSRCCT, "
16645 			"'%s', base type has no content type",
16646 			type->name);
16647 		    return (-1);
16648 		}
16649 	    } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16650 		(WXS_IS_RESTRICTION(type))) {
16651 
16652 		/*
16653 		* 2.1.2 only if the <restriction> alternative is also
16654 		* chosen, a complex type definition whose {content type}
16655 		* is mixed and a particle emptiable.
16656 		*/
16657 		if (! xmlSchemaIsParticleEmptiable(
16658 		    (xmlSchemaParticlePtr) base->subtypes)) {
16659 		    ret = XML_SCHEMAP_SRC_CT_1;
16660 		} else
16661 		    /*
16662 		    * Attention: at this point the <simpleType> child is in
16663 		    * ->contentTypeDef (put there during parsing).
16664 		    */
16665 		    if (type->contentTypeDef == NULL) {
16666 		    xmlChar *str = NULL;
16667 		    /*
16668 		    * 2.2 If clause 2.1.2 above is satisfied, then there
16669 		    * must be a <simpleType> among the [children] of
16670 		    * <restriction>.
16671 		    */
16672 		    /* TODO: Change error code to ..._SRC_CT_2_2. */
16673 		    xmlSchemaPCustomErr(ctxt,
16674 			XML_SCHEMAP_SRC_CT_1,
16675 			WXS_BASIC_CAST type, NULL,
16676 			"A <simpleType> is expected among the children "
16677 			"of <restriction>, if <simpleContent> is used and "
16678 			"the base type '%s' is a complex type",
16679 			xmlSchemaFormatQName(&str, base->targetNamespace,
16680 			base->name));
16681 		    FREE_AND_NULL(str)
16682 		    return (XML_SCHEMAP_SRC_CT_1);
16683 		}
16684 	    } else {
16685 		ret = XML_SCHEMAP_SRC_CT_1;
16686 	    }
16687 	}
16688 	if (ret > 0) {
16689 	    xmlChar *str = NULL;
16690 	    if (WXS_IS_RESTRICTION(type)) {
16691 		xmlSchemaPCustomErr(ctxt,
16692 		    XML_SCHEMAP_SRC_CT_1,
16693 		    WXS_BASIC_CAST type, NULL,
16694 		    "If <simpleContent> and <restriction> is used, the "
16695 		    "base type must be a simple type or a complex type with "
16696 		    "mixed content and particle emptiable. The base type "
16697 		    "'%s' is none of those",
16698 		    xmlSchemaFormatQName(&str, base->targetNamespace,
16699 		    base->name));
16700 	    } else {
16701 		xmlSchemaPCustomErr(ctxt,
16702 		    XML_SCHEMAP_SRC_CT_1,
16703 		    WXS_BASIC_CAST type, NULL,
16704 		    "If <simpleContent> and <extension> is used, the "
16705 		    "base type must be a simple type. The base type '%s' "
16706 		    "is a complex type",
16707 		    xmlSchemaFormatQName(&str, base->targetNamespace,
16708 		    base->name));
16709 	    }
16710 	    FREE_AND_NULL(str)
16711 	}
16712     }
16713     /*
16714     * SPEC (3) "The corresponding complex type definition component must
16715     * satisfy the conditions set out in Constraints on Complex Type
16716     * Definition Schema Components (�3.4.6);"
16717     * NOTE (3) will be done in xmlSchemaTypeFixup().
16718     */
16719     /*
16720     * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
16721     * above for {attribute wildcard} is satisfied, the intensional
16722     * intersection must be expressible, as defined in Attribute Wildcard
16723     * Intersection (�3.10.6).
16724     * NOTE (4) is done in xmlSchemaFixupTypeAttributeUses().
16725     */
16726     return (ret);
16727 }
16728 
16729 #ifdef ENABLE_PARTICLE_RESTRICTION
16730 /**
16731  * xmlSchemaCheckParticleRangeOK:
16732  * @ctxt:  the schema parser context
16733  * @type:  the complex type definition
16734  *
16735  * (3.9.6) Constraints on Particle Schema Components
16736  * Schema Component Constraint:
16737  * Occurrence Range OK (range-ok)
16738  *
16739  * STATUS: complete
16740  *
16741  * Returns 0 if the constraints are satisfied, a positive
16742  * error code if not and -1 if an internal error occured.
16743  */
16744 static int
xmlSchemaCheckParticleRangeOK(int rmin,int rmax,int bmin,int bmax)16745 xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
16746 			      int bmin, int bmax)
16747 {
16748     if (rmin < bmin)
16749 	return (1);
16750     if ((bmax != UNBOUNDED) &&
16751 	(rmax > bmax))
16752 	return (1);
16753     return (0);
16754 }
16755 
16756 /**
16757  * xmlSchemaCheckRCaseNameAndTypeOK:
16758  * @ctxt:  the schema parser context
16759  * @r: the restricting element declaration particle
16760  * @b: the base element declaration particle
16761  *
16762  * (3.9.6) Constraints on Particle Schema Components
16763  * Schema Component Constraint:
16764  * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
16765  * (rcase-NameAndTypeOK)
16766  *
16767  * STATUS:
16768  *   MISSING (3.2.3)
16769  *   CLARIFY: (3.2.2)
16770  *
16771  * Returns 0 if the constraints are satisfied, a positive
16772  * error code if not and -1 if an internal error occured.
16773  */
16774 static int
xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)16775 xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
16776 				 xmlSchemaParticlePtr r,
16777 				 xmlSchemaParticlePtr b)
16778 {
16779     xmlSchemaElementPtr elemR, elemB;
16780 
16781     /* TODO: Error codes (rcase-NameAndTypeOK). */
16782     elemR = (xmlSchemaElementPtr) r->children;
16783     elemB = (xmlSchemaElementPtr) b->children;
16784     /*
16785     * SPEC (1) "The declarations' {name}s and {target namespace}s are
16786     * the same."
16787     */
16788     if ((elemR != elemB) &&
16789 	((! xmlStrEqual(elemR->name, elemB->name)) ||
16790 	(! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
16791 	return (1);
16792     /*
16793     * SPEC (2) "R's occurrence range is a valid restriction of B's
16794     * occurrence range as defined by Occurrence Range OK (�3.9.6)."
16795     */
16796     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16797 	    b->minOccurs, b->maxOccurs) != 0)
16798 	return (1);
16799     /*
16800     * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
16801     * {scope} are global."
16802     */
16803     if (elemR == elemB)
16804 	return (0);
16805     /*
16806     * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
16807     */
16808     if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
16809 	(elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
16810 	 return (1);
16811     /*
16812     * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
16813     * or is not fixed, or R's declaration's {value constraint} is fixed
16814     * with the same value."
16815     */
16816     if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
16817 	((elemR->value == NULL) ||
16818 	 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
16819 	 /* TODO: Equality of the initial value or normalized or canonical? */
16820 	 (! xmlStrEqual(elemR->value, elemB->value))))
16821 	 return (1);
16822     /*
16823     * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
16824     * definitions} is a subset of B's declaration's {identity-constraint
16825     * definitions}, if any."
16826     */
16827     if (elemB->idcs != NULL) {
16828 	/* TODO */
16829     }
16830     /*
16831     * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
16832     * superset of B's declaration's {disallowed substitutions}."
16833     */
16834     if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
16835 	 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
16836 	((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
16837 	 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
16838 	((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
16839 	 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
16840 	 return (1);
16841     /*
16842     * SPEC (3.2.5) "R's {type definition} is validly derived given
16843     * {extension, list, union} from B's {type definition}"
16844     *
16845     * BADSPEC TODO: What's the point of adding "list" and "union" to the
16846     * set, if the corresponding constraints handle "restriction" and
16847     * "extension" only?
16848     *
16849     */
16850     {
16851 	int set = 0;
16852 
16853 	set |= SUBSET_EXTENSION;
16854 	set |= SUBSET_LIST;
16855 	set |= SUBSET_UNION;
16856 	if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST ctxt, elemR->subtypes,
16857 	    elemB->subtypes, set) != 0)
16858 	    return (1);
16859     }
16860     return (0);
16861 }
16862 
16863 /**
16864  * xmlSchemaCheckRCaseNSCompat:
16865  * @ctxt:  the schema parser context
16866  * @r: the restricting element declaration particle
16867  * @b: the base wildcard particle
16868  *
16869  * (3.9.6) Constraints on Particle Schema Components
16870  * Schema Component Constraint:
16871  * Particle Derivation OK (Elt:Any -- NSCompat)
16872  * (rcase-NSCompat)
16873  *
16874  * STATUS: complete
16875  *
16876  * Returns 0 if the constraints are satisfied, a positive
16877  * error code if not and -1 if an internal error occured.
16878  */
16879 static int
xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)16880 xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
16881 			    xmlSchemaParticlePtr r,
16882 			    xmlSchemaParticlePtr b)
16883 {
16884     /* TODO:Error codes (rcase-NSCompat). */
16885     /*
16886     * SPEC "For an element declaration particle to be a �valid restriction�
16887     * of a wildcard particle all of the following must be true:"
16888     *
16889     * SPEC (1) "The element declaration's {target namespace} is �valid�
16890     * with respect to the wildcard's {namespace constraint} as defined by
16891     * Wildcard allows Namespace Name (�3.10.4)."
16892     */
16893     if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
16894 	((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
16895 	return (1);
16896     /*
16897     * SPEC (2) "R's occurrence range is a valid restriction of B's
16898     * occurrence range as defined by Occurrence Range OK (�3.9.6)."
16899     */
16900     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16901 	    b->minOccurs, b->maxOccurs) != 0)
16902 	return (1);
16903 
16904     return (0);
16905 }
16906 
16907 /**
16908  * xmlSchemaCheckRCaseRecurseAsIfGroup:
16909  * @ctxt:  the schema parser context
16910  * @r: the restricting element declaration particle
16911  * @b: the base model group particle
16912  *
16913  * (3.9.6) Constraints on Particle Schema Components
16914  * Schema Component Constraint:
16915  * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
16916  * (rcase-RecurseAsIfGroup)
16917  *
16918  * STATUS: TODO
16919  *
16920  * Returns 0 if the constraints are satisfied, a positive
16921  * error code if not and -1 if an internal error occured.
16922  */
16923 static int
xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)16924 xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
16925 				    xmlSchemaParticlePtr r,
16926 				    xmlSchemaParticlePtr b)
16927 {
16928     /* TODO: Error codes (rcase-RecurseAsIfGroup). */
16929     TODO
16930     return (0);
16931 }
16932 
16933 /**
16934  * xmlSchemaCheckRCaseNSSubset:
16935  * @ctxt:  the schema parser context
16936  * @r: the restricting wildcard particle
16937  * @b: the base wildcard particle
16938  *
16939  * (3.9.6) Constraints on Particle Schema Components
16940  * Schema Component Constraint:
16941  * Particle Derivation OK (Any:Any -- NSSubset)
16942  * (rcase-NSSubset)
16943  *
16944  * STATUS: complete
16945  *
16946  * Returns 0 if the constraints are satisfied, a positive
16947  * error code if not and -1 if an internal error occured.
16948  */
16949 static int
xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b,int isAnyTypeBase)16950 xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
16951 				    xmlSchemaParticlePtr r,
16952 				    xmlSchemaParticlePtr b,
16953 				    int isAnyTypeBase)
16954 {
16955     /* TODO: Error codes (rcase-NSSubset). */
16956     /*
16957     * SPEC (1) "R's occurrence range is a valid restriction of B's
16958     * occurrence range as defined by Occurrence Range OK (�3.9.6)."
16959     */
16960     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16961 	    b->minOccurs, b->maxOccurs))
16962 	return (1);
16963     /*
16964     * SPEC (2) "R's {namespace constraint} must be an intensional subset
16965     * of B's {namespace constraint} as defined by Wildcard Subset (�3.10.6)."
16966     */
16967     if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
16968 	(xmlSchemaWildcardPtr) b->children))
16969 	return (1);
16970     /*
16971     * SPEC (3) "Unless B is the content model wildcard of the �ur-type
16972     * definition�, R's {process contents} must be identical to or stronger
16973     * than B's {process contents}, where strict is stronger than lax is
16974     * stronger than skip."
16975     */
16976     if (! isAnyTypeBase) {
16977 	if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
16978 	    ((xmlSchemaWildcardPtr) b->children)->processContents)
16979 	    return (1);
16980     }
16981 
16982     return (0);
16983 }
16984 
16985 /**
16986  * xmlSchemaCheckCOSParticleRestrict:
16987  * @ctxt:  the schema parser context
16988  * @type:  the complex type definition
16989  *
16990  * (3.9.6) Constraints on Particle Schema Components
16991  * Schema Component Constraint:
16992  * Particle Valid (Restriction) (cos-particle-restrict)
16993  *
16994  * STATUS: TODO
16995  *
16996  * Returns 0 if the constraints are satisfied, a positive
16997  * error code if not and -1 if an internal error occured.
16998  */
16999 static int
xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)17000 xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
17001 				  xmlSchemaParticlePtr r,
17002 				  xmlSchemaParticlePtr b)
17003 {
17004     int ret = 0;
17005 
17006     /*part = WXS_TYPE_PARTICLE(type);
17007     basePart = WXS_TYPE_PARTICLE(base);
17008     */
17009 
17010     TODO
17011 
17012     /*
17013     * SPEC (1) "They are the same particle."
17014     */
17015     if (r == b)
17016 	return (0);
17017 
17018 
17019     return (0);
17020 }
17021 
17022 #if 0
17023 /**
17024  * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
17025  * @ctxt:  the schema parser context
17026  * @r: the model group particle
17027  * @b: the base wildcard particle
17028  *
17029  * (3.9.6) Constraints on Particle Schema Components
17030  * Schema Component Constraint:
17031  * Particle Derivation OK (All/Choice/Sequence:Any --
17032  *                         NSRecurseCheckCardinality)
17033  * (rcase-NSRecurseCheckCardinality)
17034  *
17035  * STATUS: TODO: subst-groups
17036  *
17037  * Returns 0 if the constraints are satisfied, a positive
17038  * error code if not and -1 if an internal error occured.
17039  */
17040 static int
17041 xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
17042 					     xmlSchemaParticlePtr r,
17043 					     xmlSchemaParticlePtr b)
17044 {
17045     xmlSchemaParticlePtr part;
17046     /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
17047     if ((r->children == NULL) || (r->children->children == NULL))
17048 	return (-1);
17049     /*
17050     * SPEC "For a group particle to be a �valid restriction� of a
17051     * wildcard particle..."
17052     *
17053     * SPEC (1) "Every member of the {particles} of the group is a �valid
17054     * restriction� of the wildcard as defined by
17055     * Particle Valid (Restriction) (�3.9.6)."
17056     */
17057     part = (xmlSchemaParticlePtr) r->children->children;
17058     do {
17059 	if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
17060 	    return (1);
17061 	part = (xmlSchemaParticlePtr) part->next;
17062     } while (part != NULL);
17063     /*
17064     * SPEC (2) "The effective total range of the group [...] is a
17065     * valid restriction of B's occurrence range as defined by
17066     * Occurrence Range OK (�3.9.6)."
17067     */
17068     if (xmlSchemaCheckParticleRangeOK(
17069 	    xmlSchemaGetParticleTotalRangeMin(r),
17070 	    xmlSchemaGetParticleTotalRangeMax(r),
17071 	    b->minOccurs, b->maxOccurs) != 0)
17072 	return (1);
17073     return (0);
17074 }
17075 #endif
17076 
17077 /**
17078  * xmlSchemaCheckRCaseRecurse:
17079  * @ctxt:  the schema parser context
17080  * @r: the <all> or <sequence> model group particle
17081  * @b: the base <all> or <sequence> model group particle
17082  *
17083  * (3.9.6) Constraints on Particle Schema Components
17084  * Schema Component Constraint:
17085  * Particle Derivation OK (All:All,Sequence:Sequence --
17086                            Recurse)
17087  * (rcase-Recurse)
17088  *
17089  * STATUS:  ?
17090  * TODO: subst-groups
17091  *
17092  * Returns 0 if the constraints are satisfied, a positive
17093  * error code if not and -1 if an internal error occured.
17094  */
17095 static int
xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)17096 xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
17097 			   xmlSchemaParticlePtr r,
17098 			   xmlSchemaParticlePtr b)
17099 {
17100     /* xmlSchemaParticlePtr part; */
17101     /* TODO: Error codes (rcase-Recurse). */
17102     if ((r->children == NULL) || (b->children == NULL) ||
17103 	(r->children->type != b->children->type))
17104 	return (-1);
17105     /*
17106     * SPEC "For an all or sequence group particle to be a �valid
17107     * restriction� of another group particle with the same {compositor}..."
17108     *
17109     * SPEC (1) "R's occurrence range is a valid restriction of B's
17110     * occurrence range as defined by Occurrence Range OK (�3.9.6)."
17111     */
17112     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17113 	    b->minOccurs, b->maxOccurs))
17114 	return (1);
17115 
17116 
17117     return (0);
17118 }
17119 
17120 #endif
17121 
17122 #define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
17123     xmlSchemaPCustomErrExt(pctxt,      \
17124 	XML_SCHEMAP_INVALID_FACET_VALUE, \
17125 	WXS_BASIC_CAST fac1, fac1->node, \
17126 	"It is an error for both '%s' and '%s' to be specified on the "\
17127 	"same type definition", \
17128 	BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
17129 	BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
17130 
17131 #define FACET_RESTR_ERR(fac1, msg) \
17132     xmlSchemaPCustomErr(pctxt,      \
17133 	XML_SCHEMAP_INVALID_FACET_VALUE, \
17134 	WXS_BASIC_CAST fac1, fac1->node, \
17135 	msg, NULL);
17136 
17137 #define FACET_RESTR_FIXED_ERR(fac) \
17138     xmlSchemaPCustomErr(pctxt, \
17139 	XML_SCHEMAP_INVALID_FACET_VALUE, \
17140 	WXS_BASIC_CAST fac, fac->node, \
17141 	"The base type's facet is 'fixed', thus the value must not " \
17142 	"differ", NULL);
17143 
17144 static void
xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,xmlSchemaFacetPtr facet1,xmlSchemaFacetPtr facet2,int lessGreater,int orEqual,int ofBase)17145 xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
17146 			xmlSchemaFacetPtr facet1,
17147 			xmlSchemaFacetPtr facet2,
17148 			int lessGreater,
17149 			int orEqual,
17150 			int ofBase)
17151 {
17152     xmlChar *msg = NULL;
17153 
17154     msg = xmlStrdup(BAD_CAST "'");
17155     msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
17156     msg = xmlStrcat(msg, BAD_CAST "' has to be");
17157     if (lessGreater == 0)
17158 	msg = xmlStrcat(msg, BAD_CAST " equal to");
17159     if (lessGreater == 1)
17160 	msg = xmlStrcat(msg, BAD_CAST " greater than");
17161     else
17162 	msg = xmlStrcat(msg, BAD_CAST " less than");
17163 
17164     if (orEqual)
17165 	msg = xmlStrcat(msg, BAD_CAST " or equal to");
17166     msg = xmlStrcat(msg, BAD_CAST " '");
17167     msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
17168     if (ofBase)
17169 	msg = xmlStrcat(msg, BAD_CAST "' of the base type");
17170     else
17171 	msg = xmlStrcat(msg, BAD_CAST "'");
17172 
17173     xmlSchemaPCustomErr(pctxt,
17174 	XML_SCHEMAP_INVALID_FACET_VALUE,
17175 	WXS_BASIC_CAST facet1, NULL,
17176 	(const char *) msg, NULL);
17177 
17178     if (msg != NULL)
17179 	xmlFree(msg);
17180 }
17181 
17182 /*
17183 * xmlSchemaDeriveAndValidateFacets:
17184 *
17185 * Schema Component Constraint: Simple Type Restriction (Facets)
17186 * (st-restrict-facets)
17187 */
17188 static int
xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)17189 xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
17190 				 xmlSchemaTypePtr type)
17191 {
17192     xmlSchemaTypePtr base = type->baseType;
17193     xmlSchemaFacetLinkPtr link, cur, last = NULL;
17194     xmlSchemaFacetPtr facet, bfacet,
17195 	flength = NULL, ftotdig = NULL, ffracdig = NULL,
17196 	fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
17197 	fmininc = NULL, fmaxinc = NULL,
17198 	fminexc = NULL, fmaxexc = NULL,
17199 	bflength = NULL, bftotdig = NULL, bffracdig = NULL,
17200 	bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
17201 	bfmininc = NULL, bfmaxinc = NULL,
17202 	bfminexc = NULL, bfmaxexc = NULL;
17203     int res; /* err = 0, fixedErr; */
17204 
17205     /*
17206     * SPEC st-restrict-facets 1:
17207     * "The {variety} of R is the same as that of B."
17208     */
17209     /*
17210     * SPEC st-restrict-facets 2:
17211     * "If {variety} is atomic, the {primitive type definition}
17212     * of R is the same as that of B."
17213     *
17214     * NOTE: we leave 1 & 2 out for now, since this will be
17215     * satisfied by the derivation process.
17216     * CONSTRUCTION TODO: Maybe needed if using a construction API.
17217     */
17218     /*
17219     * SPEC st-restrict-facets 3:
17220     * "The {facets} of R are the union of S and the {facets}
17221     * of B, eliminating duplicates. To eliminate duplicates,
17222     * when a facet of the same kind occurs in both S and the
17223     * {facets} of B, the one in the {facets} of B is not
17224     * included, with the exception of enumeration and pattern
17225     * facets, for which multiple occurrences with distinct values
17226     * are allowed."
17227     */
17228 
17229     if ((type->facetSet == NULL) && (base->facetSet == NULL))
17230 	return (0);
17231 
17232     last = type->facetSet;
17233     if (last != NULL)
17234 	while (last->next != NULL)
17235 	    last = last->next;
17236 
17237     for (cur = type->facetSet; cur != NULL; cur = cur->next) {
17238 	facet = cur->facet;
17239 	switch (facet->type) {
17240 	    case XML_SCHEMA_FACET_LENGTH:
17241 		flength = facet; break;
17242 	    case XML_SCHEMA_FACET_MINLENGTH:
17243 		fminlen = facet; break;
17244 	    case XML_SCHEMA_FACET_MININCLUSIVE:
17245 		fmininc = facet; break;
17246 	    case XML_SCHEMA_FACET_MINEXCLUSIVE:
17247 		fminexc = facet; break;
17248 	    case XML_SCHEMA_FACET_MAXLENGTH:
17249 		fmaxlen = facet; break;
17250 	    case XML_SCHEMA_FACET_MAXINCLUSIVE:
17251 		fmaxinc = facet; break;
17252 	    case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17253 		fmaxexc = facet; break;
17254 	    case XML_SCHEMA_FACET_TOTALDIGITS:
17255 		ftotdig = facet; break;
17256 	    case XML_SCHEMA_FACET_FRACTIONDIGITS:
17257 		ffracdig = facet; break;
17258 	    default:
17259 		break;
17260 	}
17261     }
17262     for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17263 	facet = cur->facet;
17264 	switch (facet->type) {
17265 	    case XML_SCHEMA_FACET_LENGTH:
17266 		bflength = facet; break;
17267 	    case XML_SCHEMA_FACET_MINLENGTH:
17268 		bfminlen = facet; break;
17269 	    case XML_SCHEMA_FACET_MININCLUSIVE:
17270 		bfmininc = facet; break;
17271 	    case XML_SCHEMA_FACET_MINEXCLUSIVE:
17272 		bfminexc = facet; break;
17273 	    case XML_SCHEMA_FACET_MAXLENGTH:
17274 		bfmaxlen = facet; break;
17275 	    case XML_SCHEMA_FACET_MAXINCLUSIVE:
17276 		bfmaxinc = facet; break;
17277 	    case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17278 		bfmaxexc = facet; break;
17279 	    case XML_SCHEMA_FACET_TOTALDIGITS:
17280 		bftotdig = facet; break;
17281 	    case XML_SCHEMA_FACET_FRACTIONDIGITS:
17282 		bffracdig = facet; break;
17283 	    default:
17284 		break;
17285 	}
17286     }
17287     /*
17288     * length and minLength or maxLength (2.2) + (3.2)
17289     */
17290     if (flength && (fminlen || fmaxlen)) {
17291 	FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
17292 	    "either of 'minLength' or 'maxLength' to be specified on "
17293 	    "the same type definition")
17294     }
17295     /*
17296     * Mutual exclusions in the same derivation step.
17297     */
17298     if ((fmaxinc) && (fmaxexc)) {
17299 	/*
17300 	* SCC "maxInclusive and maxExclusive"
17301 	*/
17302 	FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
17303     }
17304     if ((fmininc) && (fminexc)) {
17305 	/*
17306 	* SCC "minInclusive and minExclusive"
17307 	*/
17308 	FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
17309     }
17310 
17311     if (flength && bflength) {
17312 	/*
17313 	* SCC "length valid restriction"
17314 	* The values have to be equal.
17315 	*/
17316 	res = xmlSchemaCompareValues(flength->val, bflength->val);
17317 	if (res == -2)
17318 	    goto internal_error;
17319 	if (res != 0)
17320 	    xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
17321 	if ((res != 0) && (bflength->fixed)) {
17322 	    FACET_RESTR_FIXED_ERR(flength)
17323 	}
17324 
17325     }
17326     if (fminlen && bfminlen) {
17327 	/*
17328 	* SCC "minLength valid restriction"
17329 	* minLength >= BASE minLength
17330 	*/
17331 	res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
17332 	if (res == -2)
17333 	    goto internal_error;
17334 	if (res == -1)
17335 	    xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
17336 	if ((res != 0) && (bfminlen->fixed)) {
17337 	    FACET_RESTR_FIXED_ERR(fminlen)
17338 	}
17339     }
17340     if (fmaxlen && bfmaxlen) {
17341 	/*
17342 	* SCC "maxLength valid restriction"
17343 	* maxLength <= BASE minLength
17344 	*/
17345 	res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
17346 	if (res == -2)
17347 	    goto internal_error;
17348 	if (res == 1)
17349 	    xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
17350 	if ((res != 0) && (bfmaxlen->fixed)) {
17351 	    FACET_RESTR_FIXED_ERR(fmaxlen)
17352 	}
17353     }
17354     /*
17355     * SCC "length and minLength or maxLength"
17356     */
17357     if (! flength)
17358 	flength = bflength;
17359     if (flength) {
17360 	if (! fminlen)
17361 	    fminlen = bfminlen;
17362 	if (fminlen) {
17363 	    /* (1.1) length >= minLength */
17364 	    res = xmlSchemaCompareValues(flength->val, fminlen->val);
17365 	    if (res == -2)
17366 		goto internal_error;
17367 	    if (res == -1)
17368 		xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
17369 	}
17370 	if (! fmaxlen)
17371 	    fmaxlen = bfmaxlen;
17372 	if (fmaxlen) {
17373 	    /* (2.1) length <= maxLength */
17374 	    res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
17375 	    if (res == -2)
17376 		goto internal_error;
17377 	    if (res == 1)
17378 		xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
17379 	}
17380     }
17381     if (fmaxinc) {
17382 	/*
17383 	* "maxInclusive"
17384 	*/
17385 	if (fmininc) {
17386 	    /* SCC "maxInclusive >= minInclusive" */
17387 	    res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
17388 	    if (res == -2)
17389 		goto internal_error;
17390 	    if (res == -1) {
17391 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
17392 	    }
17393 	}
17394 	/*
17395 	* SCC "maxInclusive valid restriction"
17396 	*/
17397 	if (bfmaxinc) {
17398 	    /* maxInclusive <= BASE maxInclusive */
17399 	    res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
17400 	    if (res == -2)
17401 		goto internal_error;
17402 	    if (res == 1)
17403 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
17404 	    if ((res != 0) && (bfmaxinc->fixed)) {
17405 		FACET_RESTR_FIXED_ERR(fmaxinc)
17406 	    }
17407 	}
17408 	if (bfmaxexc) {
17409 	    /* maxInclusive < BASE maxExclusive */
17410 	    res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
17411 	    if (res == -2)
17412 		goto internal_error;
17413 	    if (res != -1) {
17414 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
17415 	    }
17416 	}
17417 	if (bfmininc) {
17418 	    /* maxInclusive >= BASE minInclusive */
17419 	    res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
17420 	    if (res == -2)
17421 		goto internal_error;
17422 	    if (res == -1) {
17423 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
17424 	    }
17425 	}
17426 	if (bfminexc) {
17427 	    /* maxInclusive > BASE minExclusive */
17428 	    res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
17429 	    if (res == -2)
17430 		goto internal_error;
17431 	    if (res != 1) {
17432 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
17433 	    }
17434 	}
17435     }
17436     if (fmaxexc) {
17437 	/*
17438 	* "maxExclusive >= minExclusive"
17439 	*/
17440 	if (fminexc) {
17441 	    res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
17442 	    if (res == -2)
17443 		goto internal_error;
17444 	    if (res == -1) {
17445 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
17446 	    }
17447 	}
17448 	/*
17449 	* "maxExclusive valid restriction"
17450 	*/
17451 	if (bfmaxexc) {
17452 	    /* maxExclusive <= BASE maxExclusive */
17453 	    res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
17454 	    if (res == -2)
17455 		goto internal_error;
17456 	    if (res == 1) {
17457 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
17458 	    }
17459 	    if ((res != 0) && (bfmaxexc->fixed)) {
17460 		FACET_RESTR_FIXED_ERR(fmaxexc)
17461 	    }
17462 	}
17463 	if (bfmaxinc) {
17464 	    /* maxExclusive <= BASE maxInclusive */
17465 	    res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
17466 	    if (res == -2)
17467 		goto internal_error;
17468 	    if (res == 1) {
17469 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
17470 	    }
17471 	}
17472 	if (bfmininc) {
17473 	    /* maxExclusive > BASE minInclusive */
17474 	    res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
17475 	    if (res == -2)
17476 		goto internal_error;
17477 	    if (res != 1) {
17478 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
17479 	    }
17480 	}
17481 	if (bfminexc) {
17482 	    /* maxExclusive > BASE minExclusive */
17483 	    res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
17484 	    if (res == -2)
17485 		goto internal_error;
17486 	    if (res != 1) {
17487 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
17488 	    }
17489 	}
17490     }
17491     if (fminexc) {
17492 	/*
17493 	* "minExclusive < maxInclusive"
17494 	*/
17495 	if (fmaxinc) {
17496 	    res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
17497 	    if (res == -2)
17498 		goto internal_error;
17499 	    if (res != -1) {
17500 		xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
17501 	    }
17502 	}
17503 	/*
17504 	* "minExclusive valid restriction"
17505 	*/
17506 	if (bfminexc) {
17507 	    /* minExclusive >= BASE minExclusive */
17508 	    res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
17509 	    if (res == -2)
17510 		goto internal_error;
17511 	    if (res == -1) {
17512 		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
17513 	    }
17514 	    if ((res != 0) && (bfminexc->fixed)) {
17515 		FACET_RESTR_FIXED_ERR(fminexc)
17516 	    }
17517 	}
17518 	if (bfmaxinc) {
17519 	    /* minExclusive <= BASE maxInclusive */
17520 	    res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
17521 	    if (res == -2)
17522 		goto internal_error;
17523 	    if (res == 1) {
17524 		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
17525 	    }
17526 	}
17527 	if (bfmininc) {
17528 	    /* minExclusive >= BASE minInclusive */
17529 	    res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
17530 	    if (res == -2)
17531 		goto internal_error;
17532 	    if (res == -1) {
17533 		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
17534 	    }
17535 	}
17536 	if (bfmaxexc) {
17537 	    /* minExclusive < BASE maxExclusive */
17538 	    res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
17539 	    if (res == -2)
17540 		goto internal_error;
17541 	    if (res != -1) {
17542 		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
17543 	    }
17544 	}
17545     }
17546     if (fmininc) {
17547 	/*
17548 	* "minInclusive < maxExclusive"
17549 	*/
17550 	if (fmaxexc) {
17551 	    res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
17552 	    if (res == -2)
17553 		goto internal_error;
17554 	    if (res != -1) {
17555 		xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
17556 	    }
17557 	}
17558 	/*
17559 	* "minExclusive valid restriction"
17560 	*/
17561 	if (bfmininc) {
17562 	    /* minInclusive >= BASE minInclusive */
17563 	    res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
17564 	    if (res == -2)
17565 		goto internal_error;
17566 	    if (res == -1) {
17567 		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
17568 	    }
17569 	    if ((res != 0) && (bfmininc->fixed)) {
17570 		FACET_RESTR_FIXED_ERR(fmininc)
17571 	    }
17572 	}
17573 	if (bfmaxinc) {
17574 	    /* minInclusive <= BASE maxInclusive */
17575 	    res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
17576 	    if (res == -2)
17577 		goto internal_error;
17578 	    if (res == 1) {
17579 		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
17580 	    }
17581 	}
17582 	if (bfminexc) {
17583 	    /* minInclusive > BASE minExclusive */
17584 	    res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
17585 	    if (res == -2)
17586 		goto internal_error;
17587 	    if (res != 1)
17588 		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
17589 	}
17590 	if (bfmaxexc) {
17591 	    /* minInclusive < BASE maxExclusive */
17592 	    res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
17593 	    if (res == -2)
17594 		goto internal_error;
17595 	    if (res != -1)
17596 		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
17597 	}
17598     }
17599     if (ftotdig && bftotdig) {
17600 	/*
17601 	* SCC " totalDigits valid restriction"
17602 	* totalDigits <= BASE totalDigits
17603 	*/
17604 	res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
17605 	if (res == -2)
17606 	    goto internal_error;
17607 	if (res == 1)
17608 	    xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
17609 	    -1, 1, 1);
17610 	if ((res != 0) && (bftotdig->fixed)) {
17611 	    FACET_RESTR_FIXED_ERR(ftotdig)
17612 	}
17613     }
17614     if (ffracdig && bffracdig) {
17615 	/*
17616 	* SCC  "fractionDigits valid restriction"
17617 	* fractionDigits <= BASE fractionDigits
17618 	*/
17619 	res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
17620 	if (res == -2)
17621 	    goto internal_error;
17622 	if (res == 1)
17623 	    xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
17624 	    -1, 1, 1);
17625 	if ((res != 0) && (bffracdig->fixed)) {
17626 	    FACET_RESTR_FIXED_ERR(ffracdig)
17627 	}
17628     }
17629     /*
17630     * SCC "fractionDigits less than or equal to totalDigits"
17631     */
17632     if (! ftotdig)
17633 	ftotdig = bftotdig;
17634     if (! ffracdig)
17635 	ffracdig = bffracdig;
17636     if (ftotdig && ffracdig) {
17637 	res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
17638 	if (res == -2)
17639 	    goto internal_error;
17640 	if (res == 1)
17641 	    xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
17642 		-1, 1, 0);
17643     }
17644     /*
17645     * *Enumerations* won' be added here, since only the first set
17646     * of enumerations in the ancestor-or-self axis is used
17647     * for validation, plus we need to use the base type of those
17648     * enumerations for whitespace.
17649     *
17650     * *Patterns*: won't be add here, since they are ORed at
17651     * type level and ANDed at ancestor level. This will
17652     * happed during validation by walking the base axis
17653     * of the type.
17654     */
17655     for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17656 	bfacet = cur->facet;
17657 	/*
17658 	* Special handling of enumerations and patterns.
17659 	* TODO: hmm, they should not appear in the set, so remove this.
17660 	*/
17661 	if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
17662 	    (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
17663 	    continue;
17664 	/*
17665 	* Search for a duplicate facet in the current type.
17666 	*/
17667 	link = type->facetSet;
17668 	/* err = 0; */
17669 	/* fixedErr = 0; */
17670 	while (link != NULL) {
17671 	    facet = link->facet;
17672 	    if (facet->type == bfacet->type) {
17673 		switch (facet->type) {
17674 		    case XML_SCHEMA_FACET_WHITESPACE:
17675 			/*
17676 			* The whitespace must be stronger.
17677 			*/
17678 			if (facet->whitespace < bfacet->whitespace) {
17679 			    FACET_RESTR_ERR(facet,
17680 				"The 'whitespace' value has to be equal to "
17681 				"or stronger than the 'whitespace' value of "
17682 				"the base type")
17683 			}
17684 			if ((bfacet->fixed) &&
17685 			    (facet->whitespace != bfacet->whitespace)) {
17686 			    FACET_RESTR_FIXED_ERR(facet)
17687 			}
17688 			break;
17689 		    default:
17690 			break;
17691 		}
17692 		/* Duplicate found. */
17693 		break;
17694 	    }
17695 	    link = link->next;
17696 	}
17697 	/*
17698 	* If no duplicate was found: add the base types's facet
17699 	* to the set.
17700 	*/
17701 	if (link == NULL) {
17702 	    link = (xmlSchemaFacetLinkPtr)
17703 		xmlMalloc(sizeof(xmlSchemaFacetLink));
17704 	    if (link == NULL) {
17705 		xmlSchemaPErrMemory(pctxt,
17706 		    "deriving facets, creating a facet link", NULL);
17707 		return (-1);
17708 	    }
17709 	    link->facet = cur->facet;
17710 	    link->next = NULL;
17711 	    if (last == NULL)
17712 		type->facetSet = link;
17713 	    else
17714 		last->next = link;
17715 	    last = link;
17716 	}
17717 
17718     }
17719 
17720     return (0);
17721 internal_error:
17722     PERROR_INT("xmlSchemaDeriveAndValidateFacets",
17723 	"an error occured");
17724     return (-1);
17725 }
17726 
17727 static int
xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)17728 xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
17729 					     xmlSchemaTypePtr type)
17730 {
17731     xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
17732     /*
17733     * The actual value is then formed by replacing any union type
17734     * definition in the �explicit members� with the members of their
17735     * {member type definitions}, in order.
17736     *
17737     * TODO: There's a bug entry at
17738     * "http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0287.html"
17739     * which indicates that we'll keep the union types the future.
17740     */
17741     link = type->memberTypes;
17742     while (link != NULL) {
17743 
17744 	if (WXS_IS_TYPE_NOT_FIXED(link->type))
17745 	    xmlSchemaTypeFixup(link->type, ACTXT_CAST pctxt);
17746 
17747 	if (WXS_IS_UNION(link->type)) {
17748 	    subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
17749 	    if (subLink != NULL) {
17750 		link->type = subLink->type;
17751 		if (subLink->next != NULL) {
17752 		    lastLink = link->next;
17753 		    subLink = subLink->next;
17754 		    prevLink = link;
17755 		    while (subLink != NULL) {
17756 			newLink = (xmlSchemaTypeLinkPtr)
17757 			    xmlMalloc(sizeof(xmlSchemaTypeLink));
17758 			if (newLink == NULL) {
17759 			    xmlSchemaPErrMemory(pctxt, "allocating a type link",
17760 				NULL);
17761 			    return (-1);
17762 			}
17763 			newLink->type = subLink->type;
17764 			prevLink->next = newLink;
17765 			prevLink = newLink;
17766 			newLink->next = lastLink;
17767 
17768 			subLink = subLink->next;
17769 		    }
17770 		}
17771 	    }
17772 	}
17773 	link = link->next;
17774     }
17775     return (0);
17776 }
17777 
17778 static void
xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)17779 xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
17780 {
17781     int has = 0, needVal = 0, normVal = 0;
17782 
17783     has	= (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
17784     if (has) {
17785 	needVal = (type->baseType->flags &
17786 	    XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
17787 	normVal = (type->baseType->flags &
17788 	    XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
17789     }
17790     if (type->facets != NULL) {
17791 	xmlSchemaFacetPtr fac;
17792 
17793 	for (fac = type->facets; fac != NULL; fac = fac->next) {
17794 	    switch (fac->type) {
17795 		case XML_SCHEMA_FACET_WHITESPACE:
17796 		    break;
17797 		case XML_SCHEMA_FACET_PATTERN:
17798 		    normVal = 1;
17799 		    has = 1;
17800 		    break;
17801 		case XML_SCHEMA_FACET_ENUMERATION:
17802 		    needVal = 1;
17803 		    normVal = 1;
17804 		    has = 1;
17805 		    break;
17806 		default:
17807 		    has = 1;
17808 		    break;
17809 	    }
17810 	}
17811     }
17812     if (normVal)
17813 	type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
17814     if (needVal)
17815 	type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17816     if (has)
17817 	type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
17818 
17819     if (has && (! needVal) && WXS_IS_ATOMIC(type)) {
17820 	xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
17821 	/*
17822 	* OPTIMIZE VAL TODO: Some facets need a computed value.
17823 	*/
17824 	if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
17825 	    (prim->builtInType != XML_SCHEMAS_STRING)) {
17826 	    type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17827 	}
17828     }
17829 }
17830 
17831 static int
xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)17832 xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
17833 {
17834 
17835 
17836     /*
17837     * Evaluate the whitespace-facet value.
17838     */
17839     if (WXS_IS_LIST(type)) {
17840 	type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17841 	return (0);
17842     } else if (WXS_IS_UNION(type))
17843 	return (0);
17844 
17845     if (type->facetSet != NULL) {
17846 	xmlSchemaFacetLinkPtr lin;
17847 
17848 	for (lin = type->facetSet; lin != NULL; lin = lin->next) {
17849 	    if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
17850 		switch (lin->facet->whitespace) {
17851 		case XML_SCHEMAS_FACET_PRESERVE:
17852 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17853 		    break;
17854 		case XML_SCHEMAS_FACET_REPLACE:
17855 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17856 		    break;
17857 		case XML_SCHEMAS_FACET_COLLAPSE:
17858 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17859 		    break;
17860 		default:
17861 		    return (-1);
17862 		}
17863 		return (0);
17864 	    }
17865 	}
17866     }
17867     /*
17868     * For all �atomic� datatypes other than string (and types �derived�
17869     * by �restriction� from it) the value of whiteSpace is fixed to
17870     * collapse
17871     */
17872     {
17873 	xmlSchemaTypePtr anc;
17874 
17875 	for (anc = type->baseType; anc != NULL &&
17876 		anc->builtInType != XML_SCHEMAS_ANYTYPE;
17877 		anc = anc->baseType) {
17878 
17879 	    if (anc->type == XML_SCHEMA_TYPE_BASIC) {
17880 		if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
17881 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17882 
17883 		} else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
17884 		    (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
17885 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17886 
17887 		} else
17888 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17889 		break;
17890 	    }
17891 	}
17892     }
17893     return (0);
17894 }
17895 
17896 static int
xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)17897 xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,
17898 			  xmlSchemaTypePtr type)
17899 {
17900     if (type->type != XML_SCHEMA_TYPE_SIMPLE)
17901 	return(0);
17902     if (! WXS_IS_TYPE_NOT_FIXED_1(type))
17903 	return(0);
17904     type->flags |= XML_SCHEMAS_TYPE_FIXUP_1;
17905 
17906     if (WXS_IS_LIST(type)) {
17907 	/*
17908 	* Corresponds to <simpleType><list>...
17909 	*/
17910 	if (type->subtypes == NULL) {
17911 	    /*
17912 	    * This one is really needed, so get out.
17913 	    */
17914 	    PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17915 		"list type has no item-type assigned");
17916 	    return(-1);
17917 	}
17918     } else if (WXS_IS_UNION(type)) {
17919 	/*
17920 	* Corresponds to <simpleType><union>...
17921 	*/
17922 	if (type->memberTypes == NULL) {
17923 	    /*
17924 	    * This one is really needed, so get out.
17925 	    */
17926 	    PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17927 		"union type has no member-types assigned");
17928 	    return(-1);
17929 	}
17930     } else {
17931 	/*
17932 	* Corresponds to <simpleType><restriction>...
17933 	*/
17934 	if (type->baseType == NULL) {
17935 	    PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17936 		"type has no base-type assigned");
17937 	    return(-1);
17938 	}
17939 	if (WXS_IS_TYPE_NOT_FIXED_1(type->baseType))
17940 	    if (xmlSchemaFixupSimpleTypeStageOne(pctxt, type->baseType) == -1)
17941 		return(-1);
17942 	/*
17943 	* Variety
17944 	* If the <restriction> alternative is chosen, then the
17945 	* {variety} of the {base type definition}.
17946 	*/
17947 	if (WXS_IS_ATOMIC(type->baseType))
17948 	    type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
17949 	else if (WXS_IS_LIST(type->baseType)) {
17950 	    type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
17951 	    /*
17952 	    * Inherit the itemType.
17953 	    */
17954 	    type->subtypes = type->baseType->subtypes;
17955 	} else if (WXS_IS_UNION(type->baseType)) {
17956 	    type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
17957 	    /*
17958 	    * NOTE that we won't assign the memberTypes of the base,
17959 	    * since this will make trouble when freeing them; we will
17960 	    * use a lookup function to access them instead.
17961 	    */
17962 	}
17963     }
17964     return(0);
17965 }
17966 
17967 #ifdef DEBUG_TYPE
17968 static void
xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)17969 xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt,
17970 		       xmlSchemaTypePtr type)
17971 {
17972     if (type->node != NULL) {
17973         xmlGenericError(xmlGenericErrorContext,
17974                         "Type of %s : %s:%d :", name,
17975                         type->node->doc->URL,
17976                         xmlGetLineNo(type->node));
17977     } else {
17978         xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
17979     }
17980     if ((WXS_IS_SIMPLE(type)) || (WXS_IS_COMPLEX(type))) {
17981 	switch (type->contentType) {
17982 	    case XML_SCHEMA_CONTENT_SIMPLE:
17983 		xmlGenericError(xmlGenericErrorContext, "simple\n");
17984 		break;
17985 	    case XML_SCHEMA_CONTENT_ELEMENTS:
17986 		xmlGenericError(xmlGenericErrorContext, "elements\n");
17987 		break;
17988 	    case XML_SCHEMA_CONTENT_UNKNOWN:
17989 		xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
17990 		break;
17991 	    case XML_SCHEMA_CONTENT_EMPTY:
17992 		xmlGenericError(xmlGenericErrorContext, "empty\n");
17993 		break;
17994 	    case XML_SCHEMA_CONTENT_MIXED:
17995 		if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
17996 		    type->subtypes))
17997 		    xmlGenericError(xmlGenericErrorContext,
17998 			"mixed as emptiable particle\n");
17999 		else
18000 		    xmlGenericError(xmlGenericErrorContext, "mixed\n");
18001 		break;
18002 		/* Removed, since not used. */
18003 		/*
18004 		case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
18005 		xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
18006 		break;
18007 		*/
18008 	    case XML_SCHEMA_CONTENT_BASIC:
18009 		xmlGenericError(xmlGenericErrorContext, "basic\n");
18010 		break;
18011 	    default:
18012 		xmlGenericError(xmlGenericErrorContext,
18013 		    "not registered !!!\n");
18014 		break;
18015 	}
18016     }
18017 }
18018 #endif
18019 
18020 /*
18021 * 3.14.6 Constraints on Simple Type Definition Schema Components
18022 */
18023 static int
xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)18024 xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,
18025 				 xmlSchemaTypePtr type)
18026 {
18027     int res, olderrs = pctxt->nberrors;
18028 
18029     if (type->type != XML_SCHEMA_TYPE_SIMPLE)
18030 	return(-1);
18031 
18032     if (! WXS_IS_TYPE_NOT_FIXED(type))
18033 	return(0);
18034 
18035     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18036     type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
18037 
18038     if (type->baseType == NULL) {
18039 	PERROR_INT("xmlSchemaFixupSimpleTypeStageTwo",
18040 	    "missing baseType");
18041 	goto exit_failure;
18042     }
18043     if (WXS_IS_TYPE_NOT_FIXED(type->baseType))
18044 	xmlSchemaTypeFixup(type->baseType, ACTXT_CAST pctxt);
18045     /*
18046     * If a member type of a union is a union itself, we need to substitute
18047     * that member type for its member types.
18048     * NOTE that this might change in WXS 1.1; i.e. we will keep the union
18049     * types in WXS 1.1.
18050     */
18051     if ((type->memberTypes != NULL) &&
18052 	(xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1))
18053 	return(-1);
18054     /*
18055     * SPEC src-simple-type 1
18056     * "The corresponding simple type definition, if any, must satisfy
18057     * the conditions set out in Constraints on Simple Type Definition
18058     * Schema Components (�3.14.6)."
18059     */
18060     /*
18061     * Schema Component Constraint: Simple Type Definition Properties Correct
18062     * (st-props-correct)
18063     */
18064     res = xmlSchemaCheckSTPropsCorrect(pctxt, type);
18065     HFAILURE HERROR
18066     /*
18067     * Schema Component Constraint: Derivation Valid (Restriction, Simple)
18068     * (cos-st-restricts)
18069     */
18070     res = xmlSchemaCheckCOSSTRestricts(pctxt, type);
18071     HFAILURE HERROR
18072     /*
18073     * TODO: Removed the error report, since it got annoying to get an
18074     * extra error report, if anything failed until now.
18075     * Enable this if needed.
18076     *
18077     * xmlSchemaPErr(ctxt, type->node,
18078     *    XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
18079     *    "Simple type '%s' does not satisfy the constraints "
18080     *    "on simple type definitions.\n",
18081     *    type->name, NULL);
18082     */
18083     /*
18084     * Schema Component Constraint: Simple Type Restriction (Facets)
18085     * (st-restrict-facets)
18086     */
18087     res = xmlSchemaCheckFacetValues(type, pctxt);
18088     HFAILURE HERROR
18089     if ((type->facetSet != NULL) ||
18090 	(type->baseType->facetSet != NULL)) {
18091 	res = xmlSchemaDeriveAndValidateFacets(pctxt, type);
18092 	HFAILURE HERROR
18093     }
18094     /*
18095     * Whitespace value.
18096     */
18097     res = xmlSchemaTypeFixupWhitespace(type);
18098     HFAILURE HERROR
18099     xmlSchemaTypeFixupOptimFacets(type);
18100 
18101 exit_error:
18102 #ifdef DEBUG_TYPE
18103     xmlSchemaDebugFixedType(pctxt, type);
18104 #endif
18105     if (olderrs != pctxt->nberrors)
18106 	return(pctxt->err);
18107     return(0);
18108 
18109 exit_failure:
18110 #ifdef DEBUG_TYPE
18111     xmlSchemaDebugFixedType(pctxt, type);
18112 #endif
18113     return(-1);
18114 }
18115 
18116 static int
xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)18117 xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,
18118 			  xmlSchemaTypePtr type)
18119 {
18120     int res = 0, olderrs = pctxt->nberrors;
18121     xmlSchemaTypePtr baseType = type->baseType;
18122 
18123     if (! WXS_IS_TYPE_NOT_FIXED(type))
18124 	return(0);
18125     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18126     if (baseType == NULL) {
18127 	PERROR_INT("xmlSchemaFixupComplexType",
18128 	    "missing baseType");
18129 	goto exit_failure;
18130     }
18131     /*
18132     * Fixup the base type.
18133     */
18134     if (WXS_IS_TYPE_NOT_FIXED(baseType))
18135 	xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt);
18136     if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
18137 	/*
18138 	* Skip fixup if the base type is invalid.
18139 	* TODO: Generate a warning!
18140 	*/
18141 	return(0);
18142     }
18143     /*
18144     * This basically checks if the base type can be derived.
18145     */
18146     res = xmlSchemaCheckSRCCT(pctxt, type);
18147     HFAILURE HERROR
18148     /*
18149     * Fixup the content type.
18150     */
18151     if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
18152 	/*
18153 	* Corresponds to <complexType><simpleContent>...
18154 	*/
18155 	if ((WXS_IS_COMPLEX(baseType)) &&
18156 	    (baseType->contentTypeDef != NULL) &&
18157 	    (WXS_IS_RESTRICTION(type))) {
18158 	    xmlSchemaTypePtr contentBase, content;
18159 #ifdef ENABLE_NAMED_LOCALS
18160 	    char buf[30];
18161 	    const xmlChar *tmpname;
18162 #endif
18163 	    /*
18164 	    * SPEC (1) If <restriction> + base type is <complexType>,
18165 	    * "whose own {content type} is a simple type..."
18166 	    */
18167 	    if (type->contentTypeDef != NULL) {
18168 		/*
18169 		* SPEC (1.1) "the simple type definition corresponding to the
18170 		* <simpleType> among the [children] of <restriction> if there
18171 		* is one;"
18172 		* Note that this "<simpleType> among the [children]" was put
18173 		* into ->contentTypeDef during parsing.
18174 		*/
18175 		contentBase = type->contentTypeDef;
18176 		type->contentTypeDef = NULL;
18177 	    } else {
18178 		/*
18179 		* (1.2) "...otherwise (<restriction> has no <simpleType>
18180 		* among its [children]), the simple type definition which
18181 		* is the {content type} of the ... base type."
18182 		*/
18183 		contentBase = baseType->contentTypeDef;
18184 	    }
18185 	    /*
18186 	    * SPEC
18187 	    * "... a simple type definition which restricts the simple
18188 	    * type definition identified in clause 1.1 or clause 1.2
18189 	    * with a set of facet components"
18190 	    *
18191 	    * Create the anonymous simple type, which will be the content
18192 	    * type of the complex type.
18193 	    */
18194 #ifdef ENABLE_NAMED_LOCALS
18195 	    snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
18196 	    tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
18197 	    content = xmlSchemaAddType(pctxt, pctxt->schema,
18198 		XML_SCHEMA_TYPE_SIMPLE, tmpname, type->targetNamespace,
18199 		type->node, 0);
18200 #else
18201 	    content = xmlSchemaAddType(pctxt, pctxt->schema,
18202 		XML_SCHEMA_TYPE_SIMPLE, NULL, type->targetNamespace,
18203 		type->node, 0);
18204 #endif
18205 	    if (content == NULL)
18206 		goto exit_failure;
18207 	    /*
18208 	    * We will use the same node as for the <complexType>
18209 	    * to have it somehow anchored in the schema doc.
18210 	    */
18211 	    content->type = XML_SCHEMA_TYPE_SIMPLE;
18212 	    content->baseType = contentBase;
18213 	    /*
18214 	    * Move the facets, previously anchored on the
18215 	    * complexType during parsing.
18216 	    */
18217 	    content->facets = type->facets;
18218 	    type->facets = NULL;
18219 	    content->facetSet = type->facetSet;
18220 	    type->facetSet = NULL;
18221 
18222 	    type->contentTypeDef = content;
18223 	    if (WXS_IS_TYPE_NOT_FIXED(contentBase))
18224 		xmlSchemaTypeFixup(contentBase, ACTXT_CAST pctxt);
18225 	    /*
18226 	    * Fixup the newly created type. We don't need to check
18227 	    * for circularity here.
18228 	    */
18229 	    res = xmlSchemaFixupSimpleTypeStageOne(pctxt, content);
18230 	    HFAILURE HERROR
18231 	    res = xmlSchemaFixupSimpleTypeStageTwo(pctxt, content);
18232 	    HFAILURE HERROR
18233 
18234 	} else if ((WXS_IS_COMPLEX(baseType)) &&
18235 	    (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
18236 	    (WXS_IS_RESTRICTION(type))) {
18237 	    /*
18238 	    * SPEC (2) If <restriction> + base is a mixed <complexType> with
18239 	    * an emptiable particle, then a simple type definition which
18240 	    * restricts the <restriction>'s <simpleType> child.
18241 	    */
18242 	    if ((type->contentTypeDef == NULL) ||
18243 		(type->contentTypeDef->baseType == NULL)) {
18244 		/*
18245 		* TODO: Check if this ever happens.
18246 		*/
18247 		xmlSchemaPCustomErr(pctxt,
18248 		    XML_SCHEMAP_INTERNAL,
18249 		    WXS_BASIC_CAST type, NULL,
18250 		    "Internal error: xmlSchemaTypeFixup, "
18251 		    "complex type '%s': the <simpleContent><restriction> "
18252 		    "is missing a <simpleType> child, but was not catched "
18253 		    "by xmlSchemaCheckSRCCT()", type->name);
18254 		goto exit_failure;
18255 	    }
18256 	} else if ((WXS_IS_COMPLEX(baseType)) && WXS_IS_EXTENSION(type)) {
18257 	    /*
18258 	    * SPEC (3) If <extension> + base is <complexType> with
18259 	    * <simpleType> content, "...then the {content type} of that
18260 	    * complex type definition"
18261 	    */
18262 	    if (baseType->contentTypeDef == NULL) {
18263 		/*
18264 		* TODO: Check if this ever happens. xmlSchemaCheckSRCCT
18265 		* should have catched this already.
18266 		*/
18267 		xmlSchemaPCustomErr(pctxt,
18268 		    XML_SCHEMAP_INTERNAL,
18269 		    WXS_BASIC_CAST type, NULL,
18270 		    "Internal error: xmlSchemaTypeFixup, "
18271 		    "complex type '%s': the <extension>ed base type is "
18272 		    "a complex type with no simple content type",
18273 		    type->name);
18274 		goto exit_failure;
18275 	    }
18276 	    type->contentTypeDef = baseType->contentTypeDef;
18277 	} else if ((WXS_IS_SIMPLE(baseType)) && WXS_IS_EXTENSION(type)) {
18278 	    /*
18279 	    * SPEC (4) <extension> + base is <simpleType>
18280 	    * "... then that simple type definition"
18281 	    */
18282 	    type->contentTypeDef = baseType;
18283 	} else {
18284 	    /*
18285 	    * TODO: Check if this ever happens.
18286 	    */
18287 	    xmlSchemaPCustomErr(pctxt,
18288 		XML_SCHEMAP_INTERNAL,
18289 		WXS_BASIC_CAST type, NULL,
18290 		"Internal error: xmlSchemaTypeFixup, "
18291 		"complex type '%s' with <simpleContent>: unhandled "
18292 		"derivation case", type->name);
18293 	    goto exit_failure;
18294 	}
18295     } else {
18296 	int dummySequence = 0;
18297 	xmlSchemaParticlePtr particle =
18298 	    (xmlSchemaParticlePtr) type->subtypes;
18299 	/*
18300 	* Corresponds to <complexType><complexContent>...
18301 	*
18302 	* NOTE that the effective mixed was already set during parsing of
18303 	* <complexType> and <complexContent>; its flag value is
18304 	* XML_SCHEMAS_TYPE_MIXED.
18305 	*
18306 	* Compute the "effective content":
18307 	* (2.1.1) + (2.1.2) + (2.1.3)
18308 	*/
18309 	if ((particle == NULL) ||
18310 	    ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
18311 	    ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
18312 	    (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
18313 	    ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
18314 	    (particle->minOccurs == 0))) &&
18315 	    ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
18316 	    if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
18317 		/*
18318 		* SPEC (2.1.4) "If the �effective mixed� is true, then
18319 		* a particle whose properties are as follows:..."
18320 		*
18321 		* Empty sequence model group with
18322 		* minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
18323 		* NOTE that we sill assign it the <complexType> node to
18324 		* somehow anchor it in the doc.
18325 		*/
18326 		if ((particle == NULL) ||
18327 		    (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
18328 		    /*
18329 		    * Create the particle.
18330 		    */
18331 		    particle = xmlSchemaAddParticle(pctxt,
18332 			type->node, 1, 1);
18333 		    if (particle == NULL)
18334 			goto exit_failure;
18335 		    /*
18336 		    * Create the model group.
18337 		    */ /* URGENT TODO: avoid adding to pending items. */
18338 		    particle->children = (xmlSchemaTreeItemPtr)
18339 			xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18340 			XML_SCHEMA_TYPE_SEQUENCE, type->node);
18341 		    if (particle->children == NULL)
18342 			goto exit_failure;
18343 
18344 		    type->subtypes = (xmlSchemaTypePtr) particle;
18345 		}
18346 		dummySequence = 1;
18347 		type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18348 	    } else {
18349 		/*
18350 		* SPEC (2.1.5) "otherwise empty"
18351 		*/
18352 		type->contentType = XML_SCHEMA_CONTENT_EMPTY;
18353 	    }
18354 	} else {
18355 	    /*
18356 	    * SPEC (2.2) "otherwise the particle corresponding to the
18357 	    * <all>, <choice>, <group> or <sequence> among the
18358 	    * [children]."
18359 	    */
18360 	    type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18361 	}
18362 	/*
18363 	* Compute the "content type".
18364 	*/
18365 	if (WXS_IS_RESTRICTION(type)) {
18366 	    /*
18367 	    * SPEC (3.1) "If <restriction>..."
18368 	    * (3.1.1) + (3.1.2) */
18369 	    if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
18370 		if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18371 		    type->contentType = XML_SCHEMA_CONTENT_MIXED;
18372 	    }
18373 	} else {
18374 	    /*
18375 	    * SPEC (3.2) "If <extension>..."
18376 	    */
18377 	    if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18378 		/*
18379 		* SPEC (3.2.1)
18380 		* "If the �effective content� is empty, then the
18381 		*  {content type} of the [...] base ..."
18382 		*/
18383 		type->contentType = baseType->contentType;
18384 		type->subtypes = baseType->subtypes;
18385 		/*
18386 		* Fixes bug #347316:
18387 		* This is the case when the base type has a simple
18388 		* type definition as content.
18389 		*/
18390 		type->contentTypeDef = baseType->contentTypeDef;
18391 		/*
18392 		* NOTE that the effective mixed is ignored here.
18393 		*/
18394 	    } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18395 		/*
18396 		* SPEC (3.2.2)
18397 		*/
18398 		if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18399 		    type->contentType = XML_SCHEMA_CONTENT_MIXED;
18400 	    } else {
18401 		/*
18402 		* SPEC (3.2.3)
18403 		*/
18404 		if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18405 		    type->contentType = XML_SCHEMA_CONTENT_MIXED;
18406 		    /*
18407 		    * "A model group whose {compositor} is sequence and whose
18408 		    * {particles} are..."
18409 		    */
18410 		if ((WXS_TYPE_PARTICLE(type) != NULL) &&
18411 		    (WXS_TYPE_PARTICLE_TERM(type) != NULL) &&
18412 		    ((WXS_TYPE_PARTICLE_TERM(type))->type ==
18413 			XML_SCHEMA_TYPE_ALL))
18414 		{
18415 		    /*
18416 		    * SPEC cos-all-limited (1)
18417 		    */
18418 		    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18419 			/* TODO: error code */
18420 			XML_SCHEMAP_COS_ALL_LIMITED,
18421 			WXS_ITEM_NODE(type), NULL,
18422 			"The type has an 'all' model group in its "
18423 			"{content type} and thus cannot be derived from "
18424 			"a non-empty type, since this would produce a "
18425 			"'sequence' model group containing the 'all' "
18426 			"model group; 'all' model groups are not "
18427 			"allowed to appear inside other model groups",
18428 			NULL, NULL);
18429 
18430 		} else if ((WXS_TYPE_PARTICLE(baseType) != NULL) &&
18431 		    (WXS_TYPE_PARTICLE_TERM(baseType) != NULL) &&
18432 		    ((WXS_TYPE_PARTICLE_TERM(baseType))->type ==
18433 			XML_SCHEMA_TYPE_ALL))
18434 		{
18435 		    /*
18436 		    * SPEC cos-all-limited (1)
18437 		    */
18438 		    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18439 			/* TODO: error code */
18440 			XML_SCHEMAP_COS_ALL_LIMITED,
18441 			WXS_ITEM_NODE(type), NULL,
18442 			"A type cannot be derived by extension from a type "
18443 			"which has an 'all' model group in its "
18444 			"{content type}, since this would produce a "
18445 			"'sequence' model group containing the 'all' "
18446 			"model group; 'all' model groups are not "
18447 			"allowed to appear inside other model groups",
18448 			NULL, NULL);
18449 
18450 		} else if (! dummySequence) {
18451 		    xmlSchemaTreeItemPtr effectiveContent =
18452 			(xmlSchemaTreeItemPtr) type->subtypes;
18453 		    /*
18454 		    * Create the particle.
18455 		    */
18456 		    particle = xmlSchemaAddParticle(pctxt,
18457 			type->node, 1, 1);
18458 		    if (particle == NULL)
18459 			goto exit_failure;
18460 		    /*
18461 		    * Create the "sequence" model group.
18462 		    */
18463 		    particle->children = (xmlSchemaTreeItemPtr)
18464 			xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18465 			XML_SCHEMA_TYPE_SEQUENCE, type->node);
18466 		    if (particle->children == NULL)
18467 			goto exit_failure;
18468 		    WXS_TYPE_CONTENTTYPE(type) = (xmlSchemaTypePtr) particle;
18469 		    /*
18470 		    * SPEC "the particle of the {content type} of
18471 		    * the ... base ..."
18472 		    * Create a duplicate of the base type's particle
18473 		    * and assign its "term" to it.
18474 		    */
18475 		    particle->children->children =
18476 			(xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
18477 			type->node,
18478 			((xmlSchemaParticlePtr) type->subtypes)->minOccurs,
18479 			((xmlSchemaParticlePtr) type->subtypes)->maxOccurs);
18480 		    if (particle->children->children == NULL)
18481 			goto exit_failure;
18482 		    particle = (xmlSchemaParticlePtr)
18483 			particle->children->children;
18484 		    particle->children =
18485 			((xmlSchemaParticlePtr) baseType->subtypes)->children;
18486 		    /*
18487 		    * SPEC "followed by the �effective content�."
18488 		    */
18489 		    particle->next = effectiveContent;
18490 		    /*
18491 		    * This all will result in:
18492 		    * new-particle
18493 		    *   --> new-sequence(
18494 		    *         new-particle
18495 		    *           --> base-model,
18496 		    *         this-particle
18497 		    *	        --> this-model
18498 		    *	    )
18499 		    */
18500 		} else {
18501 		    /*
18502 		    * This is the case when there is already an empty
18503 		    * <sequence> with minOccurs==maxOccurs==1.
18504 		    * Just add the base types's content type.
18505 		    * NOTE that, although we miss to add an intermediate
18506 		    * <sequence>, this should produce no difference to
18507 		    * neither the regex compilation of the content model,
18508 		    * nor to the complex type contraints.
18509 		    */
18510 		    particle->children->children =
18511 			(xmlSchemaTreeItemPtr) baseType->subtypes;
18512 		}
18513 	    }
18514 	}
18515     }
18516     /*
18517     * Now fixup attribute uses:
18518     *   - expand attr. group references
18519     *     - intersect attribute wildcards
18520     *   - inherit attribute uses of the base type
18521     *   - inherit or union attr. wildcards if extending
18522     *   - apply attr. use prohibitions if restricting
18523     */
18524     res = xmlSchemaFixupTypeAttributeUses(pctxt, type);
18525     HFAILURE HERROR
18526     /*
18527     * Apply the complex type component constraints; this will not
18528     * check attributes, since this is done in
18529     * xmlSchemaFixupTypeAttributeUses().
18530     */
18531     res = xmlSchemaCheckCTComponent(pctxt, type);
18532     HFAILURE HERROR
18533 
18534 #ifdef DEBUG_TYPE
18535     xmlSchemaDebugFixedType(pctxt, type);
18536 #endif
18537     if (olderrs != pctxt->nberrors)
18538 	return(pctxt->err);
18539     else
18540 	return(0);
18541 
18542 exit_error:
18543     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18544 #ifdef DEBUG_TYPE
18545     xmlSchemaDebugFixedType(pctxt, type);
18546 #endif
18547     return(pctxt->err);
18548 
18549 exit_failure:
18550     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18551 #ifdef DEBUG_TYPE
18552     xmlSchemaDebugFixedType(pctxt, type);
18553 #endif
18554     return(-1);
18555 }
18556 
18557 
18558 /**
18559  * xmlSchemaTypeFixup:
18560  * @typeDecl:  the schema type definition
18561  * @ctxt:  the schema parser context
18562  *
18563  * Fixes the content model of the type.
18564  * URGENT TODO: We need an int result!
18565  */
18566 static int
xmlSchemaTypeFixup(xmlSchemaTypePtr type,xmlSchemaAbstractCtxtPtr actxt)18567 xmlSchemaTypeFixup(xmlSchemaTypePtr type,
18568                    xmlSchemaAbstractCtxtPtr actxt)
18569 {
18570     if (type == NULL)
18571         return(0);
18572     if (actxt->type != XML_SCHEMA_CTXT_PARSER) {
18573 	AERROR_INT("xmlSchemaTypeFixup",
18574 	    "this function needs a parser context");
18575 	return(-1);
18576     }
18577     if (! WXS_IS_TYPE_NOT_FIXED(type))
18578 	return(0);
18579     if (type->type == XML_SCHEMA_TYPE_COMPLEX)
18580 	return(xmlSchemaFixupComplexType(PCTXT_CAST actxt, type));
18581     else if (type->type == XML_SCHEMA_TYPE_SIMPLE)
18582 	return(xmlSchemaFixupSimpleTypeStageTwo(PCTXT_CAST actxt, type));
18583     return(0);
18584 }
18585 
18586 /**
18587  * xmlSchemaCheckFacet:
18588  * @facet:  the facet
18589  * @typeDecl:  the schema type definition
18590  * @pctxt:  the schema parser context or NULL
18591  * @name: the optional name of the type
18592  *
18593  * Checks and computes the values of facets.
18594  *
18595  * Returns 0 if valid, a positive error code if not valid and
18596  *         -1 in case of an internal or API error.
18597  */
18598 int
xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,xmlSchemaTypePtr typeDecl,xmlSchemaParserCtxtPtr pctxt,const xmlChar * name ATTRIBUTE_UNUSED)18599 xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
18600                     xmlSchemaTypePtr typeDecl,
18601                     xmlSchemaParserCtxtPtr pctxt,
18602 		    const xmlChar * name ATTRIBUTE_UNUSED)
18603 {
18604     int ret = 0, ctxtGiven;
18605 
18606     if ((facet == NULL) || (typeDecl == NULL))
18607         return(-1);
18608     /*
18609     * TODO: will the parser context be given if used from
18610     * the relaxNG module?
18611     */
18612     if (pctxt == NULL)
18613 	ctxtGiven = 0;
18614     else
18615 	ctxtGiven = 1;
18616 
18617     switch (facet->type) {
18618         case XML_SCHEMA_FACET_MININCLUSIVE:
18619         case XML_SCHEMA_FACET_MINEXCLUSIVE:
18620         case XML_SCHEMA_FACET_MAXINCLUSIVE:
18621         case XML_SCHEMA_FACET_MAXEXCLUSIVE:
18622 	case XML_SCHEMA_FACET_ENUMERATION: {
18623                 /*
18624                  * Okay we need to validate the value
18625                  * at that point.
18626                  */
18627 		xmlSchemaTypePtr base;
18628 
18629 		/* 4.3.5.5 Constraints on enumeration Schema Components
18630 		* Schema Component Constraint: enumeration valid restriction
18631 		* It is an �error� if any member of {value} is not in the
18632 		* �value space� of {base type definition}.
18633 		*
18634 		* minInclusive, maxInclusive, minExclusive, maxExclusive:
18635 		* The value �must� be in the
18636 		* �value space� of the �base type�.
18637 		*/
18638 		/*
18639 		* This function is intended to deliver a compiled value
18640 		* on the facet. In this implementation of XML Schemata the
18641 		* type holding a facet, won't be a built-in type.
18642 		* Thus to ensure that other API
18643 		* calls (relaxng) do work, if the given type is a built-in
18644 		* type, we will assume that the given built-in type *is
18645 		* already* the base type.
18646 		*/
18647 		if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
18648 		    base = typeDecl->baseType;
18649 		    if (base == NULL) {
18650 			PERROR_INT("xmlSchemaCheckFacet",
18651 			    "a type user derived type has no base type");
18652 			return (-1);
18653 		    }
18654 		} else
18655 		    base = typeDecl;
18656 
18657 		if (! ctxtGiven) {
18658 		    /*
18659 		    * A context is needed if called from RelaxNG.
18660 		    */
18661 		    pctxt = xmlSchemaNewParserCtxt("*");
18662 		    if (pctxt == NULL)
18663 			return (-1);
18664 		}
18665 		/*
18666 		* NOTE: This call does not check the content nodes,
18667 		* since they are not available:
18668 		* facet->node is just the node holding the facet
18669 		* definition, *not* the attribute holding the *value*
18670 		* of the facet.
18671 		*/
18672 		ret = xmlSchemaVCheckCVCSimpleType(
18673 		    ACTXT_CAST pctxt, facet->node, base,
18674 		    facet->value, &(facet->val), 1, 1, 0);
18675                 if (ret != 0) {
18676 		    if (ret < 0) {
18677 			/* No error message for RelaxNG. */
18678 			if (ctxtGiven) {
18679 			    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18680 				XML_SCHEMAP_INTERNAL, facet->node, NULL,
18681 				"Internal error: xmlSchemaCheckFacet, "
18682 				"failed to validate the value '%s' of the "
18683 				"facet '%s' against the base type",
18684 				facet->value, xmlSchemaFacetTypeToString(facet->type));
18685 			}
18686 			goto internal_error;
18687 		    }
18688 		    ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18689 		    /* No error message for RelaxNG. */
18690 		    if (ctxtGiven) {
18691 			xmlChar *str = NULL;
18692 
18693 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
18694 			    ret, facet->node, WXS_BASIC_CAST facet,
18695 			    "The value '%s' of the facet does not validate "
18696 			    "against the base type '%s'",
18697 			    facet->value,
18698 			    xmlSchemaFormatQName(&str,
18699 				base->targetNamespace, base->name));
18700 			FREE_AND_NULL(str);
18701 		    }
18702 		    goto exit;
18703                 } else if (facet->val == NULL) {
18704 		    if (ctxtGiven) {
18705 			PERROR_INT("xmlSchemaCheckFacet",
18706 			    "value was not computed");
18707 		    }
18708 		    TODO
18709 		}
18710                 break;
18711             }
18712         case XML_SCHEMA_FACET_PATTERN:
18713             facet->regexp = xmlRegexpCompile(facet->value);
18714             if (facet->regexp == NULL) {
18715 		ret = XML_SCHEMAP_REGEXP_INVALID;
18716 		/* No error message for RelaxNG. */
18717 		if (ctxtGiven) {
18718 		    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18719 			ret, facet->node, WXS_BASIC_CAST typeDecl,
18720 			"The value '%s' of the facet 'pattern' is not a "
18721 			"valid regular expression",
18722 			facet->value, NULL);
18723 		}
18724             }
18725             break;
18726         case XML_SCHEMA_FACET_TOTALDIGITS:
18727         case XML_SCHEMA_FACET_FRACTIONDIGITS:
18728         case XML_SCHEMA_FACET_LENGTH:
18729         case XML_SCHEMA_FACET_MAXLENGTH:
18730         case XML_SCHEMA_FACET_MINLENGTH:
18731 
18732 	    if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
18733 		ret = xmlSchemaValidatePredefinedType(
18734 		    xmlSchemaGetBuiltInType(XML_SCHEMAS_PINTEGER),
18735 		    facet->value, &(facet->val));
18736 	    } else {
18737 		ret = xmlSchemaValidatePredefinedType(
18738 		    xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
18739 		    facet->value, &(facet->val));
18740 	    }
18741 	    if (ret != 0) {
18742 		if (ret < 0) {
18743 		    /* No error message for RelaxNG. */
18744 		    if (ctxtGiven) {
18745 			PERROR_INT("xmlSchemaCheckFacet",
18746 			    "validating facet value");
18747 		    }
18748 		    goto internal_error;
18749 		}
18750 		ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18751 		/* No error message for RelaxNG. */
18752 		if (ctxtGiven) {
18753 		    /* error code */
18754 		    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
18755 			ret, facet->node, WXS_BASIC_CAST typeDecl,
18756 			"The value '%s' of the facet '%s' is not a valid '%s'",
18757 			facet->value,
18758 			xmlSchemaFacetTypeToString(facet->type),
18759 			(facet->type != XML_SCHEMA_FACET_TOTALDIGITS) ?
18760 			    BAD_CAST "nonNegativeInteger" :
18761 			    BAD_CAST "positiveInteger",
18762 			NULL);
18763 		}
18764 	    }
18765 	    break;
18766 
18767         case XML_SCHEMA_FACET_WHITESPACE:{
18768                 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
18769                     facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
18770                 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
18771                     facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
18772                 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
18773                     facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
18774                 } else {
18775 		    ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18776                     /* No error message for RelaxNG. */
18777 		    if (ctxtGiven) {
18778 			/* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
18779 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
18780 			    ret, facet->node, WXS_BASIC_CAST typeDecl,
18781 			    "The value '%s' of the facet 'whitespace' is not "
18782 			    "valid", facet->value, NULL);
18783                     }
18784                 }
18785             }
18786         default:
18787             break;
18788     }
18789 exit:
18790     if ((! ctxtGiven) && (pctxt != NULL))
18791 	xmlSchemaFreeParserCtxt(pctxt);
18792     return (ret);
18793 internal_error:
18794     if ((! ctxtGiven) && (pctxt != NULL))
18795 	xmlSchemaFreeParserCtxt(pctxt);
18796     return (-1);
18797 }
18798 
18799 /**
18800  * xmlSchemaCheckFacetValues:
18801  * @typeDecl:  the schema type definition
18802  * @ctxt:  the schema parser context
18803  *
18804  * Checks the default values types, especially for facets
18805  */
18806 static int
xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,xmlSchemaParserCtxtPtr pctxt)18807 xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
18808 			  xmlSchemaParserCtxtPtr pctxt)
18809 {
18810     int res, olderrs = pctxt->nberrors;
18811     const xmlChar *name = typeDecl->name;
18812     /*
18813     * NOTE: It is intended to use the facets list, instead
18814     * of facetSet.
18815     */
18816     if (typeDecl->facets != NULL) {
18817 	xmlSchemaFacetPtr facet = typeDecl->facets;
18818 
18819 	/*
18820 	* Temporarily assign the "schema" to the validation context
18821 	* of the parser context. This is needed for NOTATION validation.
18822 	*/
18823 	if (pctxt->vctxt == NULL) {
18824 	    if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1)
18825 		return(-1);
18826 	}
18827 	pctxt->vctxt->schema = pctxt->schema;
18828 	while (facet != NULL) {
18829 	    res = xmlSchemaCheckFacet(facet, typeDecl, pctxt, name);
18830 	    HFAILURE
18831 	    facet = facet->next;
18832 	}
18833 	pctxt->vctxt->schema = NULL;
18834     }
18835     if (olderrs != pctxt->nberrors)
18836 	return(pctxt->err);
18837     return(0);
18838 exit_failure:
18839     return(-1);
18840 }
18841 
18842 /**
18843  * xmlSchemaGetCircModelGrDefRef:
18844  * @ctxtMGroup: the searched model group
18845  * @selfMGroup: the second searched model group
18846  * @particle: the first particle
18847  *
18848  * This one is intended to be used by
18849  * xmlSchemaCheckGroupDefCircular only.
18850  *
18851  * Returns the particle with the circular model group definition reference,
18852  * otherwise NULL.
18853  */
18854 static xmlSchemaTreeItemPtr
xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,xmlSchemaTreeItemPtr particle)18855 xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
18856 			      xmlSchemaTreeItemPtr particle)
18857 {
18858     xmlSchemaTreeItemPtr circ = NULL;
18859     xmlSchemaTreeItemPtr term;
18860     xmlSchemaModelGroupDefPtr gdef;
18861 
18862     for (; particle != NULL; particle = particle->next) {
18863 	term = particle->children;
18864 	if (term == NULL)
18865 	    continue;
18866 	switch (term->type) {
18867 	    case XML_SCHEMA_TYPE_GROUP:
18868 		gdef = (xmlSchemaModelGroupDefPtr) term;
18869 		if (gdef == groupDef)
18870 		    return (particle);
18871 		/*
18872 		* Mark this model group definition to avoid infinite
18873 		* recursion on circular references not yet examined.
18874 		*/
18875 		if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
18876 		    continue;
18877 		if (gdef->children != NULL) {
18878 		    gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18879 		    circ = xmlSchemaGetCircModelGrDefRef(groupDef,
18880 			gdef->children->children);
18881 		    gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18882 		    if (circ != NULL)
18883 			return (circ);
18884 		}
18885 		break;
18886 	    case XML_SCHEMA_TYPE_SEQUENCE:
18887 	    case XML_SCHEMA_TYPE_CHOICE:
18888 	    case XML_SCHEMA_TYPE_ALL:
18889 		circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
18890 		if (circ != NULL)
18891 		    return (circ);
18892 		break;
18893 	    default:
18894 		break;
18895 	}
18896     }
18897     return (NULL);
18898 }
18899 
18900 /**
18901  * xmlSchemaCheckGroupDefCircular:
18902  * @item:  the model group definition
18903  * @ctxt:  the parser context
18904  * @name:  the name
18905  *
18906  * Checks for circular references to model group definitions.
18907  */
18908 static void
xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,xmlSchemaParserCtxtPtr ctxt)18909 xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
18910 			       xmlSchemaParserCtxtPtr ctxt)
18911 {
18912     /*
18913     * Schema Component Constraint: Model Group Correct
18914     * 2 Circular groups are disallowed. That is, within the {particles}
18915     * of a group there must not be at any depth a particle whose {term}
18916     * is the group itself.
18917     */
18918     if ((item == NULL) ||
18919 	(item->type != XML_SCHEMA_TYPE_GROUP) ||
18920 	(item->children == NULL))
18921 	return;
18922     {
18923 	xmlSchemaTreeItemPtr circ;
18924 
18925 	circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
18926 	if (circ != NULL) {
18927 	    xmlChar *str = NULL;
18928 	    /*
18929 	    * TODO: The error report is not adequate: this constraint
18930 	    * is defined for model groups but not definitions, but since
18931 	    * there cannot be any circular model groups without a model group
18932 	    * definition (if not using a construction API), we check those
18933 	    * defintions only.
18934 	    */
18935 	    xmlSchemaPCustomErr(ctxt,
18936 		XML_SCHEMAP_MG_PROPS_CORRECT_2,
18937 		NULL, WXS_ITEM_NODE(circ),
18938 		"Circular reference to the model group definition '%s' "
18939 		"defined", xmlSchemaFormatQName(&str,
18940 		    item->targetNamespace, item->name));
18941 	    FREE_AND_NULL(str)
18942 	    /*
18943 	    * NOTE: We will cut the reference to avoid further
18944 	    * confusion of the processor. This is a fatal error.
18945 	    */
18946 	    circ->children = NULL;
18947 	}
18948     }
18949 }
18950 
18951 /**
18952  * xmlSchemaModelGroupToModelGroupDefFixup:
18953  * @ctxt:  the parser context
18954  * @mg:  the model group
18955  *
18956  * Assigns the model group of model group definitions to the "term"
18957  * of the referencing particle.
18958  * In xmlSchemaResolveModelGroupParticleReferences the model group
18959  * definitions were assigned to the "term", since needed for the
18960  * circularity check.
18961  *
18962  * Schema Component Constraint:
18963  *     All Group Limited (cos-all-limited) (1.2)
18964  */
18965 static void
xmlSchemaModelGroupToModelGroupDefFixup(xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,xmlSchemaModelGroupPtr mg)18966 xmlSchemaModelGroupToModelGroupDefFixup(
18967     xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
18968     xmlSchemaModelGroupPtr mg)
18969 {
18970     xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
18971 
18972     while (particle != NULL) {
18973 	if ((WXS_PARTICLE_TERM(particle) == NULL) ||
18974 	    ((WXS_PARTICLE_TERM(particle))->type !=
18975 		XML_SCHEMA_TYPE_GROUP))
18976 	{
18977 	    particle = WXS_PTC_CAST particle->next;
18978 	    continue;
18979 	}
18980 	if (WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle)) == NULL) {
18981 	    /*
18982 	    * TODO: Remove the particle.
18983 	    */
18984 	    WXS_PARTICLE_TERM(particle) = NULL;
18985 	    particle = WXS_PTC_CAST particle->next;
18986 	    continue;
18987 	}
18988 	/*
18989 	* Assign the model group to the {term} of the particle.
18990 	*/
18991 	WXS_PARTICLE_TERM(particle) =
18992 	    WXS_TREE_CAST WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle));
18993 
18994 	particle = WXS_PTC_CAST particle->next;
18995     }
18996 }
18997 
18998 /**
18999  * xmlSchemaCheckAttrGroupCircularRecur:
19000  * @ctxtGr: the searched attribute group
19001  * @attr: the current attribute list to be processed
19002  *
19003  * This one is intended to be used by
19004  * xmlSchemaCheckAttrGroupCircular only.
19005  *
19006  * Returns the circular attribute grou reference, otherwise NULL.
19007  */
19008 static xmlSchemaQNameRefPtr
xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,xmlSchemaItemListPtr list)19009 xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,
19010 				     xmlSchemaItemListPtr list)
19011 {
19012     xmlSchemaAttributeGroupPtr gr;
19013     xmlSchemaQNameRefPtr ref, circ;
19014     int i;
19015     /*
19016     * We will search for an attribute group reference which
19017     * references the context attribute group.
19018     */
19019     for (i = 0; i < list->nbItems; i++) {
19020 	ref = list->items[i];
19021 	if ((ref->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19022 	    (ref->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
19023 	    (ref->item != NULL))
19024 	{
19025 	    gr = WXS_ATTR_GROUP_CAST ref->item;
19026 	    if (gr == ctxtGr)
19027 		return(ref);
19028 	    if (gr->flags & XML_SCHEMAS_ATTRGROUP_MARKED)
19029 		continue;
19030 	    /*
19031 	    * Mark as visited to avoid infinite recursion on
19032 	    * circular references not yet examined.
19033 	    */
19034 	    if ((gr->attrUses) &&
19035 		(gr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS))
19036 	    {
19037 		gr->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
19038 		circ = xmlSchemaCheckAttrGroupCircularRecur(ctxtGr,
19039 		    (xmlSchemaItemListPtr) gr->attrUses);
19040 		gr->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
19041 		if (circ != NULL)
19042 		    return (circ);
19043 	    }
19044 
19045 	}
19046     }
19047     return (NULL);
19048 }
19049 
19050 /**
19051  * xmlSchemaCheckAttrGroupCircular:
19052  * attrGr:  the attribute group definition
19053  * @ctxt:  the parser context
19054  * @name:  the name
19055  *
19056  * Checks for circular references of attribute groups.
19057  */
19058 static int
xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,xmlSchemaParserCtxtPtr ctxt)19059 xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
19060 				xmlSchemaParserCtxtPtr ctxt)
19061 {
19062     /*
19063     * Schema Representation Constraint:
19064     * Attribute Group Definition Representation OK
19065     * 3 Circular group reference is disallowed outside <redefine>.
19066     * That is, unless this element information item's parent is
19067     * <redefine>, then among the [children], if any, there must
19068     * not be an <attributeGroup> with ref [attribute] which resolves
19069     * to the component corresponding to this <attributeGroup>. Indirect
19070     * circularity is also ruled out. That is, when QName resolution
19071     * (Schema Document) (�3.15.3) is applied to a �QName� arising from
19072     * any <attributeGroup>s with a ref [attribute] among the [children],
19073     * it must not be the case that a �QName� is encountered at any depth
19074     * which resolves to the component corresponding to this <attributeGroup>.
19075     */
19076     if (attrGr->attrUses == NULL)
19077 	return(0);
19078     else if ((attrGr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS) == 0)
19079 	return(0);
19080     else {
19081 	xmlSchemaQNameRefPtr circ;
19082 
19083 	circ = xmlSchemaCheckAttrGroupCircularRecur(attrGr,
19084 	    (xmlSchemaItemListPtr) attrGr->attrUses);
19085 	if (circ != NULL) {
19086 	    xmlChar *str = NULL;
19087 	    /*
19088 	    * TODO: Report the referenced attr group as QName.
19089 	    */
19090 	    xmlSchemaPCustomErr(ctxt,
19091 		XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
19092 		NULL, WXS_ITEM_NODE(WXS_BASIC_CAST circ),
19093 		"Circular reference to the attribute group '%s' "
19094 		"defined", xmlSchemaGetComponentQName(&str, attrGr));
19095 	    FREE_AND_NULL(str);
19096 	    /*
19097 	    * NOTE: We will cut the reference to avoid further
19098 	    * confusion of the processor.
19099 	    * BADSPEC TODO: The spec should define how to process in this case.
19100 	    */
19101 	    circ->item = NULL;
19102 	    return(ctxt->err);
19103 	}
19104     }
19105     return(0);
19106 }
19107 
19108 static int
19109 xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19110 				  xmlSchemaAttributeGroupPtr attrGr);
19111 
19112 /**
19113  * xmlSchemaExpandAttributeGroupRefs:
19114  * @pctxt: the parser context
19115  * @node: the node of the component holding the attribute uses
19116  * @completeWild: the intersected wildcard to be returned
19117  * @list: the attribute uses
19118  *
19119  * Substitutes contained attribute group references
19120  * for their attribute uses. Wilcards are intersected.
19121  * Attribute use prohibitions are removed from the list
19122  * and returned via the @prohibs list.
19123  * Pointlessness of attr. prohibs, if a matching attr. decl
19124  * is existent a well, are checked.
19125  */
19126 static int
xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBasicItemPtr item,xmlSchemaWildcardPtr * completeWild,xmlSchemaItemListPtr list,xmlSchemaItemListPtr prohibs)19127 xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
19128 				  xmlSchemaBasicItemPtr item,
19129 				  xmlSchemaWildcardPtr *completeWild,
19130 				  xmlSchemaItemListPtr list,
19131 				  xmlSchemaItemListPtr prohibs)
19132 {
19133     xmlSchemaAttributeGroupPtr gr;
19134     xmlSchemaAttributeUsePtr use;
19135     xmlSchemaItemListPtr sublist;
19136     int i, j;
19137     int created = (*completeWild == NULL) ? 0 : 1;
19138 
19139     if (prohibs)
19140 	prohibs->nbItems = 0;
19141 
19142     for (i = 0; i < list->nbItems; i++) {
19143 	use = list->items[i];
19144 
19145 	if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
19146 	    if (prohibs == NULL) {
19147 		PERROR_INT("xmlSchemaExpandAttributeGroupRefs",
19148 		    "unexpected attr prohibition found");
19149 		return(-1);
19150 	    }
19151 	    /*
19152 	    * Remove from attribute uses.
19153 	    */
19154 	    if (xmlSchemaItemListRemove(list, i) == -1)
19155 		return(-1);
19156 	    i--;
19157 	    /*
19158 	    * Note that duplicate prohibitions were already
19159 	    * handled at parsing time.
19160 	    */
19161 	    /*
19162 	    * Add to list of prohibitions.
19163 	    */
19164 	    xmlSchemaItemListAddSize(prohibs, 2, use);
19165 	    continue;
19166 	}
19167 	if ((use->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19168 	    ((WXS_QNAME_CAST use)->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP))
19169 	{
19170 	    if ((WXS_QNAME_CAST use)->item == NULL)
19171 		return(-1);
19172 	    gr = WXS_ATTR_GROUP_CAST (WXS_QNAME_CAST use)->item;
19173 	    /*
19174 	    * Expand the referenced attr. group.
19175 	    * TODO: remove this, this is done in a previous step, so
19176 	    * already done here.
19177 	    */
19178 	    if ((gr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
19179 		if (xmlSchemaAttributeGroupExpandRefs(pctxt, gr) == -1)
19180 		    return(-1);
19181 	    }
19182 	    /*
19183 	    * Build the 'complete' wildcard; i.e. intersect multiple
19184 	    * wildcards.
19185 	    */
19186 	    if (gr->attributeWildcard != NULL) {
19187 		if (*completeWild == NULL) {
19188 		    *completeWild = gr->attributeWildcard;
19189 		} else {
19190 		    if (! created) {
19191 			xmlSchemaWildcardPtr tmpWild;
19192 
19193 			 /*
19194 			* Copy the first encountered wildcard as context,
19195 			* except for the annotation.
19196 			*
19197 			* Although the complete wildcard might not correspond
19198 			* to any node in the schema, we will anchor it on
19199 			* the node of the owner component.
19200 			*/
19201 			tmpWild =  xmlSchemaAddWildcard(pctxt, pctxt->schema,
19202 			    XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
19203 			    WXS_ITEM_NODE(item));
19204 			if (tmpWild == NULL)
19205 			    return(-1);
19206 			if (xmlSchemaCloneWildcardNsConstraints(pctxt,
19207 			    tmpWild, *completeWild) == -1)
19208 			    return (-1);
19209 			tmpWild->processContents = (*completeWild)->processContents;
19210 			*completeWild = tmpWild;
19211 			created = 1;
19212 		    }
19213 
19214 		    if (xmlSchemaIntersectWildcards(pctxt, *completeWild,
19215 			gr->attributeWildcard) == -1)
19216 			return(-1);
19217 		}
19218 	    }
19219 	    /*
19220 	    * Just remove the reference if the referenced group does not
19221 	    * contain any attribute uses.
19222 	    */
19223 	    sublist = ((xmlSchemaItemListPtr) gr->attrUses);
19224 	    if ((sublist == NULL) || sublist->nbItems == 0) {
19225 		if (xmlSchemaItemListRemove(list, i) == -1)
19226 		    return(-1);
19227 		i--;
19228 		continue;
19229 	    }
19230 	    /*
19231 	    * Add the attribute uses.
19232 	    */
19233 	    list->items[i] = sublist->items[0];
19234 	    if (sublist->nbItems != 1) {
19235 		for (j = 1; j < sublist->nbItems; j++) {
19236 		    i++;
19237 		    if (xmlSchemaItemListInsert(list,
19238 			    sublist->items[j], i) == -1)
19239 			return(-1);
19240 		}
19241 	    }
19242 	}
19243 
19244     }
19245     /*
19246     * Handle pointless prohibitions of declared attributes.
19247     */
19248     if (prohibs && (prohibs->nbItems != 0) && (list->nbItems != 0)) {
19249 	xmlSchemaAttributeUseProhibPtr prohib;
19250 
19251 	for (i = prohibs->nbItems -1; i >= 0; i--) {
19252 	    prohib = prohibs->items[i];
19253 	    for (j = 0; j < list->nbItems; j++) {
19254 		use = list->items[j];
19255 
19256 		if ((prohib->name == WXS_ATTRUSE_DECL_NAME(use)) &&
19257 		    (prohib->targetNamespace == WXS_ATTRUSE_DECL_TNS(use)))
19258 		{
19259 		    xmlChar *str = NULL;
19260 
19261 		    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
19262 			XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
19263 			prohib->node, NULL,
19264 			"Skipping pointless attribute use prohibition "
19265 			"'%s', since a corresponding attribute use "
19266 			"exists already in the type definition",
19267 			xmlSchemaFormatQName(&str,
19268 			    prohib->targetNamespace, prohib->name),
19269 			NULL, NULL);
19270 		    FREE_AND_NULL(str);
19271 		    /*
19272 		    * Remove the prohibition.
19273 		    */
19274 		    if (xmlSchemaItemListRemove(prohibs, i) == -1)
19275 			return(-1);
19276 		    break;
19277 		}
19278 	    }
19279 	}
19280     }
19281     return(0);
19282 }
19283 
19284 /**
19285  * xmlSchemaAttributeGroupExpandRefs:
19286  * @pctxt:  the parser context
19287  * @attrGr:  the attribute group definition
19288  *
19289  * Computation of:
19290  * {attribute uses} property
19291  * {attribute wildcard} property
19292  *
19293  * Substitutes contained attribute group references
19294  * for their attribute uses. Wilcards are intersected.
19295  */
19296 static int
xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,xmlSchemaAttributeGroupPtr attrGr)19297 xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19298 				  xmlSchemaAttributeGroupPtr attrGr)
19299 {
19300     if ((attrGr->attrUses == NULL) ||
19301 	(attrGr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED))
19302 	return(0);
19303 
19304     attrGr->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
19305     if (xmlSchemaExpandAttributeGroupRefs(pctxt, WXS_BASIC_CAST attrGr,
19306 	&(attrGr->attributeWildcard), attrGr->attrUses, NULL) == -1)
19307 	return(-1);
19308     return(0);
19309 }
19310 
19311 /**
19312  * xmlSchemaAttributeGroupExpandRefs:
19313  * @pctxt:  the parser context
19314  * @attrGr:  the attribute group definition
19315  *
19316  * Substitutes contained attribute group references
19317  * for their attribute uses. Wilcards are intersected.
19318  *
19319  * Schema Component Constraint:
19320  *    Attribute Group Definition Properties Correct (ag-props-correct)
19321  */
19322 static int
xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,xmlSchemaAttributeGroupPtr attrGr)19323 xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19324 				  xmlSchemaAttributeGroupPtr attrGr)
19325 {
19326     /*
19327     * SPEC ag-props-correct
19328     * (1) "The values of the properties of an attribute group definition
19329     * must be as described in the property tableau in The Attribute
19330     * Group Definition Schema Component (�3.6.1), modulo the impact of
19331     * Missing Sub-components (�5.3);"
19332     */
19333 
19334     if ((attrGr->attrUses != NULL) &&
19335 	(WXS_LIST_CAST attrGr->attrUses)->nbItems > 1)
19336     {
19337 	xmlSchemaItemListPtr uses = WXS_LIST_CAST attrGr->attrUses;
19338 	xmlSchemaAttributeUsePtr use, tmp;
19339 	int i, j, hasId = 0;
19340 
19341 	for (i = uses->nbItems -1; i >= 0; i--) {
19342 	    use = uses->items[i];
19343 	    /*
19344 	    * SPEC ag-props-correct
19345 	    * (2) "Two distinct members of the {attribute uses} must not have
19346 	    * {attribute declaration}s both of whose {name}s match and whose
19347 	    * {target namespace}s are identical."
19348 	    */
19349 	    if (i > 0) {
19350 		for (j = i -1; j >= 0; j--) {
19351 		    tmp = uses->items[j];
19352 		    if ((WXS_ATTRUSE_DECL_NAME(use) ==
19353 			WXS_ATTRUSE_DECL_NAME(tmp)) &&
19354 			(WXS_ATTRUSE_DECL_TNS(use) ==
19355 			WXS_ATTRUSE_DECL_TNS(tmp)))
19356 		    {
19357 			xmlChar *str = NULL;
19358 
19359 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
19360 			    XML_SCHEMAP_AG_PROPS_CORRECT,
19361 			    attrGr->node, WXS_BASIC_CAST attrGr,
19362 			    "Duplicate %s",
19363 			    xmlSchemaGetComponentDesignation(&str, use),
19364 			    NULL);
19365 			FREE_AND_NULL(str);
19366 			/*
19367 			* Remove the duplicate.
19368 			*/
19369 			if (xmlSchemaItemListRemove(uses, i) == -1)
19370 			    return(-1);
19371 			goto next_use;
19372 		    }
19373 		}
19374 	    }
19375 	    /*
19376 	    * SPEC ag-props-correct
19377 	    * (3) "Two distinct members of the {attribute uses} must not have
19378 	    * {attribute declaration}s both of whose {type definition}s are or
19379 	    * are derived from ID."
19380 	    * TODO: Does 'derived' include member-types of unions?
19381 	    */
19382 	    if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
19383 		if (xmlSchemaIsDerivedFromBuiltInType(
19384 		    WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
19385 		{
19386 		    if (hasId) {
19387 			xmlChar *str = NULL;
19388 
19389 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
19390 			    XML_SCHEMAP_AG_PROPS_CORRECT,
19391 			    attrGr->node, WXS_BASIC_CAST attrGr,
19392 			    "There must not exist more than one attribute "
19393 			    "declaration of type 'xs:ID' "
19394 			    "(or derived from 'xs:ID'). The %s violates this "
19395 			    "constraint",
19396 			    xmlSchemaGetComponentDesignation(&str, use),
19397 			    NULL);
19398 			FREE_AND_NULL(str);
19399 			if (xmlSchemaItemListRemove(uses, i) == -1)
19400 			    return(-1);
19401 		    }
19402 		    hasId = 1;
19403 		}
19404 	    }
19405 next_use: {}
19406 	}
19407     }
19408     return(0);
19409 }
19410 
19411 /**
19412  * xmlSchemaResolveAttrGroupReferences:
19413  * @attrgrpDecl:  the schema attribute definition
19414  * @ctxt:  the schema parser context
19415  * @name:  the attribute name
19416  *
19417  * Resolves references to attribute group definitions.
19418  */
19419 static int
xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,xmlSchemaParserCtxtPtr ctxt)19420 xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,
19421 				    xmlSchemaParserCtxtPtr ctxt)
19422 {
19423     xmlSchemaAttributeGroupPtr group;
19424 
19425     if (ref->item != NULL)
19426         return(0);
19427     group = xmlSchemaGetAttributeGroup(ctxt->schema,
19428 	ref->name,
19429 	ref->targetNamespace);
19430     if (group == NULL) {
19431 	xmlSchemaPResCompAttrErr(ctxt,
19432 	    XML_SCHEMAP_SRC_RESOLVE,
19433 	    NULL, ref->node,
19434 	    "ref", ref->name, ref->targetNamespace,
19435 	    ref->itemType, NULL);
19436 	return(ctxt->err);
19437     }
19438     ref->item = WXS_BASIC_CAST group;
19439     return(0);
19440 }
19441 
19442 /**
19443  * xmlSchemaCheckAttrPropsCorrect:
19444  * @item:  an schema attribute declaration/use
19445  * @ctxt:  a schema parser context
19446  * @name:  the name of the attribute
19447  *
19448  *
19449  * Schema Component Constraint:
19450  *    Attribute Declaration Properties Correct (a-props-correct)
19451  *
19452  * Validates the value constraints of an attribute declaration/use.
19453  * NOTE that this needs the simle type definitions to be already
19454  *   builded and checked.
19455  */
19456 static int
xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,xmlSchemaAttributePtr attr)19457 xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19458 			       xmlSchemaAttributePtr attr)
19459 {
19460 
19461     /*
19462     * SPEC a-props-correct (1)
19463     * "The values of the properties of an attribute declaration must
19464     * be as described in the property tableau in The Attribute
19465     * Declaration Schema Component (�3.2.1), modulo the impact of
19466     * Missing Sub-components (�5.3)."
19467     */
19468 
19469     if (WXS_ATTR_TYPEDEF(attr) == NULL)
19470 	return(0);
19471 
19472     if (attr->defValue != NULL) {
19473 	int ret;
19474 
19475 	/*
19476 	* SPEC a-props-correct (3)
19477 	* "If the {type definition} is or is derived from ID then there
19478 	* must not be a {value constraint}."
19479 	*/
19480 	if (xmlSchemaIsDerivedFromBuiltInType(
19481 	    WXS_ATTR_TYPEDEF(attr), XML_SCHEMAS_ID))
19482 	{
19483 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
19484 		XML_SCHEMAP_A_PROPS_CORRECT_3,
19485 		NULL, WXS_BASIC_CAST attr,
19486 		"Value constraints are not allowed if the type definition "
19487 		"is or is derived from xs:ID",
19488 		NULL, NULL);
19489 	    return(pctxt->err);
19490 	}
19491 	/*
19492 	* SPEC a-props-correct (2)
19493 	* "if there is a {value constraint}, the canonical lexical
19494 	* representation of its value must be �valid� with respect
19495 	* to the {type definition} as defined in String Valid (�3.14.4)."
19496 	* TODO: Don't care about the *cononical* stuff here, this requirement
19497 	* will be removed in WXS 1.1 anyway.
19498 	*/
19499 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt,
19500 	    attr->node, WXS_ATTR_TYPEDEF(attr),
19501 	    attr->defValue, &(attr->defVal),
19502 	    1, 1, 0);
19503 	if (ret != 0) {
19504 	    if (ret < 0) {
19505 		PERROR_INT("xmlSchemaCheckAttrPropsCorrect",
19506 		    "calling xmlSchemaVCheckCVCSimpleType()");
19507 		return(-1);
19508 	    }
19509 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
19510 		XML_SCHEMAP_A_PROPS_CORRECT_2,
19511 		NULL, WXS_BASIC_CAST attr,
19512 		"The value of the value constraint is not valid",
19513 		NULL, NULL);
19514 	    return(pctxt->err);
19515 	}
19516     }
19517 
19518     return(0);
19519 }
19520 
19521 static xmlSchemaElementPtr
xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,xmlSchemaElementPtr ancestor)19522 xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
19523 				 xmlSchemaElementPtr ancestor)
19524 {
19525     xmlSchemaElementPtr ret;
19526 
19527     if (WXS_SUBST_HEAD(ancestor) == NULL)
19528 	return (NULL);
19529     if (WXS_SUBST_HEAD(ancestor) == elemDecl)
19530 	return (ancestor);
19531 
19532     if (WXS_SUBST_HEAD(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
19533 	return (NULL);
19534     WXS_SUBST_HEAD(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
19535     ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
19536 	WXS_SUBST_HEAD(ancestor));
19537     WXS_SUBST_HEAD(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
19538 
19539     return (ret);
19540 }
19541 
19542 /**
19543  * xmlSchemaCheckElemPropsCorrect:
19544  * @ctxt:  a schema parser context
19545  * @decl: the element declaration
19546  * @name:  the name of the attribute
19547  *
19548  * Schema Component Constraint:
19549  * Element Declaration Properties Correct (e-props-correct)
19550  *
19551  * STATUS:
19552  *   missing: (6)
19553  */
19554 static int
xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,xmlSchemaElementPtr elemDecl)19555 xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19556 			       xmlSchemaElementPtr elemDecl)
19557 {
19558     int ret = 0;
19559     xmlSchemaTypePtr typeDef = WXS_ELEM_TYPEDEF(elemDecl);
19560     /*
19561     * SPEC (1) "The values of the properties of an element declaration
19562     * must be as described in the property tableau in The Element
19563     * Declaration Schema Component (�3.3.1), modulo the impact of Missing
19564     * Sub-components (�5.3)."
19565     */
19566     if (WXS_SUBST_HEAD(elemDecl) != NULL) {
19567 	xmlSchemaElementPtr head = WXS_SUBST_HEAD(elemDecl), circ;
19568 
19569 	xmlSchemaCheckElementDeclComponent(head, pctxt);
19570 	/*
19571 	* SPEC (3) "If there is a non-�absent� {substitution group
19572 	* affiliation}, then {scope} must be global."
19573 	*/
19574 	if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
19575 	    xmlSchemaPCustomErr(pctxt,
19576 		XML_SCHEMAP_E_PROPS_CORRECT_3,
19577 		WXS_BASIC_CAST elemDecl, NULL,
19578 		"Only global element declarations can have a "
19579 		"substitution group affiliation", NULL);
19580 	    ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
19581 	}
19582 	/*
19583 	* TODO: SPEC (6) "Circular substitution groups are disallowed.
19584 	* That is, it must not be possible to return to an element declaration
19585 	* by repeatedly following the {substitution group affiliation}
19586 	* property."
19587 	*/
19588 	if (head == elemDecl)
19589 	    circ = head;
19590 	else if (WXS_SUBST_HEAD(head) != NULL)
19591 	    circ = xmlSchemaCheckSubstGroupCircular(head, head);
19592 	else
19593 	    circ = NULL;
19594 	if (circ != NULL) {
19595 	    xmlChar *strA = NULL, *strB = NULL;
19596 
19597 	    xmlSchemaPCustomErrExt(pctxt,
19598 		XML_SCHEMAP_E_PROPS_CORRECT_6,
19599 		WXS_BASIC_CAST circ, NULL,
19600 		"The element declaration '%s' defines a circular "
19601 		"substitution group to element declaration '%s'",
19602 		xmlSchemaGetComponentQName(&strA, circ),
19603 		xmlSchemaGetComponentQName(&strB, head),
19604 		NULL);
19605 	    FREE_AND_NULL(strA)
19606 	    FREE_AND_NULL(strB)
19607 	    ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
19608 	}
19609 	/*
19610 	* SPEC (4) "If there is a {substitution group affiliation},
19611 	* the {type definition}
19612 	* of the element declaration must be validly derived from the {type
19613 	* definition} of the {substitution group affiliation}, given the value
19614 	* of the {substitution group exclusions} of the {substitution group
19615 	* affiliation}, as defined in Type Derivation OK (Complex) (�3.4.6)
19616 	* (if the {type definition} is complex) or as defined in
19617 	* Type Derivation OK (Simple) (�3.14.6) (if the {type definition} is
19618 	* simple)."
19619 	*
19620 	* NOTE: {substitution group exclusions} means the values of the
19621 	* attribute "final".
19622 	*/
19623 
19624 	if (typeDef != WXS_ELEM_TYPEDEF(WXS_SUBST_HEAD(elemDecl))) {
19625 	    int set = 0;
19626 
19627 	    if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
19628 		set |= SUBSET_EXTENSION;
19629 	    if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
19630 		set |= SUBSET_RESTRICTION;
19631 
19632 	    if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST pctxt, typeDef,
19633 		WXS_ELEM_TYPEDEF(head), set) != 0) {
19634 		xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
19635 
19636 		ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
19637 		xmlSchemaPCustomErrExt(pctxt,
19638 		    XML_SCHEMAP_E_PROPS_CORRECT_4,
19639 		    WXS_BASIC_CAST elemDecl, NULL,
19640 		    "The type definition '%s' was "
19641 		    "either rejected by the substitution group "
19642 		    "affiliation '%s', or not validly derived from its type "
19643 		    "definition '%s'",
19644 		    xmlSchemaGetComponentQName(&strA, typeDef),
19645 		    xmlSchemaGetComponentQName(&strB, head),
19646 		    xmlSchemaGetComponentQName(&strC, WXS_ELEM_TYPEDEF(head)));
19647 		FREE_AND_NULL(strA)
19648 		FREE_AND_NULL(strB)
19649 		FREE_AND_NULL(strC)
19650 	    }
19651 	}
19652     }
19653     /*
19654     * SPEC (5) "If the {type definition} or {type definition}'s
19655     * {content type}
19656     * is or is derived from ID then there must not be a {value constraint}.
19657     * Note: The use of ID as a type definition for elements goes beyond
19658     * XML 1.0, and should be avoided if backwards compatibility is desired"
19659     */
19660     if ((elemDecl->value != NULL) &&
19661 	((WXS_IS_SIMPLE(typeDef) &&
19662 	  xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
19663 	 (WXS_IS_COMPLEX(typeDef) &&
19664 	  WXS_HAS_SIMPLE_CONTENT(typeDef) &&
19665 	  xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
19666 	    XML_SCHEMAS_ID)))) {
19667 
19668 	ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
19669 	xmlSchemaPCustomErr(pctxt,
19670 	    XML_SCHEMAP_E_PROPS_CORRECT_5,
19671 	    WXS_BASIC_CAST elemDecl, NULL,
19672 	    "The type definition (or type definition's content type) is or "
19673 	    "is derived from ID; value constraints are not allowed in "
19674 	    "conjunction with such a type definition", NULL);
19675     } else if (elemDecl->value != NULL) {
19676 	int vcret;
19677 	xmlNodePtr node = NULL;
19678 
19679 	/*
19680 	* SPEC (2) "If there is a {value constraint}, the canonical lexical
19681 	* representation of its value must be �valid� with respect to the
19682 	* {type definition} as defined in Element Default Valid (Immediate)
19683 	* (�3.3.6)."
19684 	*/
19685 	if (typeDef == NULL) {
19686 	    xmlSchemaPErr(pctxt, elemDecl->node,
19687 		XML_SCHEMAP_INTERNAL,
19688 		"Internal error: xmlSchemaCheckElemPropsCorrect, "
19689 		"type is missing... skipping validation of "
19690 		"the value constraint", NULL, NULL);
19691 	    return (-1);
19692 	}
19693 	if (elemDecl->node != NULL) {
19694 	    if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
19695 		node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19696 		    BAD_CAST "fixed");
19697 	    else
19698 		node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19699 		    BAD_CAST "default");
19700 	}
19701 	vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
19702 	    typeDef, elemDecl->value, &(elemDecl->defVal));
19703 	if (vcret != 0) {
19704 	    if (vcret < 0) {
19705 		PERROR_INT("xmlSchemaElemCheckValConstr",
19706 		    "failed to validate the value constraint of an "
19707 		    "element declaration");
19708 		return (-1);
19709 	    }
19710 	    return (vcret);
19711 	}
19712     }
19713 
19714     return (ret);
19715 }
19716 
19717 /**
19718  * xmlSchemaCheckElemSubstGroup:
19719  * @ctxt:  a schema parser context
19720  * @decl: the element declaration
19721  * @name:  the name of the attribute
19722  *
19723  * Schema Component Constraint:
19724  * Substitution Group (cos-equiv-class)
19725  *
19726  * In Libxml2 the subst. groups will be precomputed, in terms of that
19727  * a list will be built for each subst. group head, holding all direct
19728  * referents to this head.
19729  * NOTE that this function needs:
19730  *   1. circular subst. groups to be checked beforehand
19731  *   2. the declaration's type to be derived from the head's type
19732  *
19733  * STATUS:
19734  *
19735  */
19736 static void
xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,xmlSchemaElementPtr elemDecl)19737 xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
19738 			     xmlSchemaElementPtr elemDecl)
19739 {
19740     if ((WXS_SUBST_HEAD(elemDecl) == NULL) ||
19741 	/* SPEC (1) "Its {abstract} is false." */
19742 	(elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
19743 	return;
19744     {
19745 	xmlSchemaElementPtr head;
19746 	xmlSchemaTypePtr headType, type;
19747 	int set, methSet;
19748 	/*
19749 	* SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
19750 	* {disallowed substitutions} as the blocking constraint, as defined in
19751 	* Substitution Group OK (Transitive) (�3.3.6)."
19752 	*/
19753 	for (head = WXS_SUBST_HEAD(elemDecl); head != NULL;
19754 	    head = WXS_SUBST_HEAD(head)) {
19755 	    set = 0;
19756 	    methSet = 0;
19757 	    /*
19758 	    * The blocking constraints.
19759 	    */
19760 	    if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
19761 		continue;
19762 	    headType = head->subtypes;
19763 	    type = elemDecl->subtypes;
19764 	    if (headType == type)
19765 		goto add_member;
19766 	    if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
19767 		set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19768 	    if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
19769 		set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19770 	    /*
19771 	    * SPEC: Substitution Group OK (Transitive) (2.3)
19772 	    * "The set of all {derivation method}s involved in the
19773 	    * derivation of D's {type definition} from C's {type definition}
19774 	    * does not intersect with the union of the blocking constraint,
19775 	    * C's {prohibited substitutions} (if C is complex, otherwise the
19776 	    * empty set) and the {prohibited substitutions} (respectively the
19777 	    * empty set) of any intermediate {type definition}s in the
19778 	    * derivation of D's {type definition} from C's {type definition}."
19779 	    */
19780 	    /*
19781 	    * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
19782 	    * subst.head axis, the methSet does not need to be computed for
19783 	    * the full depth over and over.
19784 	    */
19785 	    /*
19786 	    * The set of all {derivation method}s involved in the derivation
19787 	    */
19788 	    while ((type != NULL) && (type != headType)) {
19789 		if ((WXS_IS_EXTENSION(type)) &&
19790 		    ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19791 		    methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19792 
19793 		if (WXS_IS_RESTRICTION(type) &&
19794 		    ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19795 		    methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19796 
19797 		type = type->baseType;
19798 	    }
19799 	    /*
19800 	    * The {prohibited substitutions} of all intermediate types +
19801 	    * the head's type.
19802 	    */
19803 	    type = elemDecl->subtypes->baseType;
19804 	    while (type != NULL) {
19805 		if (WXS_IS_COMPLEX(type)) {
19806 		    if ((type->flags &
19807 			    XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19808 			((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
19809 		    set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19810 		    if ((type->flags &
19811 			    XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19812 			((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19813 		    set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19814 		} else
19815 		    break;
19816 		if (type == headType)
19817 		    break;
19818 		type = type->baseType;
19819 	    }
19820 	    if ((set != 0) &&
19821 		(((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19822 		(methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
19823 		((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19824 		(methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
19825 		continue;
19826 	    }
19827 add_member:
19828 	    xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
19829 	    if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
19830 		head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
19831 	}
19832     }
19833 }
19834 
19835 #ifdef WXS_ELEM_DECL_CONS_ENABLED /* enable when finished */
19836 /**
19837  * xmlSchemaCheckElementDeclComponent
19838  * @pctxt: the schema parser context
19839  * @ctxtComponent: the context component (an element declaration)
19840  * @ctxtParticle: the first particle of the context component
19841  * @searchParticle: the element declaration particle to be analysed
19842  *
19843  * Schema Component Constraint: Element Declarations Consistent
19844  */
19845 static int
xmlSchemaCheckElementDeclConsistent(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBasicItemPtr ctxtComponent,xmlSchemaParticlePtr ctxtParticle,xmlSchemaParticlePtr searchParticle,xmlSchemaParticlePtr curParticle,int search)19846 xmlSchemaCheckElementDeclConsistent(xmlSchemaParserCtxtPtr pctxt,
19847 				    xmlSchemaBasicItemPtr ctxtComponent,
19848 				    xmlSchemaParticlePtr ctxtParticle,
19849 				    xmlSchemaParticlePtr searchParticle,
19850 				    xmlSchemaParticlePtr curParticle,
19851 				    int search)
19852 {
19853     return(0);
19854 
19855     int ret = 0;
19856     xmlSchemaParticlePtr cur = curParticle;
19857     if (curParticle == NULL) {
19858 	return(0);
19859     }
19860     if (WXS_PARTICLE_TERM(curParticle) == NULL) {
19861 	/*
19862 	* Just return in this case. A missing "term" of the particle
19863 	* might arise due to an invalid "term" component.
19864 	*/
19865 	return(0);
19866     }
19867     while (cur != NULL) {
19868 	switch (WXS_PARTICLE_TERM(cur)->type) {
19869 	    case XML_SCHEMA_TYPE_ANY:
19870 		break;
19871 	    case XML_SCHEMA_TYPE_ELEMENT:
19872 		if (search == 0) {
19873 		    ret = xmlSchemaCheckElementDeclConsistent(pctxt,
19874 			ctxtComponent, ctxtParticle, cur, ctxtParticle, 1);
19875 		    if (ret != 0)
19876 			return(ret);
19877 		} else {
19878 		    xmlSchemaElementPtr elem =
19879 			WXS_ELEM_CAST(WXS_PARTICLE_TERM(cur));
19880 		    /*
19881 		    * SPEC Element Declarations Consistent:
19882 		    * "If the {particles} contains, either directly,
19883 		    * indirectly (that is, within the {particles} of a
19884 		    * contained model group, recursively) or �implicitly�
19885 		    * two or more element declaration particles with
19886 		    * the same {name} and {target namespace}, then
19887 		    * all their type definitions must be the same
19888 		    * top-level definition [...]"
19889 		    */
19890 		    if (xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->name,
19891 			    WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->name) &&
19892 			xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
19893 			    WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->targetNamespace))
19894 		    {
19895 			xmlChar *strA = NULL, *strB = NULL;
19896 
19897 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
19898 			    /* TODO: error code */
19899 			    XML_SCHEMAP_COS_NONAMBIG,
19900 			    WXS_ITEM_NODE(cur), NULL,
19901 			    "In the content model of %s, there are multiple "
19902 			    "element declarations for '%s' with different "
19903 			    "type definitions",
19904 			    xmlSchemaGetComponentDesignation(&strA,
19905 				ctxtComponent),
19906 			    xmlSchemaFormatQName(&strB,
19907 				WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
19908 				WXS_PARTICLE_TERM_AS_ELEM(cur)->name));
19909 			FREE_AND_NULL(strA);
19910 			FREE_AND_NULL(strB);
19911 			return(XML_SCHEMAP_COS_NONAMBIG);
19912 		    }
19913 		}
19914 		break;
19915 	    case XML_SCHEMA_TYPE_SEQUENCE: {
19916 		break;
19917 		}
19918 	    case XML_SCHEMA_TYPE_CHOICE:{
19919 		/*
19920 		xmlSchemaTreeItemPtr sub;
19921 
19922 		sub = WXS_PARTICLE_TERM(particle)->children;  (xmlSchemaParticlePtr)
19923 		while (sub != NULL) {
19924 		    ret = xmlSchemaCheckElementDeclConsistent(pctxt, ctxtComponent,
19925 			ctxtParticle, ctxtElem);
19926 		    if (ret != 0)
19927 			return(ret);
19928 		    sub = sub->next;
19929 		}
19930 		*/
19931 		break;
19932 		}
19933 	    case XML_SCHEMA_TYPE_ALL:
19934 		break;
19935 	    case XML_SCHEMA_TYPE_GROUP:
19936 		break;
19937 	    default:
19938 		xmlSchemaInternalErr2(ACTXT_CAST pctxt,
19939 		    "xmlSchemaCheckElementDeclConsistent",
19940 		    "found unexpected term of type '%s' in content model",
19941 		    WXS_ITEM_TYPE_NAME(WXS_PARTICLE_TERM(cur)), NULL);
19942 		return(-1);
19943 	}
19944 	cur = (xmlSchemaParticlePtr) cur->next;
19945     }
19946 
19947 exit:
19948     return(ret);
19949 }
19950 #endif
19951 
19952 /**
19953  * xmlSchemaCheckElementDeclComponent
19954  * @item:  an schema element declaration/particle
19955  * @ctxt:  a schema parser context
19956  * @name:  the name of the attribute
19957  *
19958  * Validates the value constraints of an element declaration.
19959  * Adds substitution group members.
19960  */
19961 static void
xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,xmlSchemaParserCtxtPtr ctxt)19962 xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
19963 				   xmlSchemaParserCtxtPtr ctxt)
19964 {
19965     if (elemDecl == NULL)
19966 	return;
19967     if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
19968 	return;
19969     elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
19970     if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0) {
19971 	/*
19972 	* Adds substitution group members.
19973 	*/
19974 	xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
19975     }
19976 }
19977 
19978 /**
19979  * xmlSchemaResolveModelGroupParticleReferences:
19980  * @particle:  a particle component
19981  * @ctxt:  a parser context
19982  *
19983  * Resolves references of a model group's {particles} to
19984  * model group definitions and to element declarations.
19985  */
19986 static void
xmlSchemaResolveModelGroupParticleReferences(xmlSchemaParserCtxtPtr ctxt,xmlSchemaModelGroupPtr mg)19987 xmlSchemaResolveModelGroupParticleReferences(
19988     xmlSchemaParserCtxtPtr ctxt,
19989     xmlSchemaModelGroupPtr mg)
19990 {
19991     xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
19992     xmlSchemaQNameRefPtr ref;
19993     xmlSchemaBasicItemPtr refItem;
19994 
19995     /*
19996     * URGENT TODO: Test this.
19997     */
19998     while (particle != NULL) {
19999 	if ((WXS_PARTICLE_TERM(particle) == NULL) ||
20000 	    ((WXS_PARTICLE_TERM(particle))->type !=
20001 		XML_SCHEMA_EXTRA_QNAMEREF))
20002 	{
20003 	    goto next_particle;
20004 	}
20005 	ref = WXS_QNAME_CAST WXS_PARTICLE_TERM(particle);
20006 	/*
20007 	* Resolve the reference.
20008 	* NULL the {term} by default.
20009 	*/
20010 	particle->children = NULL;
20011 
20012 	refItem = xmlSchemaGetNamedComponent(ctxt->schema,
20013 	    ref->itemType, ref->name, ref->targetNamespace);
20014 	if (refItem == NULL) {
20015 	    xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
20016 		NULL, WXS_ITEM_NODE(particle), "ref", ref->name,
20017 		ref->targetNamespace, ref->itemType, NULL);
20018 	    /* TODO: remove the particle. */
20019 	    goto next_particle;
20020 	}
20021 	if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
20022 	    if (WXS_MODELGROUPDEF_MODEL(refItem) == NULL)
20023 		/* TODO: remove the particle. */
20024 		goto next_particle;
20025 	    /*
20026 	    * NOTE that we will assign the model group definition
20027 	    * itself to the "term" of the particle. This will ease
20028 	    * the check for circular model group definitions. After
20029 	    * that the "term" will be assigned the model group of the
20030 	    * model group definition.
20031 	    */
20032 	    if ((WXS_MODELGROUPDEF_MODEL(refItem))->type ==
20033 		    XML_SCHEMA_TYPE_ALL) {
20034 		/*
20035 		* SPEC cos-all-limited (1)
20036 		* SPEC cos-all-limited (1.2)
20037 		* "It appears only as the value of one or both of the
20038 		* following properties:"
20039 		* (1.1) "the {model group} property of a model group
20040 		*        definition."
20041 		* (1.2) "the {term} property of a particle [... of] the "
20042 		* {content type} of a complex type definition."
20043 		*/
20044 		xmlSchemaCustomErr(ACTXT_CAST ctxt,
20045 		    /* TODO: error code */
20046 		    XML_SCHEMAP_COS_ALL_LIMITED,
20047 		    WXS_ITEM_NODE(particle), NULL,
20048 		    "A model group definition is referenced, but "
20049 		    "it contains an 'all' model group, which "
20050 		    "cannot be contained by model groups",
20051 		    NULL, NULL);
20052 		/* TODO: remove the particle. */
20053 		goto next_particle;
20054 	    }
20055 	    particle->children = (xmlSchemaTreeItemPtr) refItem;
20056 	} else {
20057 	    /*
20058 	    * TODO: Are referenced element declarations the only
20059 	    * other components we expect here?
20060 	    */
20061 	    particle->children = (xmlSchemaTreeItemPtr) refItem;
20062 	}
20063 next_particle:
20064 	particle = WXS_PTC_CAST particle->next;
20065     }
20066 }
20067 
20068 static int
xmlSchemaAreValuesEqual(xmlSchemaValPtr x,xmlSchemaValPtr y)20069 xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
20070 		       xmlSchemaValPtr y)
20071 {
20072     xmlSchemaTypePtr tx, ty, ptx, pty;
20073     int ret;
20074 
20075     while (x != NULL) {
20076 	/* Same types. */
20077 	tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
20078 	ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
20079 	ptx = xmlSchemaGetPrimitiveType(tx);
20080 	pty = xmlSchemaGetPrimitiveType(ty);
20081 	/*
20082 	* (1) if a datatype T' is �derived� by �restriction� from an
20083 	* atomic datatype T then the �value space� of T' is a subset of
20084 	* the �value space� of T. */
20085 	/*
20086 	* (2) if datatypes T' and T'' are �derived� by �restriction�
20087 	* from a common atomic ancestor T then the �value space�s of T'
20088 	* and T'' may overlap.
20089 	*/
20090 	if (ptx != pty)
20091 	    return(0);
20092 	/*
20093 	* We assume computed values to be normalized, so do a fast
20094 	* string comparison for string based types.
20095 	*/
20096 	if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
20097 	    WXS_IS_ANY_SIMPLE_TYPE(ptx)) {
20098 	    if (! xmlStrEqual(
20099 		xmlSchemaValueGetAsString(x),
20100 		xmlSchemaValueGetAsString(y)))
20101 		return (0);
20102 	} else {
20103 	    ret = xmlSchemaCompareValuesWhtsp(
20104 		x, XML_SCHEMA_WHITESPACE_PRESERVE,
20105 		y, XML_SCHEMA_WHITESPACE_PRESERVE);
20106 	    if (ret == -2)
20107 		return(-1);
20108 	    if (ret != 0)
20109 		return(0);
20110 	}
20111 	/*
20112 	* Lists.
20113 	*/
20114 	x = xmlSchemaValueGetNext(x);
20115 	if (x != NULL) {
20116 	    y = xmlSchemaValueGetNext(y);
20117 	    if (y == NULL)
20118 		return (0);
20119 	} else if (xmlSchemaValueGetNext(y) != NULL)
20120 	    return (0);
20121 	else
20122 	    return (1);
20123     }
20124     return (0);
20125 }
20126 
20127 /**
20128  * xmlSchemaResolveAttrUseReferences:
20129  * @item:  an attribute use
20130  * @ctxt:  a parser context
20131  *
20132  * Resolves the referenced attribute declaration.
20133  */
20134 static int
xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,xmlSchemaParserCtxtPtr ctxt)20135 xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,
20136 				  xmlSchemaParserCtxtPtr ctxt)
20137 {
20138     if ((ctxt == NULL) || (ause == NULL))
20139 	return(-1);
20140     if ((ause->attrDecl == NULL) ||
20141 	(ause->attrDecl->type != XML_SCHEMA_EXTRA_QNAMEREF))
20142 	return(0);
20143 
20144     {
20145 	xmlSchemaQNameRefPtr ref = WXS_QNAME_CAST ause->attrDecl;
20146 
20147 	/*
20148 	* TODO: Evaluate, what errors could occur if the declaration is not
20149 	* found.
20150 	*/
20151 	ause->attrDecl = xmlSchemaGetAttributeDecl(ctxt->schema,
20152 	    ref->name, ref->targetNamespace);
20153         if (ause->attrDecl == NULL) {
20154 	    xmlSchemaPResCompAttrErr(ctxt,
20155 	    	XML_SCHEMAP_SRC_RESOLVE,
20156 		WXS_BASIC_CAST ause, ause->node,
20157 		"ref", ref->name, ref->targetNamespace,
20158 		XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20159             return(ctxt->err);;
20160         }
20161     }
20162     return(0);
20163 }
20164 
20165 /**
20166  * xmlSchemaCheckAttrUsePropsCorrect:
20167  * @ctxt:  a parser context
20168  * @use:  an attribute use
20169  *
20170  * Schema Component Constraint:
20171  * Attribute Use Correct (au-props-correct)
20172  *
20173  */
20174 static int
xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,xmlSchemaAttributeUsePtr use)20175 xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,
20176 			     xmlSchemaAttributeUsePtr use)
20177 {
20178     if ((ctxt == NULL) || (use == NULL))
20179 	return(-1);
20180     if ((use->defValue == NULL) || (WXS_ATTRUSE_DECL(use) == NULL) ||
20181 	((WXS_ATTRUSE_DECL(use))->type != XML_SCHEMA_TYPE_ATTRIBUTE))
20182 	return(0);
20183 
20184     /*
20185     * SPEC au-props-correct (1)
20186     * "The values of the properties of an attribute use must be as
20187     * described in the property tableau in The Attribute Use Schema
20188     * Component (�3.5.1), modulo the impact of Missing
20189     * Sub-components (�5.3)."
20190     */
20191 
20192     if (((WXS_ATTRUSE_DECL(use))->defValue != NULL) &&
20193 	((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMAS_ATTR_FIXED) &&
20194         ((use->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20195     {
20196 	xmlSchemaPCustomErr(ctxt,
20197 	    XML_SCHEMAP_AU_PROPS_CORRECT_2,
20198 	    WXS_BASIC_CAST use, NULL,
20199 	    "The attribute declaration has a 'fixed' value constraint "
20200 	    ", thus the attribute use must also have a 'fixed' value "
20201 	    "constraint",
20202 	    NULL);
20203 	return(ctxt->err);
20204     }
20205     /*
20206     * Compute and check the value constraint's value.
20207     */
20208     if ((use->defVal != NULL) && (WXS_ATTRUSE_TYPEDEF(use) != NULL)) {
20209 	int ret;
20210 	/*
20211 	* TODO: The spec seems to be missing a check of the
20212 	* value constraint of the attribute use. We will do it here.
20213 	*/
20214 	/*
20215 	* SPEC a-props-correct (3)
20216 	*/
20217 	if (xmlSchemaIsDerivedFromBuiltInType(
20218 	    WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
20219 	{
20220 	    xmlSchemaCustomErr(ACTXT_CAST ctxt,
20221 		XML_SCHEMAP_AU_PROPS_CORRECT,
20222 		NULL, WXS_BASIC_CAST use,
20223 		"Value constraints are not allowed if the type definition "
20224 		"is or is derived from xs:ID",
20225 		NULL, NULL);
20226 	    return(ctxt->err);
20227 	}
20228 
20229 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST ctxt,
20230 	    use->node, WXS_ATTRUSE_TYPEDEF(use),
20231 	    use->defValue, &(use->defVal),
20232 	    1, 1, 0);
20233 	if (ret != 0) {
20234 	    if (ret < 0) {
20235 		PERROR_INT2("xmlSchemaCheckAttrUsePropsCorrect",
20236 		    "calling xmlSchemaVCheckCVCSimpleType()");
20237 		return(-1);
20238 	    }
20239 	    xmlSchemaCustomErr(ACTXT_CAST ctxt,
20240 		XML_SCHEMAP_AU_PROPS_CORRECT,
20241 		NULL, WXS_BASIC_CAST use,
20242 		"The value of the value constraint is not valid",
20243 		NULL, NULL);
20244 	    return(ctxt->err);
20245 	}
20246     }
20247     /*
20248     * SPEC au-props-correct (2)
20249     * "If the {attribute declaration} has a fixed
20250     * {value constraint}, then if the attribute use itself has a
20251     * {value constraint}, it must also be fixed and its value must match
20252     * that of the {attribute declaration}'s {value constraint}."
20253     */
20254     if (((WXS_ATTRUSE_DECL(use))->defVal != NULL) &&
20255 	(((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20256     {
20257 	if (! xmlSchemaAreValuesEqual(use->defVal,
20258 		(WXS_ATTRUSE_DECL(use))->defVal))
20259 	{
20260 	    xmlSchemaPCustomErr(ctxt,
20261 		XML_SCHEMAP_AU_PROPS_CORRECT_2,
20262 		WXS_BASIC_CAST use, NULL,
20263 		"The 'fixed' value constraint of the attribute use "
20264 		"must match the attribute declaration's value "
20265 		"constraint '%s'",
20266 		(WXS_ATTRUSE_DECL(use))->defValue);
20267 	}
20268 	return(ctxt->err);
20269     }
20270     return(0);
20271 }
20272 
20273 
20274 
20275 
20276 /**
20277  * xmlSchemaResolveAttrTypeReferences:
20278  * @item:  an attribute declaration
20279  * @ctxt:  a parser context
20280  *
20281  * Resolves the referenced type definition component.
20282  */
20283 static int
xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,xmlSchemaParserCtxtPtr ctxt)20284 xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,
20285 				   xmlSchemaParserCtxtPtr ctxt)
20286 {
20287     /*
20288     * The simple type definition corresponding to the <simpleType> element
20289     * information item in the [children], if present, otherwise the simple
20290     * type definition �resolved� to by the �actual value� of the type
20291     * [attribute], if present, otherwise the �simple ur-type definition�.
20292     */
20293     if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
20294 	return(0);
20295     item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
20296     if (item->subtypes != NULL)
20297         return(0);
20298     if (item->typeName != NULL) {
20299         xmlSchemaTypePtr type;
20300 
20301 	type = xmlSchemaGetType(ctxt->schema, item->typeName,
20302 	    item->typeNs);
20303 	if ((type == NULL) || (! WXS_IS_SIMPLE(type))) {
20304 	    xmlSchemaPResCompAttrErr(ctxt,
20305 		XML_SCHEMAP_SRC_RESOLVE,
20306 		WXS_BASIC_CAST item, item->node,
20307 		"type", item->typeName, item->typeNs,
20308 		XML_SCHEMA_TYPE_SIMPLE, NULL);
20309 	    return(ctxt->err);
20310 	} else
20311 	    item->subtypes = type;
20312 
20313     } else {
20314 	/*
20315 	* The type defaults to the xs:anySimpleType.
20316 	*/
20317 	item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
20318     }
20319     return(0);
20320 }
20321 
20322 /**
20323  * xmlSchemaResolveIDCKeyReferences:
20324  * @idc:  the identity-constraint definition
20325  * @ctxt:  the schema parser context
20326  * @name:  the attribute name
20327  *
20328  * Resolve keyRef references to key/unique IDCs.
20329  * Schema Component Constraint:
20330  *   Identity-constraint Definition Properties Correct (c-props-correct)
20331  */
20332 static int
xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,xmlSchemaParserCtxtPtr pctxt)20333 xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,
20334 			  xmlSchemaParserCtxtPtr pctxt)
20335 {
20336     if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
20337         return(0);
20338     if (idc->ref->name != NULL) {
20339 	idc->ref->item = (xmlSchemaBasicItemPtr)
20340 	    xmlSchemaGetIDC(pctxt->schema, idc->ref->name,
20341 		idc->ref->targetNamespace);
20342         if (idc->ref->item == NULL) {
20343 	    /*
20344 	    * TODO: It is actually not an error to fail to resolve
20345 	    * at this stage. BUT we need to be that strict!
20346 	    */
20347 	    xmlSchemaPResCompAttrErr(pctxt,
20348 		XML_SCHEMAP_SRC_RESOLVE,
20349 		WXS_BASIC_CAST idc, idc->node,
20350 		"refer", idc->ref->name,
20351 		idc->ref->targetNamespace,
20352 		XML_SCHEMA_TYPE_IDC_KEY, NULL);
20353             return(pctxt->err);
20354 	} else if (idc->ref->item->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20355 	    /*
20356 	    * SPEC c-props-correct (1)
20357 	    */
20358 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20359 		XML_SCHEMAP_C_PROPS_CORRECT,
20360 		NULL, WXS_BASIC_CAST idc,
20361 		"The keyref references a keyref",
20362 		NULL, NULL);
20363 	    idc->ref->item = NULL;
20364 	    return(pctxt->err);
20365 	} else {
20366 	    if (idc->nbFields !=
20367 		((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
20368 		xmlChar *str = NULL;
20369 		xmlSchemaIDCPtr refer;
20370 
20371 		refer = (xmlSchemaIDCPtr) idc->ref->item;
20372 		/*
20373 		* SPEC c-props-correct(2)
20374 		* "If the {identity-constraint category} is keyref,
20375 		* the cardinality of the {fields} must equal that of
20376 		* the {fields} of the {referenced key}.
20377 		*/
20378 		xmlSchemaCustomErr(ACTXT_CAST pctxt,
20379 		    XML_SCHEMAP_C_PROPS_CORRECT,
20380 		    NULL, WXS_BASIC_CAST idc,
20381 		    "The cardinality of the keyref differs from the "
20382 		    "cardinality of the referenced key/unique '%s'",
20383 		    xmlSchemaFormatQName(&str, refer->targetNamespace,
20384 			refer->name),
20385 		    NULL);
20386 		FREE_AND_NULL(str)
20387 		return(pctxt->err);
20388 	    }
20389 	}
20390     }
20391     return(0);
20392 }
20393 
20394 static int
xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,xmlSchemaParserCtxtPtr pctxt)20395 xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,
20396 				       xmlSchemaParserCtxtPtr pctxt)
20397 {
20398     if (xmlSchemaGetAttributeDecl(pctxt->schema, prohib->name,
20399 	prohib->targetNamespace) == NULL) {
20400 
20401 	xmlSchemaPResCompAttrErr(pctxt,
20402 	    XML_SCHEMAP_SRC_RESOLVE,
20403 	    NULL, prohib->node,
20404 	    "ref", prohib->name, prohib->targetNamespace,
20405 	    XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20406 	return(XML_SCHEMAP_SRC_RESOLVE);
20407     }
20408     return(0);
20409 }
20410 
20411 #define WXS_REDEFINED_TYPE(c) \
20412 (((xmlSchemaTypePtr) item)->flags & XML_SCHEMAS_TYPE_REDEFINED)
20413 
20414 #define WXS_REDEFINED_MODEL_GROUP_DEF(c) \
20415 (((xmlSchemaModelGroupDefPtr) item)->flags & XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20416 
20417 #define WXS_REDEFINED_ATTR_GROUP(c) \
20418 (((xmlSchemaAttributeGroupPtr) item)->flags & XML_SCHEMAS_ATTRGROUP_REDEFINED)
20419 
20420 static int
xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)20421 xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)
20422 {
20423     int err = 0;
20424     xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20425     xmlSchemaBasicItemPtr prev, item;
20426     int wasRedefined;
20427 
20428     if (redef == NULL)
20429 	return(0);
20430 
20431     do {
20432 	item = redef->item;
20433 	/*
20434 	* First try to locate the redefined component in the
20435 	* schema graph starting with the redefined schema.
20436 	* NOTE: According to this schema bug entry:
20437 	*   http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005OctDec/0019.html
20438 	*   it's not clear if the referenced component needs to originate
20439 	*   from the <redefine>d schema _document_ or the schema; the latter
20440 	*   would include all imported and included sub-schemas of the
20441 	*   <redefine>d schema. Currenlty we latter approach is used.
20442 	*   SUPPLEMENT: It seems that the WG moves towards the latter
20443 	*   approach, so we are doing it right.
20444 	*
20445 	*/
20446 	prev = xmlSchemaFindRedefCompInGraph(
20447 	    redef->targetBucket, item->type,
20448 	    redef->refName, redef->refTargetNs);
20449 	if (prev == NULL) {
20450 	    xmlChar *str = NULL;
20451 	    xmlNodePtr node;
20452 
20453 	    /*
20454 	    * SPEC src-redefine:
20455 	    * (6.2.1) "The �actual value� of its own name attribute plus
20456 	    * target namespace must successfully �resolve� to a model
20457 	    * group definition in I."
20458 	    * (7.2.1) "The �actual value� of its own name attribute plus
20459 	    * target namespace must successfully �resolve� to an attribute
20460 	    * group definition in I."
20461 
20462 	    *
20463 	    * Note that, if we are redefining with the use of references
20464 	    * to components, the spec assumes the src-resolve to be used;
20465 	    * but this won't assure that we search only *inside* the
20466 	    * redefined schema.
20467 	    */
20468 	    if (redef->reference)
20469 		node = WXS_ITEM_NODE(redef->reference);
20470 	    else
20471 		node = WXS_ITEM_NODE(item);
20472 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20473 		/*
20474 		* TODO: error code.
20475 		* Probably XML_SCHEMAP_SRC_RESOLVE, if this is using the
20476 		* reference kind.
20477 		*/
20478 		XML_SCHEMAP_SRC_REDEFINE, node, NULL,
20479 		"The %s '%s' to be redefined could not be found in "
20480 		"the redefined schema",
20481 		WXS_ITEM_TYPE_NAME(item),
20482 		xmlSchemaFormatQName(&str, redef->refTargetNs,
20483 		    redef->refName));
20484 	    FREE_AND_NULL(str);
20485 	    err = pctxt->err;
20486 	    redef = redef->next;
20487 	    continue;
20488 	}
20489 	/*
20490 	* TODO: Obtaining and setting the redefinition state is really
20491 	* clumsy.
20492 	*/
20493 	wasRedefined = 0;
20494 	switch (item->type) {
20495 	    case XML_SCHEMA_TYPE_COMPLEX:
20496 	    case XML_SCHEMA_TYPE_SIMPLE:
20497 		if ((WXS_TYPE_CAST prev)->flags &
20498 		    XML_SCHEMAS_TYPE_REDEFINED)
20499 		{
20500 		    wasRedefined = 1;
20501 		    break;
20502 		}
20503 		/* Mark it as redefined. */
20504 		(WXS_TYPE_CAST prev)->flags |= XML_SCHEMAS_TYPE_REDEFINED;
20505 		/*
20506 		* Assign the redefined type to the
20507 		* base type of the redefining type.
20508 		* TODO: How
20509 		*/
20510 		((xmlSchemaTypePtr) item)->baseType =
20511 		    (xmlSchemaTypePtr) prev;
20512 		break;
20513 	    case XML_SCHEMA_TYPE_GROUP:
20514 		if ((WXS_MODEL_GROUPDEF_CAST prev)->flags &
20515 		    XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20516 		{
20517 		    wasRedefined = 1;
20518 		    break;
20519 		}
20520 		/* Mark it as redefined. */
20521 		(WXS_MODEL_GROUPDEF_CAST prev)->flags |=
20522 		    XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED;
20523 		if (redef->reference != NULL) {
20524 		    /*
20525 		    * Overwrite the QName-reference with the
20526 		    * referenced model group def.
20527 		    */
20528 		    (WXS_PTC_CAST redef->reference)->children =
20529 			WXS_TREE_CAST prev;
20530 		}
20531 		redef->target = prev;
20532 		break;
20533 	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20534 		if ((WXS_ATTR_GROUP_CAST prev)->flags &
20535 		    XML_SCHEMAS_ATTRGROUP_REDEFINED)
20536 		{
20537 		    wasRedefined = 1;
20538 		    break;
20539 		}
20540 		(WXS_ATTR_GROUP_CAST prev)->flags |=
20541 		    XML_SCHEMAS_ATTRGROUP_REDEFINED;
20542 		if (redef->reference != NULL) {
20543 		    /*
20544 		    * Assign the redefined attribute group to the
20545 		    * QName-reference component.
20546 		    * This is the easy case, since we will just
20547 		    * expand the redefined group.
20548 		    */
20549 		    (WXS_QNAME_CAST redef->reference)->item = prev;
20550 		    redef->target = NULL;
20551 		} else {
20552 		    /*
20553 		    * This is the complicated case: we need
20554 		    * to apply src-redefine (7.2.2) at a later
20555 		    * stage, i.e. when attribute group references
20556 		    * have beed expanded and simple types have
20557 		    * beed fixed.
20558 		    */
20559 		    redef->target = prev;
20560 		}
20561 		break;
20562 	    default:
20563 		PERROR_INT("xmlSchemaResolveRedefReferences",
20564 		    "Unexpected redefined component type");
20565 		return(-1);
20566 	}
20567 	if (wasRedefined) {
20568 	    xmlChar *str = NULL;
20569 	    xmlNodePtr node;
20570 
20571 	    if (redef->reference)
20572 		node = WXS_ITEM_NODE(redef->reference);
20573 	    else
20574 		node = WXS_ITEM_NODE(redef->item);
20575 
20576 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20577 		/* TODO: error code. */
20578 		XML_SCHEMAP_SRC_REDEFINE,
20579 		node, NULL,
20580 		"The referenced %s was already redefined. Multiple "
20581 		"redefinition of the same component is not supported",
20582 		xmlSchemaGetComponentDesignation(&str, prev),
20583 		NULL);
20584 	    FREE_AND_NULL(str)
20585 	    err = pctxt->err;
20586 	    redef = redef->next;
20587 	    continue;
20588 	}
20589 	redef = redef->next;
20590     } while (redef != NULL);
20591 
20592     return(err);
20593 }
20594 
20595 static int
xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)20596 xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)
20597 {
20598     int err = 0;
20599     xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20600     xmlSchemaBasicItemPtr item;
20601 
20602     if (redef == NULL)
20603 	return(0);
20604 
20605     do {
20606 	if (redef->target == NULL) {
20607 	    redef = redef->next;
20608 	    continue;
20609 	}
20610 	item = redef->item;
20611 
20612 	switch (item->type) {
20613 	    case XML_SCHEMA_TYPE_SIMPLE:
20614 	    case XML_SCHEMA_TYPE_COMPLEX:
20615 		/*
20616 		* Since the spec wants the {name} of the redefined
20617 		* type to be 'absent', we'll NULL it.
20618 		*/
20619 		(WXS_TYPE_CAST redef->target)->name = NULL;
20620 
20621 		/*
20622 		* TODO: Seems like there's nothing more to do. The normal
20623 		* inheritance mechanism is used. But not 100% sure.
20624 		*/
20625 		break;
20626 	    case XML_SCHEMA_TYPE_GROUP:
20627 		/*
20628 		* URGENT TODO:
20629 		* SPEC src-redefine:
20630 		* (6.2.2) "The {model group} of the model group definition
20631 		* which corresponds to it per XML Representation of Model
20632 		* Group Definition Schema Components (�3.7.2) must be a
20633 		* �valid restriction� of the {model group} of that model
20634 		* group definition in I, as defined in Particle Valid
20635 		* (Restriction) (�3.9.6)."
20636 		*/
20637 		break;
20638 	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20639 		/*
20640 		* SPEC src-redefine:
20641 		* (7.2.2) "The {attribute uses} and {attribute wildcard} of
20642 		* the attribute group definition which corresponds to it
20643 		* per XML Representation of Attribute Group Definition Schema
20644 		* Components (�3.6.2) must be �valid restrictions� of the
20645 		* {attribute uses} and {attribute wildcard} of that attribute
20646 		* group definition in I, as defined in clause 2, clause 3 and
20647 		* clause 4 of Derivation Valid (Restriction, Complex)
20648 		* (�3.4.6) (where references to the base type definition are
20649 		* understood as references to the attribute group definition
20650 		* in I)."
20651 		*/
20652 		err = xmlSchemaCheckDerivationOKRestriction2to4(pctxt,
20653 		    XML_SCHEMA_ACTION_REDEFINE,
20654 		    item, redef->target,
20655 		    (WXS_ATTR_GROUP_CAST item)->attrUses,
20656 		    (WXS_ATTR_GROUP_CAST redef->target)->attrUses,
20657 		    (WXS_ATTR_GROUP_CAST item)->attributeWildcard,
20658 		    (WXS_ATTR_GROUP_CAST redef->target)->attributeWildcard);
20659 		if (err == -1)
20660 		    return(-1);
20661 		break;
20662 	    default:
20663 		break;
20664 	}
20665 	redef = redef->next;
20666     } while (redef != NULL);
20667     return(0);
20668 }
20669 
20670 
20671 static int
xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBucketPtr bucket)20672 xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,
20673 		       xmlSchemaBucketPtr bucket)
20674 {
20675     xmlSchemaBasicItemPtr item;
20676     int err;
20677     xmlHashTablePtr *table;
20678     const xmlChar *name;
20679     int i;
20680 
20681 #define WXS_GET_GLOBAL_HASH(c, slot) { \
20682     if (WXS_IS_BUCKET_IMPMAIN((c)->type)) \
20683 	table = &(WXS_IMPBUCKET((c))->schema->slot); \
20684     else \
20685 	table = &(WXS_INCBUCKET((c))->ownerImport->schema->slot); }
20686 
20687     /*
20688     * Add global components to the schema's hash tables.
20689     * This is the place where duplicate components will be
20690     * detected.
20691     * TODO: I think normally we should support imports of the
20692     *   same namespace from multiple locations. We don't do currently,
20693     *   but if we do then according to:
20694     *   http://www.w3.org/Bugs/Public/show_bug.cgi?id=2224
20695     *   we would need, if imported directly, to import redefined
20696     *   components as well to be able to catch clashing components.
20697     *   (I hope I'll still know what this means after some months :-()
20698     */
20699     if (bucket == NULL)
20700 	return(-1);
20701     if (bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED)
20702 	return(0);
20703     bucket->flags |= XML_SCHEMA_BUCKET_COMPS_ADDED;
20704 
20705     for (i = 0; i < bucket->globals->nbItems; i++) {
20706 	item = bucket->globals->items[i];
20707 	table = NULL;
20708 	switch (item->type) {
20709 	    case XML_SCHEMA_TYPE_COMPLEX:
20710 	    case XML_SCHEMA_TYPE_SIMPLE:
20711 		if (WXS_REDEFINED_TYPE(item))
20712 		    continue;
20713 		name = (WXS_TYPE_CAST item)->name;
20714 		WXS_GET_GLOBAL_HASH(bucket, typeDecl)
20715 		break;
20716 	    case XML_SCHEMA_TYPE_ELEMENT:
20717 		name = (WXS_ELEM_CAST item)->name;
20718 		WXS_GET_GLOBAL_HASH(bucket, elemDecl)
20719 		break;
20720 	    case XML_SCHEMA_TYPE_ATTRIBUTE:
20721 		name = (WXS_ATTR_CAST item)->name;
20722 		WXS_GET_GLOBAL_HASH(bucket, attrDecl)
20723 		break;
20724 	    case XML_SCHEMA_TYPE_GROUP:
20725 		if (WXS_REDEFINED_MODEL_GROUP_DEF(item))
20726 		    continue;
20727 		name = (WXS_MODEL_GROUPDEF_CAST item)->name;
20728 		WXS_GET_GLOBAL_HASH(bucket, groupDecl)
20729 		break;
20730 	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20731 		if (WXS_REDEFINED_ATTR_GROUP(item))
20732 		    continue;
20733 		name = (WXS_ATTR_GROUP_CAST item)->name;
20734 		WXS_GET_GLOBAL_HASH(bucket, attrgrpDecl)
20735 		break;
20736 	    case XML_SCHEMA_TYPE_IDC_KEY:
20737 	    case XML_SCHEMA_TYPE_IDC_UNIQUE:
20738 	    case XML_SCHEMA_TYPE_IDC_KEYREF:
20739 		name = (WXS_IDC_CAST item)->name;
20740 		WXS_GET_GLOBAL_HASH(bucket, idcDef)
20741 		break;
20742 	    case XML_SCHEMA_TYPE_NOTATION:
20743 		name = ((xmlSchemaNotationPtr) item)->name;
20744 		WXS_GET_GLOBAL_HASH(bucket, notaDecl)
20745 		break;
20746 	    default:
20747 		PERROR_INT("xmlSchemaAddComponents",
20748 		    "Unexpected global component type");
20749 		continue;
20750 	}
20751 	if (*table == NULL) {
20752 	    *table = xmlHashCreateDict(10, pctxt->dict);
20753 	    if (*table == NULL) {
20754 		PERROR_INT("xmlSchemaAddComponents",
20755 		    "failed to create a component hash table");
20756 		return(-1);
20757 	    }
20758 	}
20759 	err = xmlHashAddEntry(*table, name, item);
20760 	if (err != 0) {
20761 	    xmlChar *str = NULL;
20762 
20763 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20764 		XML_SCHEMAP_REDEFINED_TYPE,
20765 		WXS_ITEM_NODE(item),
20766 		WXS_BASIC_CAST item,
20767 		"A global %s '%s' does already exist",
20768 		WXS_ITEM_TYPE_NAME(item),
20769 		xmlSchemaGetComponentQName(&str, item));
20770 	    FREE_AND_NULL(str);
20771 	}
20772     }
20773     /*
20774     * Process imported/included schemas.
20775     */
20776     if (bucket->relations != NULL) {
20777 	xmlSchemaSchemaRelationPtr rel = bucket->relations;
20778 	do {
20779 	    if ((rel->bucket != NULL) &&
20780 		((rel->bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED) == 0)) {
20781 		if (xmlSchemaAddComponents(pctxt, rel->bucket) == -1)
20782 		    return(-1);
20783 	    }
20784 	    rel = rel->next;
20785 	} while (rel != NULL);
20786     }
20787     return(0);
20788 }
20789 
20790 static int
xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBucketPtr rootBucket)20791 xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt,
20792 			 xmlSchemaBucketPtr rootBucket)
20793 {
20794     xmlSchemaConstructionCtxtPtr con = pctxt->constructor;
20795     xmlSchemaTreeItemPtr item, *items;
20796     int nbItems, i, ret = 0;
20797     xmlSchemaBucketPtr oldbucket = con->bucket;
20798     xmlSchemaElementPtr elemDecl;
20799 
20800 #define FIXHFAILURE if (pctxt->err == XML_SCHEMAP_INTERNAL) goto exit_failure;
20801 
20802     if ((con->pending == NULL) ||
20803 	(con->pending->nbItems == 0))
20804 	return(0);
20805 
20806     /*
20807     * Since xmlSchemaFixupComplexType() will create new particles
20808     * (local components), and those particle components need a bucket
20809     * on the constructor, we'll assure here that the constructor has
20810     * a bucket.
20811     * TODO: Think about storing locals _only_ on the main bucket.
20812     */
20813     if (con->bucket == NULL)
20814 	con->bucket = rootBucket;
20815 
20816     /* TODO:
20817     * SPEC (src-redefine):
20818     * (6.2) "If it has no such self-reference, then all of the
20819     * following must be true:"
20820 
20821     * (6.2.2) The {model group} of the model group definition which
20822     * corresponds to it per XML Representation of Model Group
20823     * Definition Schema Components (�3.7.2) must be a �valid
20824     * restriction� of the {model group} of that model group definition
20825     * in I, as defined in Particle Valid (Restriction) (�3.9.6)."
20826     */
20827     xmlSchemaCheckSRCRedefineFirst(pctxt);
20828 
20829     /*
20830     * Add global components to the schemata's hash tables.
20831     */
20832     xmlSchemaAddComponents(pctxt, rootBucket);
20833 
20834     pctxt->ctxtType = NULL;
20835     items = (xmlSchemaTreeItemPtr *) con->pending->items;
20836     nbItems = con->pending->nbItems;
20837     /*
20838     * Now that we have parsed *all* the schema document(s) and converted
20839     * them to schema components, we can resolve references, apply component
20840     * constraints, create the FSA from the content model, etc.
20841     */
20842     /*
20843     * Resolve references of..
20844     *
20845     * 1. element declarations:
20846     *   - the type definition
20847     *   - the substitution group affiliation
20848     * 2. simple/complex types:
20849     *   - the base type definition
20850     *   - the memberTypes of union types
20851     *   - the itemType of list types
20852     * 3. attributes declarations and attribute uses:
20853     *   - the type definition
20854     *   - if an attribute use, then the attribute declaration
20855     * 4. attribute group references:
20856     *   - the attribute group definition
20857     * 5. particles:
20858     *   - the term of the particle (e.g. a model group)
20859     * 6. IDC key-references:
20860     *   - the referenced IDC 'key' or 'unique' definition
20861     * 7. Attribute prohibitions which had a "ref" attribute.
20862     */
20863     for (i = 0; i < nbItems; i++) {
20864 	item = items[i];
20865 	switch (item->type) {
20866 	    case XML_SCHEMA_TYPE_ELEMENT:
20867 		xmlSchemaResolveElementReferences(
20868 		    (xmlSchemaElementPtr) item, pctxt);
20869 		FIXHFAILURE;
20870 		break;
20871 	    case XML_SCHEMA_TYPE_COMPLEX:
20872 	    case XML_SCHEMA_TYPE_SIMPLE:
20873 		xmlSchemaResolveTypeReferences(
20874 		    (xmlSchemaTypePtr) item, pctxt);
20875 		FIXHFAILURE;
20876 		break;
20877 	    case XML_SCHEMA_TYPE_ATTRIBUTE:
20878 		xmlSchemaResolveAttrTypeReferences(
20879 		    (xmlSchemaAttributePtr) item, pctxt);
20880 		FIXHFAILURE;
20881 		break;
20882 	    case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
20883 		xmlSchemaResolveAttrUseReferences(
20884 		    (xmlSchemaAttributeUsePtr) item, pctxt);
20885 		FIXHFAILURE;
20886 		break;
20887 	    case XML_SCHEMA_EXTRA_QNAMEREF:
20888 		if ((WXS_QNAME_CAST item)->itemType ==
20889 		    XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
20890 		{
20891 		    xmlSchemaResolveAttrGroupReferences(
20892 			WXS_QNAME_CAST item, pctxt);
20893 		}
20894 		FIXHFAILURE;
20895 		break;
20896 	    case XML_SCHEMA_TYPE_SEQUENCE:
20897 	    case XML_SCHEMA_TYPE_CHOICE:
20898 	    case XML_SCHEMA_TYPE_ALL:
20899 		xmlSchemaResolveModelGroupParticleReferences(pctxt,
20900 		    WXS_MODEL_GROUP_CAST item);
20901 		FIXHFAILURE;
20902 		break;
20903 	    case XML_SCHEMA_TYPE_IDC_KEY:
20904 	    case XML_SCHEMA_TYPE_IDC_UNIQUE:
20905 	    case XML_SCHEMA_TYPE_IDC_KEYREF:
20906 		xmlSchemaResolveIDCKeyReferences(
20907 		    (xmlSchemaIDCPtr) item, pctxt);
20908 		FIXHFAILURE;
20909 		break;
20910 	    case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
20911 		/*
20912 		* Handle attribue prohibition which had a
20913 		* "ref" attribute.
20914 		*/
20915 		xmlSchemaResolveAttrUseProhibReferences(
20916 		    WXS_ATTR_PROHIB_CAST item, pctxt);
20917 		FIXHFAILURE;
20918 		break;
20919 	    default:
20920 		break;
20921 	}
20922     }
20923     if (pctxt->nberrors != 0)
20924 	goto exit_error;
20925 
20926     /*
20927     * Now that all references are resolved we
20928     * can check for circularity of...
20929     * 1. the base axis of type definitions
20930     * 2. nested model group definitions
20931     * 3. nested attribute group definitions
20932     * TODO: check for circual substitution groups.
20933     */
20934     for (i = 0; i < nbItems; i++) {
20935 	item = items[i];
20936 	/*
20937 	* Let's better stop on the first error here.
20938 	*/
20939 	switch (item->type) {
20940 	    case XML_SCHEMA_TYPE_COMPLEX:
20941 	    case XML_SCHEMA_TYPE_SIMPLE:
20942 		xmlSchemaCheckTypeDefCircular(
20943 		    (xmlSchemaTypePtr) item, pctxt);
20944 		FIXHFAILURE;
20945 		if (pctxt->nberrors != 0)
20946 		    goto exit_error;
20947 		break;
20948 	    case XML_SCHEMA_TYPE_GROUP:
20949 		xmlSchemaCheckGroupDefCircular(
20950 		    (xmlSchemaModelGroupDefPtr) item, pctxt);
20951 		FIXHFAILURE;
20952 		if (pctxt->nberrors != 0)
20953 		    goto exit_error;
20954 		break;
20955 	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20956 		xmlSchemaCheckAttrGroupCircular(
20957 		    (xmlSchemaAttributeGroupPtr) item, pctxt);
20958 		FIXHFAILURE;
20959 		if (pctxt->nberrors != 0)
20960 		    goto exit_error;
20961 		break;
20962 	    default:
20963 		break;
20964 	}
20965     }
20966     if (pctxt->nberrors != 0)
20967 	goto exit_error;
20968     /*
20969     * Model group definition references:
20970     * Such a reference is reflected by a particle at the component
20971     * level. Until now the 'term' of such particles pointed
20972     * to the model group definition; this was done, in order to
20973     * ease circularity checks. Now we need to set the 'term' of
20974     * such particles to the model group of the model group definition.
20975     */
20976     for (i = 0; i < nbItems; i++) {
20977 	item = items[i];
20978 	switch (item->type) {
20979 	    case XML_SCHEMA_TYPE_SEQUENCE:
20980 	    case XML_SCHEMA_TYPE_CHOICE:
20981 		xmlSchemaModelGroupToModelGroupDefFixup(pctxt,
20982 		    WXS_MODEL_GROUP_CAST item);
20983 		break;
20984 	    default:
20985 		break;
20986 	}
20987     }
20988     if (pctxt->nberrors != 0)
20989 	goto exit_error;
20990     /*
20991     * Expand attribute group references of attribute group definitions.
20992     */
20993     for (i = 0; i < nbItems; i++) {
20994 	item = items[i];
20995 	switch (item->type) {
20996             case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20997 		if ((! WXS_ATTR_GROUP_EXPANDED(item)) &&
20998 		    WXS_ATTR_GROUP_HAS_REFS(item))
20999 		{
21000 		    xmlSchemaAttributeGroupExpandRefs(pctxt,
21001 			WXS_ATTR_GROUP_CAST item);
21002 		    FIXHFAILURE;
21003 		}
21004 		break;
21005 	    default:
21006 		break;
21007 	}
21008     }
21009     if (pctxt->nberrors != 0)
21010 	goto exit_error;
21011     /*
21012     * First compute the variety of simple types. This is needed as
21013     * a seperate step, since otherwise we won't be able to detect
21014     * circular union types in all cases.
21015     */
21016     for (i = 0; i < nbItems; i++) {
21017 	item = items[i];
21018 	switch (item->type) {
21019             case XML_SCHEMA_TYPE_SIMPLE:
21020 		if (WXS_IS_TYPE_NOT_FIXED_1((xmlSchemaTypePtr) item)) {
21021 		    xmlSchemaFixupSimpleTypeStageOne(pctxt,
21022 			(xmlSchemaTypePtr) item);
21023 		    FIXHFAILURE;
21024 		}
21025 		break;
21026 	    default:
21027 		break;
21028 	}
21029     }
21030     if (pctxt->nberrors != 0)
21031 	goto exit_error;
21032     /*
21033     * Detect circular union types. Note that this needs the variety to
21034     * be already computed.
21035     */
21036     for (i = 0; i < nbItems; i++) {
21037 	item = items[i];
21038 	switch (item->type) {
21039             case XML_SCHEMA_TYPE_SIMPLE:
21040 		if (((xmlSchemaTypePtr) item)->memberTypes != NULL) {
21041 		    xmlSchemaCheckUnionTypeDefCircular(pctxt,
21042 			(xmlSchemaTypePtr) item);
21043 		    FIXHFAILURE;
21044 		}
21045 		break;
21046 	    default:
21047 		break;
21048 	}
21049     }
21050     if (pctxt->nberrors != 0)
21051 	goto exit_error;
21052 
21053     /*
21054     * Do the complete type fixup for simple types.
21055     */
21056     for (i = 0; i < nbItems; i++) {
21057 	item = items[i];
21058 	switch (item->type) {
21059             case XML_SCHEMA_TYPE_SIMPLE:
21060 		if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21061 		    xmlSchemaFixupSimpleTypeStageTwo(pctxt, WXS_TYPE_CAST item);
21062 		    FIXHFAILURE;
21063 		}
21064 		break;
21065 	    default:
21066 		break;
21067 	}
21068     }
21069     if (pctxt->nberrors != 0)
21070 	goto exit_error;
21071     /*
21072     * At this point we need build and check all simple types.
21073     */
21074     /*
21075     * Apply contraints for attribute declarations.
21076     */
21077     for (i = 0; i < nbItems; i++) {
21078 	item = items[i];
21079 	switch (item->type) {
21080 	    case XML_SCHEMA_TYPE_ATTRIBUTE:
21081 		xmlSchemaCheckAttrPropsCorrect(pctxt, WXS_ATTR_CAST item);
21082 		FIXHFAILURE;
21083 		break;
21084 	    default:
21085 		break;
21086 	}
21087     }
21088     if (pctxt->nberrors != 0)
21089 	goto exit_error;
21090     /*
21091     * Apply constraints for attribute uses.
21092     */
21093     for (i = 0; i < nbItems; i++) {
21094 	item = items[i];
21095 	switch (item->type) {
21096 	    case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
21097 		if (((xmlSchemaAttributeUsePtr)item)->defValue != NULL) {
21098 		    xmlSchemaCheckAttrUsePropsCorrect(pctxt,
21099 			WXS_ATTR_USE_CAST item);
21100 		    FIXHFAILURE;
21101 		}
21102 		break;
21103 	    default:
21104 		break;
21105 	}
21106     }
21107     if (pctxt->nberrors != 0)
21108 	goto exit_error;
21109 
21110     /*
21111     * Apply constraints for attribute group definitions.
21112     */
21113     for (i = 0; i < nbItems; i++) {
21114 	item = items[i];
21115 	switch (item->type) {
21116 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21117 	    if (( (WXS_ATTR_GROUP_CAST item)->attrUses != NULL) &&
21118 		( (WXS_LIST_CAST (WXS_ATTR_GROUP_CAST item)->attrUses)->nbItems > 1))
21119 	    {
21120 		xmlSchemaCheckAGPropsCorrect(pctxt, WXS_ATTR_GROUP_CAST item);
21121 		FIXHFAILURE;
21122 	    }
21123 	    break;
21124 	default:
21125 	    break;
21126 	}
21127     }
21128     if (pctxt->nberrors != 0)
21129 	goto exit_error;
21130 
21131     /*
21132     * Apply constraints for redefinitions.
21133     */
21134     if (WXS_CONSTRUCTOR(pctxt)->redefs != NULL)
21135 	xmlSchemaCheckSRCRedefineSecond(pctxt);
21136     if (pctxt->nberrors != 0)
21137 	goto exit_error;
21138 
21139     /*
21140     * Complex types are builded and checked.
21141     */
21142     for (i = 0; i < nbItems; i++) {
21143 	item = con->pending->items[i];
21144 	switch (item->type) {
21145 	    case XML_SCHEMA_TYPE_COMPLEX:
21146 		if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21147 		    xmlSchemaFixupComplexType(pctxt, WXS_TYPE_CAST item);
21148 		    FIXHFAILURE;
21149 		}
21150 		break;
21151 	    default:
21152 		break;
21153 	}
21154     }
21155     if (pctxt->nberrors != 0)
21156 	goto exit_error;
21157 
21158     /*
21159     * The list could have changed, since xmlSchemaFixupComplexType()
21160     * will create particles and model groups in some cases.
21161     */
21162     items = (xmlSchemaTreeItemPtr *) con->pending->items;
21163     nbItems = con->pending->nbItems;
21164 
21165     /*
21166     * Apply some constraints for element declarations.
21167     */
21168     for (i = 0; i < nbItems; i++) {
21169 	item = items[i];
21170 	switch (item->type) {
21171 	    case XML_SCHEMA_TYPE_ELEMENT:
21172 		elemDecl = (xmlSchemaElementPtr) item;
21173 
21174 		if ((elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED) == 0)
21175 		{
21176 		    xmlSchemaCheckElementDeclComponent(
21177 			(xmlSchemaElementPtr) elemDecl, pctxt);
21178 		    FIXHFAILURE;
21179 		}
21180 
21181 #ifdef WXS_ELEM_DECL_CONS_ENABLED
21182 		/*
21183 		* Schema Component Constraint: Element Declarations Consistent
21184 		* Apply this constraint to local types of element declarations.
21185 		*/
21186 		if ((WXS_ELEM_TYPEDEF(elemDecl) != NULL) &&
21187 		    (WXS_IS_COMPLEX(WXS_ELEM_TYPEDEF(elemDecl))) &&
21188 		    (WXS_TYPE_IS_LOCAL(WXS_ELEM_TYPEDEF(elemDecl))))
21189 		{
21190 		    xmlSchemaCheckElementDeclConsistent(pctxt,
21191 			WXS_BASIC_CAST elemDecl,
21192 			WXS_TYPE_PARTICLE(WXS_ELEM_TYPEDEF(elemDecl)),
21193 			NULL, NULL, 0);
21194 		}
21195 #endif
21196 		break;
21197 	    default:
21198 		break;
21199 	}
21200     }
21201     if (pctxt->nberrors != 0)
21202 	goto exit_error;
21203 
21204     /*
21205     * Finally we can build the automaton from the content model of
21206     * complex types.
21207     */
21208 
21209     for (i = 0; i < nbItems; i++) {
21210 	item = items[i];
21211 	switch (item->type) {
21212 	    case XML_SCHEMA_TYPE_COMPLEX:
21213 		xmlSchemaBuildContentModel((xmlSchemaTypePtr) item, pctxt);
21214 		/* FIXHFAILURE; */
21215 		break;
21216 	    default:
21217 		break;
21218 	}
21219     }
21220     if (pctxt->nberrors != 0)
21221 	goto exit_error;
21222     /*
21223     * URGENT TODO: cos-element-consistent
21224     */
21225     goto exit;
21226 
21227 exit_error:
21228     ret = pctxt->err;
21229     goto exit;
21230 
21231 exit_failure:
21232     ret = -1;
21233 
21234 exit:
21235     /*
21236     * Reset the constructor. This is needed for XSI acquisition, since
21237     * those items will be processed over and over again for every XSI
21238     * if not cleared here.
21239     */
21240     con->bucket = oldbucket;
21241     con->pending->nbItems = 0;
21242     if (con->substGroups != NULL) {
21243 	xmlHashFree(con->substGroups,
21244 	    (xmlHashDeallocator) xmlSchemaSubstGroupFree);
21245 	con->substGroups = NULL;
21246     }
21247     if (con->redefs != NULL) {
21248 	xmlSchemaRedefListFree(con->redefs);
21249 	con->redefs = NULL;
21250     }
21251     return(ret);
21252 }
21253 /**
21254  * xmlSchemaParse:
21255  * @ctxt:  a schema validation context
21256  *
21257  * parse a schema definition resource and build an internal
21258  * XML Shema struture which can be used to validate instances.
21259  *
21260  * Returns the internal XML Schema structure built from the resource or
21261  *         NULL in case of error
21262  */
21263 xmlSchemaPtr
xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)21264 xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
21265 {
21266     xmlSchemaPtr mainSchema = NULL;
21267     xmlSchemaBucketPtr bucket = NULL;
21268     int res;
21269 
21270     /*
21271     * This one is used if the schema to be parsed was specified via
21272     * the API; i.e. not automatically by the validated instance document.
21273     */
21274 
21275     xmlSchemaInitTypes();
21276 
21277     if (ctxt == NULL)
21278         return (NULL);
21279 
21280     /* TODO: Init the context. Is this all we need?*/
21281     ctxt->nberrors = 0;
21282     ctxt->err = 0;
21283     ctxt->counter = 0;
21284 
21285     /* Create the *main* schema. */
21286     mainSchema = xmlSchemaNewSchema(ctxt);
21287     if (mainSchema == NULL)
21288 	goto exit_failure;
21289     /*
21290     * Create the schema constructor.
21291     */
21292     if (ctxt->constructor == NULL) {
21293 	ctxt->constructor = xmlSchemaConstructionCtxtCreate(ctxt->dict);
21294 	if (ctxt->constructor == NULL)
21295 	    return(NULL);
21296 	/* Take ownership of the constructor to be able to free it. */
21297 	ctxt->ownsConstructor = 1;
21298     }
21299     ctxt->constructor->mainSchema = mainSchema;
21300     /*
21301     * Locate and add the schema document.
21302     */
21303     res = xmlSchemaAddSchemaDoc(ctxt, XML_SCHEMA_SCHEMA_MAIN,
21304 	ctxt->URL, ctxt->doc, ctxt->buffer, ctxt->size, NULL,
21305 	NULL, NULL, &bucket);
21306     if (res == -1)
21307 	goto exit_failure;
21308     if (res != 0)
21309 	goto exit;
21310 
21311     if (bucket == NULL) {
21312 	/* TODO: Error code, actually we failed to *locate* the schema. */
21313 	if (ctxt->URL)
21314 	    xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21315 		NULL, NULL,
21316 		"Failed to locate the main schema resource at '%s'",
21317 		ctxt->URL, NULL);
21318 	else
21319 	    xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21320 		NULL, NULL,
21321 		"Failed to locate the main schema resource",
21322 		    NULL, NULL);
21323 	goto exit;
21324     }
21325     /* Then do the parsing for good. */
21326     if (xmlSchemaParseNewDocWithContext(ctxt, mainSchema, bucket) == -1)
21327 	goto exit_failure;
21328     if (ctxt->nberrors != 0)
21329 	goto exit;
21330 
21331     mainSchema->doc = bucket->doc;
21332     mainSchema->preserve = ctxt->preserve;
21333 
21334     ctxt->schema = mainSchema;
21335 
21336     if (xmlSchemaFixupComponents(ctxt, WXS_CONSTRUCTOR(ctxt)->mainBucket) == -1)
21337 	goto exit_failure;
21338 
21339     /*
21340     * TODO: This is not nice, since we cannot distinguish from the
21341     * result if there was an internal error or not.
21342     */
21343 exit:
21344     if (ctxt->nberrors != 0) {
21345 	if (mainSchema) {
21346 	    xmlSchemaFree(mainSchema);
21347 	    mainSchema = NULL;
21348 	}
21349 	if (ctxt->constructor) {
21350 	    xmlSchemaConstructionCtxtFree(ctxt->constructor);
21351 	    ctxt->constructor = NULL;
21352 	    ctxt->ownsConstructor = 0;
21353 	}
21354     }
21355     ctxt->schema = NULL;
21356     return(mainSchema);
21357 exit_failure:
21358     /*
21359     * Quite verbose, but should catch internal errors, which were
21360     * not communitated.
21361     */
21362     if (mainSchema) {
21363         xmlSchemaFree(mainSchema);
21364 	mainSchema = NULL;
21365     }
21366     if (ctxt->constructor) {
21367 	xmlSchemaConstructionCtxtFree(ctxt->constructor);
21368 	ctxt->constructor = NULL;
21369 	ctxt->ownsConstructor = 0;
21370     }
21371     PERROR_INT2("xmlSchemaParse",
21372 	"An internal error occured");
21373     ctxt->schema = NULL;
21374     return(NULL);
21375 }
21376 
21377 /**
21378  * xmlSchemaSetParserErrors:
21379  * @ctxt:  a schema validation context
21380  * @err:  the error callback
21381  * @warn:  the warning callback
21382  * @ctx:  contextual data for the callbacks
21383  *
21384  * Set the callback functions used to handle errors for a validation context
21385  */
21386 void
xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,xmlSchemaValidityErrorFunc err,xmlSchemaValidityWarningFunc warn,void * ctx)21387 xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21388                          xmlSchemaValidityErrorFunc err,
21389                          xmlSchemaValidityWarningFunc warn, void *ctx)
21390 {
21391     if (ctxt == NULL)
21392         return;
21393     ctxt->error = err;
21394     ctxt->warning = warn;
21395     ctxt->errCtxt = ctx;
21396     if (ctxt->vctxt != NULL)
21397 	xmlSchemaSetValidErrors(ctxt->vctxt, err, warn, ctx);
21398 }
21399 
21400 /**
21401  * xmlSchemaSetParserStructuredErrors:
21402  * @ctxt:  a schema parser context
21403  * @serror:  the structured error function
21404  * @ctx: the functions context
21405  *
21406  * Set the structured error callback
21407  */
21408 void
xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,xmlStructuredErrorFunc serror,void * ctx)21409 xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,
21410 				   xmlStructuredErrorFunc serror,
21411 				   void *ctx)
21412 {
21413     if (ctxt == NULL)
21414 	return;
21415     ctxt->serror = serror;
21416     ctxt->errCtxt = ctx;
21417     if (ctxt->vctxt != NULL)
21418 	xmlSchemaSetValidStructuredErrors(ctxt->vctxt, serror, ctx);
21419 }
21420 
21421 /**
21422  * xmlSchemaGetParserErrors:
21423  * @ctxt:  a XMl-Schema parser context
21424  * @err: the error callback result
21425  * @warn: the warning callback result
21426  * @ctx: contextual data for the callbacks result
21427  *
21428  * Get the callback information used to handle errors for a parser context
21429  *
21430  * Returns -1 in case of failure, 0 otherwise
21431  */
21432 int
xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,xmlSchemaValidityErrorFunc * err,xmlSchemaValidityWarningFunc * warn,void ** ctx)21433 xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21434 			 xmlSchemaValidityErrorFunc * err,
21435 			 xmlSchemaValidityWarningFunc * warn, void **ctx)
21436 {
21437 	if (ctxt == NULL)
21438 		return(-1);
21439 	if (err != NULL)
21440 		*err = ctxt->error;
21441 	if (warn != NULL)
21442 		*warn = ctxt->warning;
21443 	if (ctx != NULL)
21444 		*ctx = ctxt->errCtxt;
21445 	return(0);
21446 }
21447 
21448 /**
21449  * xmlSchemaFacetTypeToString:
21450  * @type:  the facet type
21451  *
21452  * Convert the xmlSchemaTypeType to a char string.
21453  *
21454  * Returns the char string representation of the facet type if the
21455  *     type is a facet and an "Internal Error" string otherwise.
21456  */
21457 static const xmlChar *
xmlSchemaFacetTypeToString(xmlSchemaTypeType type)21458 xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
21459 {
21460     switch (type) {
21461         case XML_SCHEMA_FACET_PATTERN:
21462             return (BAD_CAST "pattern");
21463         case XML_SCHEMA_FACET_MAXEXCLUSIVE:
21464             return (BAD_CAST "maxExclusive");
21465         case XML_SCHEMA_FACET_MAXINCLUSIVE:
21466             return (BAD_CAST "maxInclusive");
21467         case XML_SCHEMA_FACET_MINEXCLUSIVE:
21468             return (BAD_CAST "minExclusive");
21469         case XML_SCHEMA_FACET_MININCLUSIVE:
21470             return (BAD_CAST "minInclusive");
21471         case XML_SCHEMA_FACET_WHITESPACE:
21472             return (BAD_CAST "whiteSpace");
21473         case XML_SCHEMA_FACET_ENUMERATION:
21474             return (BAD_CAST "enumeration");
21475         case XML_SCHEMA_FACET_LENGTH:
21476             return (BAD_CAST "length");
21477         case XML_SCHEMA_FACET_MAXLENGTH:
21478             return (BAD_CAST "maxLength");
21479         case XML_SCHEMA_FACET_MINLENGTH:
21480             return (BAD_CAST "minLength");
21481         case XML_SCHEMA_FACET_TOTALDIGITS:
21482             return (BAD_CAST "totalDigits");
21483         case XML_SCHEMA_FACET_FRACTIONDIGITS:
21484             return (BAD_CAST "fractionDigits");
21485         default:
21486             break;
21487     }
21488     return (BAD_CAST "Internal Error");
21489 }
21490 
21491 static xmlSchemaWhitespaceValueType
xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)21492 xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
21493 {
21494     /*
21495     * The normalization type can be changed only for types which are derived
21496     * from xsd:string.
21497     */
21498     if (type->type == XML_SCHEMA_TYPE_BASIC) {
21499 	/*
21500 	* Note that we assume a whitespace of preserve for anySimpleType.
21501 	*/
21502 	if ((type->builtInType == XML_SCHEMAS_STRING) ||
21503 	    (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
21504 	    return(XML_SCHEMA_WHITESPACE_PRESERVE);
21505 	else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
21506 	    return(XML_SCHEMA_WHITESPACE_REPLACE);
21507 	else {
21508 	    /*
21509 	    * For all �atomic� datatypes other than string (and types �derived�
21510 	    * by �restriction� from it) the value of whiteSpace is fixed to
21511 	    * collapse
21512 	    * Note that this includes built-in list datatypes.
21513 	    */
21514 	    return(XML_SCHEMA_WHITESPACE_COLLAPSE);
21515 	}
21516     } else if (WXS_IS_LIST(type)) {
21517 	/*
21518 	* For list types the facet "whiteSpace" is fixed to "collapse".
21519 	*/
21520 	return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21521     } else if (WXS_IS_UNION(type)) {
21522 	return (XML_SCHEMA_WHITESPACE_UNKNOWN);
21523     } else if (WXS_IS_ATOMIC(type)) {
21524 	if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
21525 	    return (XML_SCHEMA_WHITESPACE_PRESERVE);
21526 	else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
21527 	    return (XML_SCHEMA_WHITESPACE_REPLACE);
21528 	else
21529 	    return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21530     }
21531     return (-1);
21532 }
21533 
21534 /************************************************************************
21535  * 									*
21536  * 			Simple type validation				*
21537  * 									*
21538  ************************************************************************/
21539 
21540 
21541 /************************************************************************
21542  * 									*
21543  * 			DOM Validation code				*
21544  * 									*
21545  ************************************************************************/
21546 
21547 /**
21548  * xmlSchemaAssembleByLocation:
21549  * @pctxt:  a schema parser context
21550  * @vctxt:  a schema validation context
21551  * @schema: the existing schema
21552  * @node: the node that fired the assembling
21553  * @nsName: the namespace name of the new schema
21554  * @location: the location of the schema
21555  *
21556  * Expands an existing schema by an additional schema.
21557  *
21558  * Returns 0 if the new schema is correct, a positive error code
21559  * number otherwise and -1 in case of an internal or API error.
21560  */
21561 static int
xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,xmlSchemaPtr schema,xmlNodePtr node,const xmlChar * nsName,const xmlChar * location)21562 xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
21563 			    xmlSchemaPtr schema,
21564 			    xmlNodePtr node,
21565 			    const xmlChar *nsName,
21566 			    const xmlChar *location)
21567 {
21568     int ret = 0;
21569     xmlSchemaParserCtxtPtr pctxt;
21570     xmlSchemaBucketPtr bucket = NULL;
21571 
21572     if ((vctxt == NULL) || (schema == NULL))
21573 	return (-1);
21574 
21575     if (vctxt->pctxt == NULL) {
21576 	VERROR_INT("xmlSchemaAssembleByLocation",
21577 	    "no parser context available");
21578 	return(-1);
21579     }
21580     pctxt = vctxt->pctxt;
21581     if (pctxt->constructor == NULL) {
21582 	PERROR_INT("xmlSchemaAssembleByLocation",
21583 	    "no constructor");
21584 	return(-1);
21585     }
21586     /*
21587     * Acquire the schema document.
21588     */
21589     location = xmlSchemaBuildAbsoluteURI(pctxt->dict,
21590 	location, node);
21591     /*
21592     * Note that we pass XML_SCHEMA_SCHEMA_IMPORT here;
21593     * the process will automatically change this to
21594     * XML_SCHEMA_SCHEMA_MAIN if it is the first schema document.
21595     */
21596     ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
21597 	location, NULL, NULL, 0, node, NULL, nsName,
21598 	&bucket);
21599     if (ret != 0)
21600 	return(ret);
21601     if (bucket == NULL) {
21602 	/*
21603 	* Generate a warning that the document could not be located.
21604 	*/
21605 	xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21606 	    node, NULL,
21607 	    "The document at location '%s' could not be acquired",
21608 	    location, NULL, NULL);
21609 	return(ret);
21610     }
21611     /*
21612     * The first located schema will be handled as if all other
21613     * schemas imported by XSI were imported by this first schema.
21614     */
21615     if ((bucket != NULL) &&
21616 	(WXS_CONSTRUCTOR(pctxt)->bucket == NULL))
21617 	WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
21618     /*
21619     * TODO: Is this handled like an import? I.e. is it not an error
21620     * if the schema cannot be located?
21621     */
21622     if ((bucket == NULL) || (! CAN_PARSE_SCHEMA(bucket)))
21623 	return(0);
21624     /*
21625     * We will reuse the parser context for every schema imported
21626     * directly via XSI. So reset the context.
21627     */
21628     pctxt->nberrors = 0;
21629     pctxt->err = 0;
21630     pctxt->doc = bucket->doc;
21631 
21632     ret = xmlSchemaParseNewDocWithContext(pctxt, schema, bucket);
21633     if (ret == -1) {
21634 	pctxt->doc = NULL;
21635 	goto exit_failure;
21636     }
21637     /* Paranoid error channelling. */
21638     if ((ret == 0) && (pctxt->nberrors != 0))
21639 	ret = pctxt->err;
21640     if (pctxt->nberrors == 0) {
21641 	/*
21642 	* Only bother to fixup pending components, if there was
21643 	* no error yet.
21644 	* For every XSI acquired schema (and its sub-schemata) we will
21645 	* fixup the components.
21646 	*/
21647 	xmlSchemaFixupComponents(pctxt, bucket);
21648 	ret = pctxt->err;
21649 	/*
21650 	* Not nice, but we need somehow to channel the schema parser
21651 	* error to the validation context.
21652 	*/
21653 	if ((ret != 0) && (vctxt->err == 0))
21654 	    vctxt->err = ret;
21655 	vctxt->nberrors += pctxt->nberrors;
21656     } else {
21657 	/* Add to validation error sum. */
21658 	vctxt->nberrors += pctxt->nberrors;
21659     }
21660     pctxt->doc = NULL;
21661     return(ret);
21662 exit_failure:
21663     pctxt->doc = NULL;
21664     return (-1);
21665 }
21666 
21667 static xmlSchemaAttrInfoPtr
xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,int metaType)21668 xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
21669 			 int metaType)
21670 {
21671     if (vctxt->nbAttrInfos == 0)
21672 	return (NULL);
21673     {
21674 	int i;
21675 	xmlSchemaAttrInfoPtr iattr;
21676 
21677 	for (i = 0; i < vctxt->nbAttrInfos; i++) {
21678 	    iattr = vctxt->attrInfos[i];
21679 	    if (iattr->metaType == metaType)
21680 		return (iattr);
21681 	}
21682 
21683     }
21684     return (NULL);
21685 }
21686 
21687 /**
21688  * xmlSchemaAssembleByXSI:
21689  * @vctxt:  a schema validation context
21690  *
21691  * Expands an existing schema by an additional schema using
21692  * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
21693  * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
21694  * must be set to 1.
21695  *
21696  * Returns 0 if the new schema is correct, a positive error code
21697  * number otherwise and -1 in case of an internal or API error.
21698  */
21699 static int
xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)21700 xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
21701 {
21702     const xmlChar *cur, *end;
21703     const xmlChar *nsname = NULL, *location;
21704     int count = 0;
21705     int ret = 0;
21706     xmlSchemaAttrInfoPtr iattr;
21707 
21708     /*
21709     * Parse the value; we will assume an even number of values
21710     * to be given (this is how Xerces and XSV work).
21711     *
21712     * URGENT TODO: !! This needs to work for both
21713     * @noNamespaceSchemaLocation AND @schemaLocation on the same
21714     * element !!
21715     */
21716     iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21717 	XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
21718     if (iattr == NULL)
21719 	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21720 	XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
21721     if (iattr == NULL)
21722 	return (0);
21723     cur = iattr->value;
21724     do {
21725 	/*
21726 	* TODO: Move the string parsing mechanism away from here.
21727 	*/
21728 	if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
21729 	    /*
21730 	    * Get the namespace name.
21731 	    */
21732 	    while (IS_BLANK_CH(*cur))
21733 		cur++;
21734 	    end = cur;
21735 	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21736 		end++;
21737 	    if (end == cur)
21738 		break;
21739 	    count++; /* TODO: Don't use the schema's dict. */
21740 	    nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21741 	    cur = end;
21742 	}
21743 	/*
21744 	* Get the URI.
21745 	*/
21746 	while (IS_BLANK_CH(*cur))
21747 	    cur++;
21748 	end = cur;
21749 	while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21750 	    end++;
21751 	if (end == cur) {
21752 	    if (iattr->metaType ==
21753 		XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC)
21754 	    {
21755 		/*
21756 		* If using @schemaLocation then tuples are expected.
21757 		* I.e. the namespace name *and* the document's URI.
21758 		*/
21759 		xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21760 		    iattr->node, NULL,
21761 		    "The value must consist of tuples: the target namespace "
21762 		    "name and the document's URI", NULL, NULL, NULL);
21763 	    }
21764 	    break;
21765 	}
21766 	count++; /* TODO: Don't use the schema's dict. */
21767 	location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21768 	cur = end;
21769 	ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
21770 	    iattr->node, nsname, location);
21771 	if (ret == -1) {
21772 	    VERROR_INT("xmlSchemaAssembleByXSI",
21773 		"assembling schemata");
21774 	    return (-1);
21775 	}
21776     } while (*cur != 0);
21777     return (ret);
21778 }
21779 
21780 static const xmlChar *
xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,const xmlChar * prefix)21781 xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
21782 			 const xmlChar *prefix)
21783 {
21784     if (vctxt->sax != NULL) {
21785 	int i, j;
21786 	xmlSchemaNodeInfoPtr inode;
21787 
21788 	for (i = vctxt->depth; i >= 0; i--) {
21789 	    if (vctxt->elemInfos[i]->nbNsBindings != 0) {
21790 		inode = vctxt->elemInfos[i];
21791 		for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
21792 		    if (((prefix == NULL) &&
21793 			    (inode->nsBindings[j] == NULL)) ||
21794 			((prefix != NULL) && xmlStrEqual(prefix,
21795 			    inode->nsBindings[j]))) {
21796 
21797 			/*
21798 			* Note that the namespace bindings are already
21799 			* in a string dict.
21800 			*/
21801 			return (inode->nsBindings[j+1]);
21802 		    }
21803 		}
21804 	    }
21805 	}
21806 	return (NULL);
21807 #ifdef LIBXML_READER_ENABLED
21808     } else if (vctxt->reader != NULL) {
21809 	xmlChar *nsName;
21810 
21811 	nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
21812 	if (nsName != NULL) {
21813 	    const xmlChar *ret;
21814 
21815 	    ret = xmlDictLookup(vctxt->dict, nsName, -1);
21816 	    xmlFree(nsName);
21817 	    return (ret);
21818 	} else
21819 	    return (NULL);
21820 #endif
21821     } else {
21822 	xmlNsPtr ns;
21823 
21824 	if ((vctxt->inode->node == NULL) ||
21825 	    (vctxt->inode->node->doc == NULL)) {
21826 	    VERROR_INT("xmlSchemaLookupNamespace",
21827 		"no node or node's doc avaliable");
21828 	    return (NULL);
21829 	}
21830 	ns = xmlSearchNs(vctxt->inode->node->doc,
21831 	    vctxt->inode->node, prefix);
21832 	if (ns != NULL)
21833 	    return (ns->href);
21834 	return (NULL);
21835     }
21836 }
21837 
21838 /*
21839 * This one works on the schema of the validation context.
21840 */
21841 static int
xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,xmlSchemaPtr schema,xmlNodePtr node,const xmlChar * value,xmlSchemaValPtr * val,int valNeeded)21842 xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
21843 			  xmlSchemaPtr schema,
21844 			  xmlNodePtr node,
21845 			  const xmlChar *value,
21846 			  xmlSchemaValPtr *val,
21847 			  int valNeeded)
21848 {
21849     int ret;
21850 
21851     if (vctxt && (vctxt->schema == NULL)) {
21852 	VERROR_INT("xmlSchemaValidateNotation",
21853 	    "a schema is needed on the validation context");
21854 	return (-1);
21855     }
21856     ret = xmlValidateQName(value, 1);
21857     if (ret != 0)
21858 	return (ret);
21859     {
21860 	xmlChar *localName = NULL;
21861 	xmlChar *prefix = NULL;
21862 
21863 	localName = xmlSplitQName2(value, &prefix);
21864 	if (prefix != NULL) {
21865 	    const xmlChar *nsName = NULL;
21866 
21867 	    if (vctxt != NULL)
21868 		nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
21869 	    else if (node != NULL) {
21870 		xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
21871 		if (ns != NULL)
21872 		    nsName = ns->href;
21873 	    } else {
21874 		xmlFree(prefix);
21875 		xmlFree(localName);
21876 		return (1);
21877 	    }
21878 	    if (nsName == NULL) {
21879 		xmlFree(prefix);
21880 		xmlFree(localName);
21881 		return (1);
21882 	    }
21883 	    if (xmlSchemaGetNotation(schema, localName, nsName) != NULL) {
21884 		if ((valNeeded) && (val != NULL)) {
21885 		    (*val) = xmlSchemaNewNOTATIONValue(xmlStrdup(localName),
21886 						       xmlStrdup(nsName));
21887 		    if (*val == NULL)
21888 			ret = -1;
21889 		}
21890 	    } else
21891 		ret = 1;
21892 	    xmlFree(prefix);
21893 	    xmlFree(localName);
21894 	} else {
21895 	    if (xmlSchemaGetNotation(schema, value, NULL) != NULL) {
21896 		if (valNeeded && (val != NULL)) {
21897 		    (*val) = xmlSchemaNewNOTATIONValue(
21898 			BAD_CAST xmlStrdup(value), NULL);
21899 		    if (*val == NULL)
21900 			ret = -1;
21901 		}
21902 	    } else
21903 		return (1);
21904 	}
21905     }
21906     return (ret);
21907 }
21908 
21909 static int
xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,const xmlChar * lname,const xmlChar * nsname)21910 xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,
21911 		       const xmlChar* lname,
21912 		       const xmlChar* nsname)
21913 {
21914     int i;
21915 
21916     lname = xmlDictLookup(vctxt->dict, lname, -1);
21917     if (lname == NULL)
21918 	return(-1);
21919     if (nsname != NULL) {
21920 	nsname = xmlDictLookup(vctxt->dict, nsname, -1);
21921 	if (nsname == NULL)
21922 	    return(-1);
21923     }
21924     for (i = 0; i < vctxt->nodeQNames->nbItems; i += 2) {
21925 	if ((vctxt->nodeQNames->items [i] == lname) &&
21926 	    (vctxt->nodeQNames->items[i +1] == nsname))
21927 	    /* Already there */
21928 	    return(i);
21929     }
21930     /* Add new entry. */
21931     i = vctxt->nodeQNames->nbItems;
21932     xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) lname);
21933     xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) nsname);
21934     return(i);
21935 }
21936 
21937 /************************************************************************
21938  * 									*
21939  *  Validation of identity-constraints (IDC)                            *
21940  * 									*
21941  ************************************************************************/
21942 
21943 /**
21944  * xmlSchemaAugmentIDC:
21945  * @idcDef: the IDC definition
21946  *
21947  * Creates an augmented IDC definition item.
21948  *
21949  * Returns the item, or NULL on internal errors.
21950  */
21951 static void
xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,xmlSchemaValidCtxtPtr vctxt)21952 xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
21953 		    xmlSchemaValidCtxtPtr vctxt)
21954 {
21955     xmlSchemaIDCAugPtr aidc;
21956 
21957     aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
21958     if (aidc == NULL) {
21959 	xmlSchemaVErrMemory(vctxt,
21960 	    "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
21961 	    NULL);
21962 	return;
21963     }
21964     aidc->keyrefDepth = -1;
21965     aidc->def = idcDef;
21966     aidc->next = NULL;
21967     if (vctxt->aidcs == NULL)
21968 	vctxt->aidcs = aidc;
21969     else {
21970 	aidc->next = vctxt->aidcs;
21971 	vctxt->aidcs = aidc;
21972     }
21973     /*
21974     * Save if we have keyrefs at all.
21975     */
21976     if ((vctxt->hasKeyrefs == 0) &&
21977 	(idcDef->type == XML_SCHEMA_TYPE_IDC_KEYREF))
21978 	vctxt->hasKeyrefs = 1;
21979 }
21980 
21981 /**
21982  * xmlSchemaAugmentImportedIDC:
21983  * @imported: the imported schema
21984  *
21985  * Creates an augmented IDC definition for the imported schema.
21986  */
21987 static void
xmlSchemaAugmentImportedIDC(xmlSchemaImportPtr imported,xmlSchemaValidCtxtPtr vctxt)21988 xmlSchemaAugmentImportedIDC(xmlSchemaImportPtr imported, xmlSchemaValidCtxtPtr vctxt) {
21989     if (imported->schema->idcDef != NULL) {
21990 	    xmlHashScan(imported->schema->idcDef ,
21991 	    (xmlHashScanner) xmlSchemaAugmentIDC, vctxt);
21992     }
21993 }
21994 
21995 /**
21996  * xmlSchemaIDCNewBinding:
21997  * @idcDef: the IDC definition of this binding
21998  *
21999  * Creates a new IDC binding.
22000  *
22001  * Returns the new IDC binding, NULL on internal errors.
22002  */
22003 static xmlSchemaPSVIIDCBindingPtr
xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)22004 xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
22005 {
22006     xmlSchemaPSVIIDCBindingPtr ret;
22007 
22008     ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
22009 	    sizeof(xmlSchemaPSVIIDCBinding));
22010     if (ret == NULL) {
22011 	xmlSchemaVErrMemory(NULL,
22012 	    "allocating a PSVI IDC binding item", NULL);
22013 	return (NULL);
22014     }
22015     memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
22016     ret->definition = idcDef;
22017     return (ret);
22018 }
22019 
22020 /**
22021  * xmlSchemaIDCStoreNodeTableItem:
22022  * @vctxt: the WXS validation context
22023  * @item: the IDC node table item
22024  *
22025  * The validation context is used to store IDC node table items.
22026  * They are stored to avoid copying them if IDC node-tables are merged
22027  * with corresponding parent IDC node-tables (bubbling).
22028  *
22029  * Returns 0 if succeeded, -1 on internal errors.
22030  */
22031 static int
xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,xmlSchemaPSVIIDCNodePtr item)22032 xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
22033 			       xmlSchemaPSVIIDCNodePtr item)
22034 {
22035     /*
22036     * Add to gobal list.
22037     */
22038     if (vctxt->idcNodes == NULL) {
22039 	vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22040 	    xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
22041 	if (vctxt->idcNodes == NULL) {
22042 	    xmlSchemaVErrMemory(vctxt,
22043 		"allocating the IDC node table item list", NULL);
22044 	    return (-1);
22045 	}
22046 	vctxt->sizeIdcNodes = 20;
22047     } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
22048 	vctxt->sizeIdcNodes *= 2;
22049 	vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22050 	    xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
22051 	    sizeof(xmlSchemaPSVIIDCNodePtr));
22052 	if (vctxt->idcNodes == NULL) {
22053 	    xmlSchemaVErrMemory(vctxt,
22054 		"re-allocating the IDC node table item list", NULL);
22055 	    return (-1);
22056 	}
22057     }
22058     vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
22059 
22060     return (0);
22061 }
22062 
22063 /**
22064  * xmlSchemaIDCStoreKey:
22065  * @vctxt: the WXS validation context
22066  * @item: the IDC key
22067  *
22068  * The validation context is used to store an IDC key.
22069  *
22070  * Returns 0 if succeeded, -1 on internal errors.
22071  */
22072 static int
xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,xmlSchemaPSVIIDCKeyPtr key)22073 xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
22074 		     xmlSchemaPSVIIDCKeyPtr key)
22075 {
22076     /*
22077     * Add to gobal list.
22078     */
22079     if (vctxt->idcKeys == NULL) {
22080 	vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22081 	    xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
22082 	if (vctxt->idcKeys == NULL) {
22083 	    xmlSchemaVErrMemory(vctxt,
22084 		"allocating the IDC key storage list", NULL);
22085 	    return (-1);
22086 	}
22087 	vctxt->sizeIdcKeys = 40;
22088     } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
22089 	vctxt->sizeIdcKeys *= 2;
22090 	vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22091 	    xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
22092 	    sizeof(xmlSchemaPSVIIDCKeyPtr));
22093 	if (vctxt->idcKeys == NULL) {
22094 	    xmlSchemaVErrMemory(vctxt,
22095 		"re-allocating the IDC key storage list", NULL);
22096 	    return (-1);
22097 	}
22098     }
22099     vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
22100 
22101     return (0);
22102 }
22103 
22104 /**
22105  * xmlSchemaIDCAppendNodeTableItem:
22106  * @bind: the IDC binding
22107  * @ntItem: the node-table item
22108  *
22109  * Appends the IDC node-table item to the binding.
22110  *
22111  * Returns 0 on success and -1 on internal errors.
22112  */
22113 static int
xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,xmlSchemaPSVIIDCNodePtr ntItem)22114 xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
22115 				xmlSchemaPSVIIDCNodePtr ntItem)
22116 {
22117     if (bind->nodeTable == NULL) {
22118 	bind->sizeNodes = 10;
22119 	bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22120 	    xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
22121 	if (bind->nodeTable == NULL) {
22122 	    xmlSchemaVErrMemory(NULL,
22123 		"allocating an array of IDC node-table items", NULL);
22124 	    return(-1);
22125 	}
22126     } else if (bind->sizeNodes <= bind->nbNodes) {
22127 	bind->sizeNodes *= 2;
22128 	bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22129 	    xmlRealloc(bind->nodeTable, bind->sizeNodes *
22130 		sizeof(xmlSchemaPSVIIDCNodePtr));
22131 	if (bind->nodeTable == NULL) {
22132 	    xmlSchemaVErrMemory(NULL,
22133 		"re-allocating an array of IDC node-table items", NULL);
22134 	    return(-1);
22135 	}
22136     }
22137     bind->nodeTable[bind->nbNodes++] = ntItem;
22138     return(0);
22139 }
22140 
22141 /**
22142  * xmlSchemaIDCAcquireBinding:
22143  * @vctxt: the WXS validation context
22144  * @matcher: the IDC matcher
22145  *
22146  * Looks up an PSVI IDC binding, for the IDC definition and
22147  * of the given matcher. If none found, a new one is created
22148  * and added to the IDC table.
22149  *
22150  * Returns an IDC binding or NULL on internal errors.
22151  */
22152 static xmlSchemaPSVIIDCBindingPtr
xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,xmlSchemaIDCMatcherPtr matcher)22153 xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,
22154 			  xmlSchemaIDCMatcherPtr matcher)
22155 {
22156     xmlSchemaNodeInfoPtr ielem;
22157 
22158     ielem = vctxt->elemInfos[matcher->depth];
22159 
22160     if (ielem->idcTable == NULL) {
22161 	ielem->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
22162 	if (ielem->idcTable == NULL)
22163 	    return (NULL);
22164 	return(ielem->idcTable);
22165     } else {
22166 	xmlSchemaPSVIIDCBindingPtr bind = NULL;
22167 
22168 	bind = ielem->idcTable;
22169 	do {
22170 	    if (bind->definition == matcher->aidc->def)
22171 		return(bind);
22172 	    if (bind->next == NULL) {
22173 		bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
22174 		if (bind->next == NULL)
22175 		    return (NULL);
22176 		return(bind->next);
22177 	    }
22178 	    bind = bind->next;
22179 	} while (bind != NULL);
22180     }
22181     return (NULL);
22182 }
22183 
22184 static xmlSchemaItemListPtr
xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,xmlSchemaIDCMatcherPtr matcher)22185 xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
22186 			     xmlSchemaIDCMatcherPtr matcher)
22187 {
22188     if (matcher->targets == NULL)
22189 	matcher->targets = xmlSchemaItemListCreate();
22190     return(matcher->targets);
22191 }
22192 
22193 /**
22194  * xmlSchemaIDCFreeKey:
22195  * @key: the IDC key
22196  *
22197  * Frees an IDC key together with its compiled value.
22198  */
22199 static void
xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)22200 xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
22201 {
22202     if (key->val != NULL)
22203 	xmlSchemaFreeValue(key->val);
22204     xmlFree(key);
22205 }
22206 
22207 /**
22208  * xmlSchemaIDCFreeBinding:
22209  *
22210  * Frees an IDC binding. Note that the node table-items
22211  * are not freed.
22212  */
22213 static void
xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)22214 xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
22215 {
22216     if (bind->nodeTable != NULL)
22217 	xmlFree(bind->nodeTable);
22218     if (bind->dupls != NULL)
22219 	xmlSchemaItemListFree(bind->dupls);
22220     xmlFree(bind);
22221 }
22222 
22223 /**
22224  * xmlSchemaIDCFreeIDCTable:
22225  * @bind: the first IDC binding in the list
22226  *
22227  * Frees an IDC table, i.e. all the IDC bindings in the list.
22228  */
22229 static void
xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)22230 xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
22231 {
22232     xmlSchemaPSVIIDCBindingPtr prev;
22233 
22234     while (bind != NULL) {
22235 	prev = bind;
22236 	bind = bind->next;
22237 	xmlSchemaIDCFreeBinding(prev);
22238     }
22239 }
22240 
22241 /**
22242  * xmlSchemaIDCFreeMatcherList:
22243  * @matcher: the first IDC matcher in the list
22244  *
22245  * Frees a list of IDC matchers.
22246  */
22247 static void
xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)22248 xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
22249 {
22250     xmlSchemaIDCMatcherPtr next;
22251 
22252     while (matcher != NULL) {
22253 	next = matcher->next;
22254 	if (matcher->keySeqs != NULL) {
22255 	    int i;
22256 	    for (i = 0; i < matcher->sizeKeySeqs; i++)
22257 		if (matcher->keySeqs[i] != NULL)
22258 		    xmlFree(matcher->keySeqs[i]);
22259 	    xmlFree(matcher->keySeqs);
22260 	}
22261 	if (matcher->targets != NULL) {
22262 	    if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22263 		int i;
22264 		xmlSchemaPSVIIDCNodePtr idcNode;
22265 		/*
22266 		* Node-table items for keyrefs are not stored globally
22267 		* to the validation context, since they are not bubbled.
22268 		* We need to free them here.
22269 		*/
22270 		for (i = 0; i < matcher->targets->nbItems; i++) {
22271 		    idcNode =
22272 			(xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22273 		    xmlFree(idcNode->keys);
22274 		    xmlFree(idcNode);
22275 		}
22276 	    }
22277 	    xmlSchemaItemListFree(matcher->targets);
22278 	}
22279 	xmlFree(matcher);
22280 	matcher = next;
22281     }
22282 }
22283 
22284 /**
22285  * xmlSchemaIDCReleaseMatcherList:
22286  * @vctxt: the WXS validation context
22287  * @matcher: the first IDC matcher in the list
22288  *
22289  * Caches a list of IDC matchers for reuse.
22290  */
22291 static void
xmlSchemaIDCReleaseMatcherList(xmlSchemaValidCtxtPtr vctxt,xmlSchemaIDCMatcherPtr matcher)22292 xmlSchemaIDCReleaseMatcherList(xmlSchemaValidCtxtPtr vctxt,
22293 			       xmlSchemaIDCMatcherPtr matcher)
22294 {
22295     xmlSchemaIDCMatcherPtr next;
22296 
22297     while (matcher != NULL) {
22298 	next = matcher->next;
22299 	if (matcher->keySeqs != NULL) {
22300 	    int i;
22301 	    /*
22302 	    * Don't free the array, but only the content.
22303 	    */
22304 	    for (i = 0; i < matcher->sizeKeySeqs; i++)
22305 		if (matcher->keySeqs[i] != NULL) {
22306 		    xmlFree(matcher->keySeqs[i]);
22307 		    matcher->keySeqs[i] = NULL;
22308 		}
22309 	}
22310 	if (matcher->targets) {
22311 	    if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22312 		int i;
22313 		xmlSchemaPSVIIDCNodePtr idcNode;
22314 		/*
22315 		* Node-table items for keyrefs are not stored globally
22316 		* to the validation context, since they are not bubbled.
22317 		* We need to free them here.
22318 		*/
22319 		for (i = 0; i < matcher->targets->nbItems; i++) {
22320 		    idcNode =
22321 			(xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22322 		    xmlFree(idcNode->keys);
22323 		    xmlFree(idcNode);
22324 		}
22325 	    }
22326 	    xmlSchemaItemListFree(matcher->targets);
22327 	    matcher->targets = NULL;
22328 	}
22329 	matcher->next = NULL;
22330 	/*
22331 	* Cache the matcher.
22332 	*/
22333 	if (vctxt->idcMatcherCache != NULL)
22334 	    matcher->nextCached = vctxt->idcMatcherCache;
22335 	vctxt->idcMatcherCache = matcher;
22336 
22337 	matcher = next;
22338     }
22339 }
22340 
22341 /**
22342  * xmlSchemaIDCAddStateObject:
22343  * @vctxt: the WXS validation context
22344  * @matcher: the IDC matcher
22345  * @sel: the XPath information
22346  * @parent: the parent "selector" state object if any
22347  * @type: "selector" or "field"
22348  *
22349  * Creates/reuses and activates state objects for the given
22350  * XPath information; if the XPath expression consists of unions,
22351  * multiple state objects are created for every unioned expression.
22352  *
22353  * Returns 0 on success and -1 on internal errors.
22354  */
22355 static int
xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,xmlSchemaIDCMatcherPtr matcher,xmlSchemaIDCSelectPtr sel,int type)22356 xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
22357 			xmlSchemaIDCMatcherPtr matcher,
22358 			xmlSchemaIDCSelectPtr sel,
22359 			int type)
22360 {
22361     xmlSchemaIDCStateObjPtr sto;
22362 
22363     /*
22364     * Reuse the state objects from the pool.
22365     */
22366     if (vctxt->xpathStatePool != NULL) {
22367 	sto = vctxt->xpathStatePool;
22368 	vctxt->xpathStatePool = sto->next;
22369 	sto->next = NULL;
22370     } else {
22371 	/*
22372 	* Create a new state object.
22373 	*/
22374 	sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
22375 	if (sto == NULL) {
22376 	    xmlSchemaVErrMemory(NULL,
22377 		"allocating an IDC state object", NULL);
22378 	    return (-1);
22379 	}
22380 	memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
22381     }
22382     /*
22383     * Add to global list.
22384     */
22385     if (vctxt->xpathStates != NULL)
22386 	sto->next = vctxt->xpathStates;
22387     vctxt->xpathStates = sto;
22388 
22389     /*
22390     * Free the old xpath validation context.
22391     */
22392     if (sto->xpathCtxt != NULL)
22393 	xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
22394 
22395     /*
22396     * Create a new XPath (pattern) validation context.
22397     */
22398     sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
22399 	(xmlPatternPtr) sel->xpathComp);
22400     if (sto->xpathCtxt == NULL) {
22401 	VERROR_INT("xmlSchemaIDCAddStateObject",
22402 	    "failed to create an XPath validation context");
22403 	return (-1);
22404     }
22405     sto->type = type;
22406     sto->depth = vctxt->depth;
22407     sto->matcher = matcher;
22408     sto->sel = sel;
22409     sto->nbHistory = 0;
22410 
22411 #ifdef DEBUG_IDC
22412     xmlGenericError(xmlGenericErrorContext, "IDC:   STO push '%s'\n",
22413 	sto->sel->xpath);
22414 #endif
22415     return (0);
22416 }
22417 
22418 /**
22419  * xmlSchemaXPathEvaluate:
22420  * @vctxt: the WXS validation context
22421  * @nodeType: the nodeType of the current node
22422  *
22423  * Evaluates all active XPath state objects.
22424  *
22425  * Returns the number of IC "field" state objects which resolved to
22426  * this node, 0 if none resolved and -1 on internal errors.
22427  */
22428 static int
xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,xmlElementType nodeType)22429 xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
22430 		       xmlElementType nodeType)
22431 {
22432     xmlSchemaIDCStateObjPtr sto, head = NULL, first;
22433     int res, resolved = 0, depth = vctxt->depth;
22434 
22435     if (vctxt->xpathStates == NULL)
22436 	return (0);
22437 
22438     if (nodeType == XML_ATTRIBUTE_NODE)
22439 	depth++;
22440 #ifdef DEBUG_IDC
22441     {
22442 	xmlChar *str = NULL;
22443 	xmlGenericError(xmlGenericErrorContext,
22444 	    "IDC: EVAL on %s, depth %d, type %d\n",
22445 	    xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22446 		vctxt->inode->localName), depth, nodeType);
22447 	FREE_AND_NULL(str)
22448     }
22449 #endif
22450     /*
22451     * Process all active XPath state objects.
22452     */
22453     first = vctxt->xpathStates;
22454     sto = first;
22455     while (sto != head) {
22456 #ifdef DEBUG_IDC
22457 	if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
22458 	    xmlGenericError(xmlGenericErrorContext, "IDC:   ['%s'] selector '%s'\n",
22459 		sto->matcher->aidc->def->name, sto->sel->xpath);
22460 	else
22461 	    xmlGenericError(xmlGenericErrorContext, "IDC:   ['%s'] field '%s'\n",
22462 		sto->matcher->aidc->def->name, sto->sel->xpath);
22463 #endif
22464 	if (nodeType == XML_ELEMENT_NODE)
22465 	    res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
22466 		vctxt->inode->localName, vctxt->inode->nsName);
22467 	else
22468 	    res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
22469 		vctxt->inode->localName, vctxt->inode->nsName);
22470 
22471 	if (res == -1) {
22472 	    VERROR_INT("xmlSchemaXPathEvaluate",
22473 		"calling xmlStreamPush()");
22474 	    return (-1);
22475 	}
22476 	if (res == 0)
22477 	    goto next_sto;
22478 	/*
22479 	* Full match.
22480 	*/
22481 #ifdef DEBUG_IDC
22482 	xmlGenericError(xmlGenericErrorContext, "IDC:     "
22483 	    "MATCH\n");
22484 #endif
22485 	/*
22486 	* Register a match in the state object history.
22487 	*/
22488 	if (sto->history == NULL) {
22489 	    sto->history = (int *) xmlMalloc(5 * sizeof(int));
22490 	    if (sto->history == NULL) {
22491 		xmlSchemaVErrMemory(NULL,
22492 		    "allocating the state object history", NULL);
22493 		return(-1);
22494 	    }
22495 	    sto->sizeHistory = 5;
22496 	} else if (sto->sizeHistory <= sto->nbHistory) {
22497 	    sto->sizeHistory *= 2;
22498 	    sto->history = (int *) xmlRealloc(sto->history,
22499 		sto->sizeHistory * sizeof(int));
22500 	    if (sto->history == NULL) {
22501 		xmlSchemaVErrMemory(NULL,
22502 		    "re-allocating the state object history", NULL);
22503 		return(-1);
22504 	    }
22505 	}
22506 	sto->history[sto->nbHistory++] = depth;
22507 
22508 #ifdef DEBUG_IDC
22509 	xmlGenericError(xmlGenericErrorContext, "IDC:       push match '%d'\n",
22510 	    vctxt->depth);
22511 #endif
22512 
22513 	if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22514 	    xmlSchemaIDCSelectPtr sel;
22515 	    /*
22516 	    * Activate state objects for the IDC fields of
22517 	    * the IDC selector.
22518 	    */
22519 #ifdef DEBUG_IDC
22520 	    xmlGenericError(xmlGenericErrorContext, "IDC:     "
22521 		"activating field states\n");
22522 #endif
22523 	    sel = sto->matcher->aidc->def->fields;
22524 	    while (sel != NULL) {
22525 		if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
22526 		    sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
22527 		    return (-1);
22528 		sel = sel->next;
22529 	    }
22530 	} else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22531 	    /*
22532 	    * An IDC key node was found by the IDC field.
22533 	    */
22534 #ifdef DEBUG_IDC
22535 	    xmlGenericError(xmlGenericErrorContext,
22536 		"IDC:     key found\n");
22537 #endif
22538 	    /*
22539 	    * Notify that the character value of this node is
22540 	    * needed.
22541 	    */
22542 	    if (resolved == 0) {
22543 		if ((vctxt->inode->flags &
22544 		    XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
22545 		vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
22546 	    }
22547 	    resolved++;
22548 	}
22549 next_sto:
22550 	if (sto->next == NULL) {
22551 	    /*
22552 	    * Evaluate field state objects created on this node as well.
22553 	    */
22554 	    head = first;
22555 	    sto = vctxt->xpathStates;
22556 	} else
22557 	    sto = sto->next;
22558     }
22559     return (resolved);
22560 }
22561 
22562 static const xmlChar *
xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,xmlChar ** buf,xmlSchemaPSVIIDCKeyPtr * seq,int count)22563 xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
22564 			      xmlChar **buf,
22565 			      xmlSchemaPSVIIDCKeyPtr *seq,
22566 			      int count)
22567 {
22568     int i, res;
22569     xmlChar *value = NULL;
22570 
22571     *buf = xmlStrdup(BAD_CAST "[");
22572     for (i = 0; i < count; i++) {
22573 	*buf = xmlStrcat(*buf, BAD_CAST "'");
22574 	res = xmlSchemaGetCanonValueWhtspExt(seq[i]->val,
22575 	    xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type),
22576 	    &value);
22577 	if (res == 0)
22578 	    *buf = xmlStrcat(*buf, BAD_CAST value);
22579 	else {
22580 	    VERROR_INT("xmlSchemaFormatIDCKeySequence",
22581 		"failed to compute a canonical value");
22582 	    *buf = xmlStrcat(*buf, BAD_CAST "???");
22583 	}
22584 	if (i < count -1)
22585 	    *buf = xmlStrcat(*buf, BAD_CAST "', ");
22586 	else
22587 	    *buf = xmlStrcat(*buf, BAD_CAST "'");
22588 	if (value != NULL) {
22589 	    xmlFree(value);
22590 	    value = NULL;
22591 	}
22592     }
22593     *buf = xmlStrcat(*buf, BAD_CAST "]");
22594 
22595     return (BAD_CAST *buf);
22596 }
22597 
22598 /**
22599  * xmlSchemaXPathPop:
22600  * @vctxt: the WXS validation context
22601  *
22602  * Pops all XPath states.
22603  *
22604  * Returns 0 on success and -1 on internal errors.
22605  */
22606 static int
xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)22607 xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)
22608 {
22609     xmlSchemaIDCStateObjPtr sto;
22610     int res;
22611 
22612     if (vctxt->xpathStates == NULL)
22613 	return(0);
22614     sto = vctxt->xpathStates;
22615     do {
22616 	res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22617 	if (res == -1)
22618 	    return (-1);
22619 	sto = sto->next;
22620     } while (sto != NULL);
22621     return(0);
22622 }
22623 
22624 /**
22625  * xmlSchemaXPathProcessHistory:
22626  * @vctxt: the WXS validation context
22627  * @type: the simple/complex type of the current node if any at all
22628  * @val: the precompiled value
22629  *
22630  * Processes and pops the history items of the IDC state objects.
22631  * IDC key-sequences are validated/created on IDC bindings.
22632  *
22633  * Returns 0 on success and -1 on internal errors.
22634  */
22635 static int
xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,int depth)22636 xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
22637 			     int depth)
22638 {
22639     xmlSchemaIDCStateObjPtr sto, nextsto;
22640     int res, matchDepth;
22641     xmlSchemaPSVIIDCKeyPtr key = NULL;
22642     xmlSchemaTypePtr type = vctxt->inode->typeDef, simpleType = NULL;
22643 
22644     if (vctxt->xpathStates == NULL)
22645 	return (0);
22646     sto = vctxt->xpathStates;
22647 
22648 #ifdef DEBUG_IDC
22649     {
22650 	xmlChar *str = NULL;
22651 	xmlGenericError(xmlGenericErrorContext,
22652 	    "IDC: BACK on %s, depth %d\n",
22653 	    xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22654 		vctxt->inode->localName), vctxt->depth);
22655 	FREE_AND_NULL(str)
22656     }
22657 #endif
22658     /*
22659     * Evaluate the state objects.
22660     */
22661     while (sto != NULL) {
22662 	res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22663 	if (res == -1) {
22664 	    VERROR_INT("xmlSchemaXPathProcessHistory",
22665 		"calling xmlStreamPop()");
22666 	    return (-1);
22667 	}
22668 #ifdef DEBUG_IDC
22669 	xmlGenericError(xmlGenericErrorContext, "IDC:   stream pop '%s'\n",
22670 	    sto->sel->xpath);
22671 #endif
22672 	if (sto->nbHistory == 0)
22673 	    goto deregister_check;
22674 
22675 	matchDepth = sto->history[sto->nbHistory -1];
22676 
22677 	/*
22678 	* Only matches at the current depth are of interest.
22679 	*/
22680 	if (matchDepth != depth) {
22681 	    sto = sto->next;
22682 	    continue;
22683 	}
22684 	if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22685 	    /*
22686 	    * NOTE: According to
22687 	    *   http://www.w3.org/Bugs/Public/show_bug.cgi?id=2198
22688 	    *   ... the simple-content of complex types is also allowed.
22689 	    */
22690 
22691 	    if (WXS_IS_COMPLEX(type)) {
22692 		if (WXS_HAS_SIMPLE_CONTENT(type)) {
22693 		    /*
22694 		    * Sanity check for complex types with simple content.
22695 		    */
22696 		    simpleType = type->contentTypeDef;
22697 		    if (simpleType == NULL) {
22698 			VERROR_INT("xmlSchemaXPathProcessHistory",
22699 			    "field resolves to a CT with simple content "
22700 			    "but the CT is missing the ST definition");
22701 			return (-1);
22702 		    }
22703 		} else
22704 		    simpleType = NULL;
22705 	    } else
22706 		simpleType = type;
22707 	    if (simpleType == NULL) {
22708 		xmlChar *str = NULL;
22709 
22710 		/*
22711 		* Not qualified if the field resolves to a node of non
22712 		* simple type.
22713 		*/
22714 		xmlSchemaCustomErr(ACTXT_CAST vctxt,
22715 		    XML_SCHEMAV_CVC_IDC, NULL,
22716 		    WXS_BASIC_CAST sto->matcher->aidc->def,
22717 		    "The XPath '%s' of a field of %s does evaluate to a node of "
22718 		    "non-simple type",
22719 		    sto->sel->xpath,
22720 		    xmlSchemaGetIDCDesignation(&str, sto->matcher->aidc->def));
22721 		FREE_AND_NULL(str);
22722 		sto->nbHistory--;
22723 		goto deregister_check;
22724 	    }
22725 
22726 	    if ((key == NULL) && (vctxt->inode->val == NULL)) {
22727 		/*
22728 		* Failed to provide the normalized value; maybe
22729 		* the value was invalid.
22730 		*/
22731 		VERROR(XML_SCHEMAV_CVC_IDC,
22732 		    WXS_BASIC_CAST sto->matcher->aidc->def,
22733 		    "Warning: No precomputed value available, the value "
22734 		    "was either invalid or something strange happend");
22735 		sto->nbHistory--;
22736 		goto deregister_check;
22737 	    } else {
22738 		xmlSchemaIDCMatcherPtr matcher = sto->matcher;
22739 		xmlSchemaPSVIIDCKeyPtr *keySeq;
22740 		int pos, idx;
22741 
22742 		/*
22743 		* The key will be anchored on the matcher's list of
22744 		* key-sequences. The position in this list is determined
22745 		* by the target node's depth relative to the matcher's
22746 		* depth of creation (i.e. the depth of the scope element).
22747 		*
22748 		* Element        Depth    Pos   List-entries
22749 		* <scope>          0              NULL
22750 		*   <bar>          1              NULL
22751 		*     <target/>    2       2      target
22752 		*   <bar>
22753                 * </scope>
22754 		*
22755 		* The size of the list is only dependant on the depth of
22756 		* the tree.
22757 		* An entry will be NULLed in selector_leave, i.e. when
22758 		* we hit the target's
22759 		*/
22760 		pos = sto->depth - matcher->depth;
22761 		idx = sto->sel->index;
22762 
22763 		/*
22764 		* Create/grow the array of key-sequences.
22765 		*/
22766 		if (matcher->keySeqs == NULL) {
22767 		    if (pos > 9)
22768 			matcher->sizeKeySeqs = pos * 2;
22769 		    else
22770 			matcher->sizeKeySeqs = 10;
22771 		    matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22772 			xmlMalloc(matcher->sizeKeySeqs *
22773 			sizeof(xmlSchemaPSVIIDCKeyPtr *));
22774 		    if (matcher->keySeqs == NULL) {
22775 			xmlSchemaVErrMemory(NULL,
22776 			    "allocating an array of key-sequences",
22777 			    NULL);
22778 			return(-1);
22779 		    }
22780 		    memset(matcher->keySeqs, 0,
22781 			matcher->sizeKeySeqs *
22782 			sizeof(xmlSchemaPSVIIDCKeyPtr *));
22783 		} else if (pos >= matcher->sizeKeySeqs) {
22784 		    int i = matcher->sizeKeySeqs;
22785 
22786 		    matcher->sizeKeySeqs *= 2;
22787 		    matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22788 			xmlRealloc(matcher->keySeqs,
22789 			matcher->sizeKeySeqs *
22790 			sizeof(xmlSchemaPSVIIDCKeyPtr *));
22791 		    if (matcher->keySeqs == NULL) {
22792 			xmlSchemaVErrMemory(NULL,
22793 			    "reallocating an array of key-sequences",
22794 			    NULL);
22795 			return (-1);
22796 		    }
22797 		    /*
22798 		    * The array needs to be NULLed.
22799 		    * TODO: Use memset?
22800 		    */
22801 		    for (; i < matcher->sizeKeySeqs; i++)
22802 			matcher->keySeqs[i] = NULL;
22803 		}
22804 
22805 		/*
22806 		* Get/create the key-sequence.
22807 		*/
22808 		keySeq = matcher->keySeqs[pos];
22809 		if (keySeq == NULL) {
22810 		    goto create_sequence;
22811 		} else if (keySeq[idx] != NULL) {
22812 		    xmlChar *str = NULL;
22813 		    /*
22814 		    * cvc-identity-constraint:
22815 		    * 3 For each node in the �target node set� all
22816 		    * of the {fields}, with that node as the context
22817 		    * node, evaluate to either an empty node-set or
22818 		    * a node-set with exactly one member, which must
22819 		    * have a simple type.
22820 		    *
22821 		    * The key was already set; report an error.
22822 		    */
22823 		    xmlSchemaCustomErr(ACTXT_CAST vctxt,
22824 			XML_SCHEMAV_CVC_IDC, NULL,
22825 			WXS_BASIC_CAST matcher->aidc->def,
22826 			"The XPath '%s' of a field of %s evaluates to a "
22827 			"node-set with more than one member",
22828 			sto->sel->xpath,
22829 			xmlSchemaGetIDCDesignation(&str, matcher->aidc->def));
22830 		    FREE_AND_NULL(str);
22831 		    sto->nbHistory--;
22832 		    goto deregister_check;
22833 		} else
22834 		    goto create_key;
22835 
22836 create_sequence:
22837 		/*
22838 		* Create a key-sequence.
22839 		*/
22840 		keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
22841 		    matcher->aidc->def->nbFields *
22842 		    sizeof(xmlSchemaPSVIIDCKeyPtr));
22843 		if (keySeq == NULL) {
22844 		    xmlSchemaVErrMemory(NULL,
22845 			"allocating an IDC key-sequence", NULL);
22846 		    return(-1);
22847 		}
22848 		memset(keySeq, 0, matcher->aidc->def->nbFields *
22849 		    sizeof(xmlSchemaPSVIIDCKeyPtr));
22850 		matcher->keySeqs[pos] = keySeq;
22851 create_key:
22852 		/*
22853 		* Create a key once per node only.
22854 		*/
22855 		if (key == NULL) {
22856 		    key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
22857 			sizeof(xmlSchemaPSVIIDCKey));
22858 		    if (key == NULL) {
22859 			xmlSchemaVErrMemory(NULL,
22860 			    "allocating a IDC key", NULL);
22861 			xmlFree(keySeq);
22862 			matcher->keySeqs[pos] = NULL;
22863 			return(-1);
22864 		    }
22865 		    /*
22866 		    * Consume the compiled value.
22867 		    */
22868 		    key->type = simpleType;
22869 		    key->val = vctxt->inode->val;
22870 		    vctxt->inode->val = NULL;
22871 		    /*
22872 		    * Store the key in a global list.
22873 		    */
22874 		    if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
22875 			xmlSchemaIDCFreeKey(key);
22876 			return (-1);
22877 		    }
22878 		}
22879 		keySeq[idx] = key;
22880 	    }
22881 	} else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22882 
22883 	    xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
22884 	    /* xmlSchemaPSVIIDCBindingPtr bind; */
22885 	    xmlSchemaPSVIIDCNodePtr ntItem;
22886 	    xmlSchemaIDCMatcherPtr matcher;
22887 	    xmlSchemaIDCPtr idc;
22888 	    xmlSchemaItemListPtr targets;
22889 	    int pos, i, j, nbKeys;
22890 	    /*
22891 	    * Here we have the following scenario:
22892 	    * An IDC 'selector' state object resolved to a target node,
22893 	    * during the time this target node was in the
22894 	    * ancestor-or-self axis, the 'field' state object(s) looked
22895 	    * out for matching nodes to create a key-sequence for this
22896 	    * target node. Now we are back to this target node and need
22897 	    * to put the key-sequence, together with the target node
22898 	    * itself, into the node-table of the corresponding IDC
22899 	    * binding.
22900 	    */
22901 	    matcher = sto->matcher;
22902 	    idc = matcher->aidc->def;
22903 	    nbKeys = idc->nbFields;
22904 	    pos = depth - matcher->depth;
22905 	    /*
22906 	    * Check if the matcher has any key-sequences at all, plus
22907 	    * if it has a key-sequence for the current target node.
22908 	    */
22909 	    if ((matcher->keySeqs == NULL) ||
22910 		(matcher->sizeKeySeqs <= pos)) {
22911 		if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22912 		    goto selector_key_error;
22913 		else
22914 		    goto selector_leave;
22915 	    }
22916 
22917 	    keySeq = &(matcher->keySeqs[pos]);
22918 	    if (*keySeq == NULL) {
22919 		if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22920 		    goto selector_key_error;
22921 		else
22922 		    goto selector_leave;
22923 	    }
22924 
22925 	    for (i = 0; i < nbKeys; i++) {
22926 		if ((*keySeq)[i] == NULL) {
22927 		    /*
22928 		    * Not qualified, if not all fields did resolve.
22929 		    */
22930 		    if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
22931 			/*
22932 			* All fields of a "key" IDC must resolve.
22933 			*/
22934 			goto selector_key_error;
22935 		    }
22936 		    goto selector_leave;
22937 		}
22938 	    }
22939 	    /*
22940 	    * All fields did resolve.
22941 	    */
22942 
22943 	    /*
22944 	    * 4.1 If the {identity-constraint category} is unique(/key),
22945 	    * then no two members of the �qualified node set� have
22946 	    * �key-sequences� whose members are pairwise equal, as
22947 	    * defined by Equal in [XML Schemas: Datatypes].
22948 	    *
22949 	    * Get the IDC binding from the matcher and check for
22950 	    * duplicate key-sequences.
22951 	    */
22952 #if 0
22953 	    bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
22954 #endif
22955 	    targets = xmlSchemaIDCAcquireTargetList(vctxt, matcher);
22956 	    if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
22957 		(targets->nbItems != 0)) {
22958 		xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
22959 
22960 		i = 0;
22961 		res = 0;
22962 		/*
22963 		* Compare the key-sequences, key by key.
22964 		*/
22965 		do {
22966 		    bkeySeq =
22967 			((xmlSchemaPSVIIDCNodePtr) targets->items[i])->keys;
22968 		    for (j = 0; j < nbKeys; j++) {
22969 			ckey = (*keySeq)[j];
22970 			bkey = bkeySeq[j];
22971 			res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
22972 			if (res == -1) {
22973 			    return (-1);
22974 			} else if (res == 0) {
22975 			    /*
22976 			    * One of the keys differs, so the key-sequence
22977 			    * won't be equal; get out.
22978 			    */
22979 			    break;
22980 			}
22981 		    }
22982 		    if (res == 1) {
22983 			/*
22984 			* Duplicate key-sequence found.
22985 			*/
22986 			break;
22987 		    }
22988 		    i++;
22989 		} while (i < targets->nbItems);
22990 		if (i != targets->nbItems) {
22991 		    xmlChar *str = NULL, *strB = NULL;
22992 		    /*
22993 		    * TODO: Try to report the key-sequence.
22994 		    */
22995 		    xmlSchemaCustomErr(ACTXT_CAST vctxt,
22996 			XML_SCHEMAV_CVC_IDC, NULL,
22997 			WXS_BASIC_CAST idc,
22998 			"Duplicate key-sequence %s in %s",
22999 			xmlSchemaFormatIDCKeySequence(vctxt, &str,
23000 			    (*keySeq), nbKeys),
23001 			xmlSchemaGetIDCDesignation(&strB, idc));
23002 		    FREE_AND_NULL(str);
23003 		    FREE_AND_NULL(strB);
23004 		    goto selector_leave;
23005 		}
23006 	    }
23007 	    /*
23008 	    * Add a node-table item to the IDC binding.
23009 	    */
23010 	    ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
23011 		sizeof(xmlSchemaPSVIIDCNode));
23012 	    if (ntItem == NULL) {
23013 		xmlSchemaVErrMemory(NULL,
23014 		    "allocating an IDC node-table item", NULL);
23015 		xmlFree(*keySeq);
23016 		*keySeq = NULL;
23017 		return(-1);
23018 	    }
23019 	    memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
23020 
23021 	    /*
23022 	    * Store the node-table item in a global list.
23023 	    */
23024 	    if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
23025 		if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
23026 		    xmlFree(ntItem);
23027 		    xmlFree(*keySeq);
23028 		    *keySeq = NULL;
23029 		    return (-1);
23030 		}
23031 		ntItem->nodeQNameID = -1;
23032 	    } else {
23033 		/*
23034 		* Save a cached QName for this node on the IDC node, to be
23035 		* able to report it, even if the node is not saved.
23036 		*/
23037 		ntItem->nodeQNameID = xmlSchemaVAddNodeQName(vctxt,
23038 		    vctxt->inode->localName, vctxt->inode->nsName);
23039 		if (ntItem->nodeQNameID == -1) {
23040 		    xmlFree(ntItem);
23041 		    xmlFree(*keySeq);
23042 		    *keySeq = NULL;
23043 		    return (-1);
23044 		}
23045 	    }
23046 	    /*
23047 	    * Init the node-table item: Save the node, position and
23048 	    * consume the key-sequence.
23049 	    */
23050 	    ntItem->node = vctxt->node;
23051 	    ntItem->nodeLine = vctxt->inode->nodeLine;
23052 	    ntItem->keys = *keySeq;
23053 	    *keySeq = NULL;
23054 #if 0
23055 	    if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1)
23056 #endif
23057 	    if (xmlSchemaItemListAdd(targets, ntItem) == -1) {
23058 		if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23059 		    /*
23060 		    * Free the item, since keyref items won't be
23061 		    * put on a global list.
23062 		    */
23063 		    xmlFree(ntItem->keys);
23064 		    xmlFree(ntItem);
23065 		}
23066 		return (-1);
23067 	    }
23068 
23069 	    goto selector_leave;
23070 selector_key_error:
23071 	    {
23072 		xmlChar *str = NULL;
23073 		/*
23074 		* 4.2.1 (KEY) The �target node set� and the
23075 		* �qualified node set� are equal, that is, every
23076 		* member of the �target node set� is also a member
23077 		* of the �qualified node set� and vice versa.
23078 		*/
23079 		xmlSchemaCustomErr(ACTXT_CAST vctxt,
23080 		    XML_SCHEMAV_CVC_IDC, NULL,
23081 		    WXS_BASIC_CAST idc,
23082 		    "Not all fields of %s evaluate to a node",
23083 		    xmlSchemaGetIDCDesignation(&str, idc), NULL);
23084 		FREE_AND_NULL(str);
23085 	    }
23086 selector_leave:
23087 	    /*
23088 	    * Free the key-sequence if not added to the IDC table.
23089 	    */
23090 	    if ((keySeq != NULL) && (*keySeq != NULL)) {
23091 		xmlFree(*keySeq);
23092 		*keySeq = NULL;
23093 	    }
23094 	} /* if selector */
23095 
23096 	sto->nbHistory--;
23097 
23098 deregister_check:
23099 	/*
23100 	* Deregister state objects if they reach the depth of creation.
23101 	*/
23102 	if ((sto->nbHistory == 0) && (sto->depth == depth)) {
23103 #ifdef DEBUG_IDC
23104 	    xmlGenericError(xmlGenericErrorContext, "IDC:   STO pop '%s'\n",
23105 		sto->sel->xpath);
23106 #endif
23107 	    if (vctxt->xpathStates != sto) {
23108 		VERROR_INT("xmlSchemaXPathProcessHistory",
23109 		    "The state object to be removed is not the first "
23110 		    "in the list");
23111 	    }
23112 	    nextsto = sto->next;
23113 	    /*
23114 	    * Unlink from the list of active XPath state objects.
23115 	    */
23116 	    vctxt->xpathStates = sto->next;
23117 	    sto->next = vctxt->xpathStatePool;
23118 	    /*
23119 	    * Link it to the pool of reusable state objects.
23120 	    */
23121 	    vctxt->xpathStatePool = sto;
23122 	    sto = nextsto;
23123 	} else
23124 	    sto = sto->next;
23125     } /* while (sto != NULL) */
23126     return (0);
23127 }
23128 
23129 /**
23130  * xmlSchemaIDCRegisterMatchers:
23131  * @vctxt: the WXS validation context
23132  * @elemDecl: the element declaration
23133  *
23134  * Creates helper objects to evaluate IDC selectors/fields
23135  * successively.
23136  *
23137  * Returns 0 if OK and -1 on internal errors.
23138  */
23139 static int
xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,xmlSchemaElementPtr elemDecl)23140 xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
23141 			     xmlSchemaElementPtr elemDecl)
23142 {
23143     xmlSchemaIDCMatcherPtr matcher, last = NULL;
23144     xmlSchemaIDCPtr idc, refIdc;
23145     xmlSchemaIDCAugPtr aidc;
23146 
23147     idc = (xmlSchemaIDCPtr) elemDecl->idcs;
23148     if (idc == NULL)
23149 	return (0);
23150 
23151 #ifdef DEBUG_IDC
23152     {
23153 	xmlChar *str = NULL;
23154 	xmlGenericError(xmlGenericErrorContext,
23155 	    "IDC: REGISTER on %s, depth %d\n",
23156 	    (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
23157 		vctxt->inode->localName), vctxt->depth);
23158 	FREE_AND_NULL(str)
23159     }
23160 #endif
23161     if (vctxt->inode->idcMatchers != NULL) {
23162 	VERROR_INT("xmlSchemaIDCRegisterMatchers",
23163 	    "The chain of IDC matchers is expected to be empty");
23164 	return (-1);
23165     }
23166     do {
23167 	if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23168 	    /*
23169 	    * Since IDCs bubbles are expensive we need to know the
23170 	    * depth at which the bubbles should stop; this will be
23171 	    * the depth of the top-most keyref IDC. If no keyref
23172 	    * references a key/unique IDC, the keyrefDepth will
23173 	    * be -1, indicating that no bubbles are needed.
23174 	    */
23175 	    refIdc = (xmlSchemaIDCPtr) idc->ref->item;
23176 	    if (refIdc != NULL) {
23177 		/*
23178 		* Remember that we have keyrefs on this node.
23179 		*/
23180 		vctxt->inode->hasKeyrefs = 1;
23181 		/*
23182 		* Lookup the referenced augmented IDC info.
23183 		*/
23184 		aidc = vctxt->aidcs;
23185 		while (aidc != NULL) {
23186 		    if (aidc->def == refIdc)
23187 			break;
23188 		    aidc = aidc->next;
23189 		}
23190 		if (aidc == NULL) {
23191 		    VERROR_INT("xmlSchemaIDCRegisterMatchers",
23192 			"Could not find an augmented IDC item for an IDC "
23193 			"definition");
23194 		    return (-1);
23195 		}
23196 		if ((aidc->keyrefDepth == -1) ||
23197 		    (vctxt->depth < aidc->keyrefDepth))
23198 		    aidc->keyrefDepth = vctxt->depth;
23199 	    }
23200 	}
23201 	/*
23202 	* Lookup the augmented IDC item for the IDC definition.
23203 	*/
23204 	aidc = vctxt->aidcs;
23205 	while (aidc != NULL) {
23206 	    if (aidc->def == idc)
23207 		break;
23208 	    aidc = aidc->next;
23209 	}
23210 	if (aidc == NULL) {
23211 	    VERROR_INT("xmlSchemaIDCRegisterMatchers",
23212 		"Could not find an augmented IDC item for an IDC definition");
23213 	    return (-1);
23214 	}
23215 	/*
23216 	* Create an IDC matcher for every IDC definition.
23217 	*/
23218 	if (vctxt->idcMatcherCache != NULL) {
23219 	    /*
23220 	    * Reuse a cached matcher.
23221 	    */
23222 	    matcher = vctxt->idcMatcherCache;
23223 	    vctxt->idcMatcherCache = matcher->nextCached;
23224 	    matcher->nextCached = NULL;
23225 	} else {
23226 	    matcher = (xmlSchemaIDCMatcherPtr)
23227 		xmlMalloc(sizeof(xmlSchemaIDCMatcher));
23228 	    if (matcher == NULL) {
23229 		xmlSchemaVErrMemory(vctxt,
23230 		    "allocating an IDC matcher", NULL);
23231 		return (-1);
23232 	    }
23233 	    memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
23234 	}
23235 	if (last == NULL)
23236 	    vctxt->inode->idcMatchers = matcher;
23237 	else
23238 	    last->next = matcher;
23239 	last = matcher;
23240 
23241 	matcher->type = IDC_MATCHER;
23242 	matcher->depth = vctxt->depth;
23243 	matcher->aidc = aidc;
23244 	matcher->idcType = aidc->def->type;
23245 #ifdef DEBUG_IDC
23246 	xmlGenericError(xmlGenericErrorContext, "IDC:   register matcher\n");
23247 #endif
23248 	/*
23249 	* Init the automaton state object.
23250 	*/
23251 	if (xmlSchemaIDCAddStateObject(vctxt, matcher,
23252 	    idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
23253 	    return (-1);
23254 
23255 	idc = idc->next;
23256     } while (idc != NULL);
23257     return (0);
23258 }
23259 
23260 static int
xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,xmlSchemaNodeInfoPtr ielem)23261 xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,
23262 			   xmlSchemaNodeInfoPtr ielem)
23263 {
23264     xmlSchemaPSVIIDCBindingPtr bind;
23265     int res, i, j, k, nbTargets, nbFields, nbDupls, nbNodeTable;
23266     xmlSchemaPSVIIDCKeyPtr *keys, *ntkeys;
23267     xmlSchemaPSVIIDCNodePtr *targets, *dupls;
23268 
23269     xmlSchemaIDCMatcherPtr matcher = ielem->idcMatchers;
23270     /* vctxt->createIDCNodeTables */
23271     while (matcher != NULL) {
23272 	/*
23273 	* Skip keyref IDCs and empty IDC target-lists.
23274 	*/
23275 	if ((matcher->aidc->def->type == XML_SCHEMA_TYPE_IDC_KEYREF) ||
23276 	    WXS_ILIST_IS_EMPTY(matcher->targets))
23277 	{
23278 	    matcher = matcher->next;
23279 	    continue;
23280 	}
23281 	/*
23282 	* If we _want_ the IDC node-table to be created in any case
23283 	* then do so. Otherwise create them only if keyrefs need them.
23284 	*/
23285 	if ((! vctxt->createIDCNodeTables) &&
23286 	    ((matcher->aidc->keyrefDepth == -1) ||
23287 	     (matcher->aidc->keyrefDepth > vctxt->depth)))
23288 	{
23289 	    matcher = matcher->next;
23290 	    continue;
23291 	}
23292 	/*
23293 	* Get/create the IDC binding on this element for the IDC definition.
23294 	*/
23295 	bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
23296 
23297 	if (! WXS_ILIST_IS_EMPTY(bind->dupls)) {
23298 	    dupls = (xmlSchemaPSVIIDCNodePtr *) bind->dupls->items;
23299 	    nbDupls = bind->dupls->nbItems;
23300 	} else {
23301 	    dupls = NULL;
23302 	    nbDupls = 0;
23303 	}
23304 	if (bind->nodeTable != NULL) {
23305 	    nbNodeTable = bind->nbNodes;
23306 	} else {
23307 	    nbNodeTable = 0;
23308 	}
23309 
23310 	if ((nbNodeTable == 0) && (nbDupls == 0)) {
23311 	    /*
23312 	    * Transfer all IDC target-nodes to the IDC node-table.
23313 	    */
23314 	    bind->nodeTable =
23315 		(xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23316 	    bind->sizeNodes = matcher->targets->sizeItems;
23317 	    bind->nbNodes = matcher->targets->nbItems;
23318 
23319 	    matcher->targets->items = NULL;
23320 	    matcher->targets->sizeItems = 0;
23321 	    matcher->targets->nbItems = 0;
23322 	} else {
23323 	    /*
23324 	    * Compare the key-sequences and add to the IDC node-table.
23325 	    */
23326 	    nbTargets = matcher->targets->nbItems;
23327 	    targets = (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23328 	    nbFields = matcher->aidc->def->nbFields;
23329 	    i = 0;
23330 	    do {
23331 		keys = targets[i]->keys;
23332 		if (nbDupls) {
23333 		    /*
23334 		    * Search in already found duplicates first.
23335 		    */
23336 		    j = 0;
23337 		    do {
23338 			if (nbFields == 1) {
23339 			    res = xmlSchemaAreValuesEqual(keys[0]->val,
23340 				dupls[j]->keys[0]->val);
23341 			    if (res == -1)
23342 				goto internal_error;
23343 			    if (res == 1) {
23344 				/*
23345 				* Equal key-sequence.
23346 				*/
23347 				goto next_target;
23348 			    }
23349 			} else {
23350 			    res = 0;
23351 			    ntkeys = dupls[j]->keys;
23352 			    for (k = 0; k < nbFields; k++) {
23353 				res = xmlSchemaAreValuesEqual(keys[k]->val,
23354 				    ntkeys[k]->val);
23355 				if (res == -1)
23356 				    goto internal_error;
23357 				if (res == 0) {
23358 				    /*
23359 				    * One of the keys differs.
23360 				    */
23361 				    break;
23362 				}
23363 			    }
23364 			    if (res == 1) {
23365 				/*
23366 				* Equal key-sequence found.
23367 				*/
23368 				goto next_target;
23369 			    }
23370 			}
23371 			j++;
23372 		    } while (j < nbDupls);
23373 		}
23374 		if (nbNodeTable) {
23375 		    j = 0;
23376 		    do {
23377 			if (nbFields == 1) {
23378 			    res = xmlSchemaAreValuesEqual(keys[0]->val,
23379 				bind->nodeTable[j]->keys[0]->val);
23380 			    if (res == -1)
23381 				goto internal_error;
23382 			    if (res == 0) {
23383 				/*
23384 				* The key-sequence differs.
23385 				*/
23386 				goto next_node_table_entry;
23387 			    }
23388 			} else {
23389 			    res = 0;
23390 			    ntkeys = bind->nodeTable[j]->keys;
23391 			    for (k = 0; k < nbFields; k++) {
23392 				res = xmlSchemaAreValuesEqual(keys[k]->val,
23393 				    ntkeys[k]->val);
23394 				if (res == -1)
23395 				    goto internal_error;
23396 				if (res == 0) {
23397 				    /*
23398 				    * One of the keys differs.
23399 				    */
23400 				    goto next_node_table_entry;
23401 				}
23402 			    }
23403 			}
23404 			/*
23405 			* Add the duplicate to the list of duplicates.
23406 			*/
23407 			if (bind->dupls == NULL) {
23408 			    bind->dupls = xmlSchemaItemListCreate();
23409 			    if (bind->dupls == NULL)
23410 				goto internal_error;
23411 			}
23412 			if (xmlSchemaItemListAdd(bind->dupls, bind->nodeTable[j]) == -1)
23413 			    goto internal_error;
23414 			/*
23415 			* Remove the duplicate entry from the IDC node-table.
23416 			*/
23417 			bind->nodeTable[j] = bind->nodeTable[bind->nbNodes -1];
23418 			bind->nbNodes--;
23419 
23420 			goto next_target;
23421 
23422 next_node_table_entry:
23423 			j++;
23424 		    } while (j < nbNodeTable);
23425 		}
23426 		/*
23427 		* If everything is fine, then add the IDC target-node to
23428 		* the IDC node-table.
23429 		*/
23430 		if (xmlSchemaIDCAppendNodeTableItem(bind, targets[i]) == -1)
23431 		    goto internal_error;
23432 
23433 next_target:
23434 		i++;
23435 	    } while (i < nbTargets);
23436 	}
23437 	matcher = matcher->next;
23438     }
23439     return(0);
23440 
23441 internal_error:
23442     return(-1);
23443 }
23444 
23445 /**
23446  * xmlSchemaBubbleIDCNodeTables:
23447  * @depth: the current tree depth
23448  *
23449  * Merges IDC bindings of an element at @depth into the corresponding IDC
23450  * bindings of its parent element. If a duplicate note-table entry is found,
23451  * both, the parent node-table entry and child entry are discarded from the
23452  * node-table of the parent.
23453  *
23454  * Returns 0 if OK and -1 on internal errors.
23455  */
23456 static int
xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)23457 xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
23458 {
23459     xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
23460     xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL; /* parent IDC bindings. */
23461     xmlSchemaPSVIIDCNodePtr node, parNode = NULL, *dupls, *parNodes; /* node-table entries. */
23462     xmlSchemaIDCAugPtr aidc;
23463     int i, j, k, ret = 0, nbFields, oldNum, oldDupls;
23464 
23465     bind = vctxt->inode->idcTable;
23466     if (bind == NULL) {
23467 	/* Fine, no table, no bubbles. */
23468 	return (0);
23469     }
23470 
23471     parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
23472     /*
23473     * Walk all bindings; create new or add to existing bindings.
23474     * Remove duplicate key-sequences.
23475     */
23476     while (bind != NULL) {
23477 
23478 	if ((bind->nbNodes == 0) && WXS_ILIST_IS_EMPTY(bind->dupls))
23479 	    goto next_binding;
23480 	/*
23481 	* Check if the key/unique IDC table needs to be bubbled.
23482 	*/
23483 	if (! vctxt->createIDCNodeTables) {
23484 	    aidc = vctxt->aidcs;
23485 	    do {
23486 		if (aidc->def == bind->definition) {
23487 		    if ((aidc->keyrefDepth == -1) ||
23488 			(aidc->keyrefDepth >= vctxt->depth)) {
23489 			goto next_binding;
23490 		    }
23491 		    break;
23492 		}
23493 		aidc = aidc->next;
23494 	    } while (aidc != NULL);
23495 	}
23496 
23497 	if (parTable != NULL)
23498 	    parBind = *parTable;
23499 	/*
23500 	* Search a matching parent binding for the
23501 	* IDC definition.
23502 	*/
23503 	while (parBind != NULL) {
23504 	    if (parBind->definition == bind->definition)
23505 		break;
23506 	    parBind = parBind->next;
23507 	}
23508 
23509 	if (parBind != NULL) {
23510 	    /*
23511 	    * Compare every node-table entry of the child node,
23512 	    * i.e. the key-sequence within, ...
23513 	    */
23514 	    oldNum = parBind->nbNodes; /* Skip newly added items. */
23515 
23516 	    if (! WXS_ILIST_IS_EMPTY(parBind->dupls)) {
23517 		oldDupls = parBind->dupls->nbItems;
23518 		dupls = (xmlSchemaPSVIIDCNodePtr *) parBind->dupls->items;
23519 	    } else {
23520 		dupls = NULL;
23521 		oldDupls = 0;
23522 	    }
23523 
23524 	    parNodes = parBind->nodeTable;
23525 	    nbFields = bind->definition->nbFields;
23526 
23527 	    for (i = 0; i < bind->nbNodes; i++) {
23528 		node = bind->nodeTable[i];
23529 		if (node == NULL)
23530 		    continue;
23531 		/*
23532 		* ...with every key-sequence of the parent node, already
23533 		* evaluated to be a duplicate key-sequence.
23534 		*/
23535 		if (oldDupls) {
23536 		    j = 0;
23537 		    while (j < oldDupls) {
23538 			if (nbFields == 1) {
23539 			    ret = xmlSchemaAreValuesEqual(
23540 				node->keys[0]->val,
23541 				dupls[j]->keys[0]->val);
23542 			    if (ret == -1)
23543 				goto internal_error;
23544 			    if (ret == 0) {
23545 				j++;
23546 				continue;
23547 			    }
23548 			} else {
23549 			    parNode = dupls[j];
23550 			    for (k = 0; k < nbFields; k++) {
23551 				ret = xmlSchemaAreValuesEqual(
23552 				    node->keys[k]->val,
23553 				    parNode->keys[k]->val);
23554 				if (ret == -1)
23555 				    goto internal_error;
23556 				if (ret == 0)
23557 				    break;
23558 			    }
23559 			}
23560 			if (ret == 1)
23561 			    /* Duplicate found. */
23562 			    break;
23563 			j++;
23564 		    }
23565 		    if (j != oldDupls) {
23566 			/* Duplicate found. Skip this entry. */
23567 			continue;
23568 		    }
23569 		}
23570 		/*
23571 		* ... and with every key-sequence of the parent node.
23572 		*/
23573 		if (oldNum) {
23574 		    j = 0;
23575 		    while (j < oldNum) {
23576 			parNode = parNodes[j];
23577 			if (nbFields == 1) {
23578 			    ret = xmlSchemaAreValuesEqual(
23579 				node->keys[0]->val,
23580 				parNode->keys[0]->val);
23581 			    if (ret == -1)
23582 				goto internal_error;
23583 			    if (ret == 0) {
23584 				j++;
23585 				continue;
23586 			    }
23587 			} else {
23588 			    for (k = 0; k < nbFields; k++) {
23589 				ret = xmlSchemaAreValuesEqual(
23590 				    node->keys[k]->val,
23591 				    parNode->keys[k]->val);
23592 				if (ret == -1)
23593 				    goto internal_error;
23594 				if (ret == 0)
23595 				    break;
23596 			    }
23597 			}
23598 			if (ret == 1)
23599 			    /* Duplicate found. */
23600 			    break;
23601 			j++;
23602 		    }
23603 		    if (j != oldNum) {
23604 			/*
23605 			* Handle duplicates. Move the duplicate in
23606 			* the parent's node-table to the list of
23607 			* duplicates.
23608 			*/
23609 			oldNum--;
23610 			parBind->nbNodes--;
23611 			/*
23612 			* Move last old item to pos of duplicate.
23613 			*/
23614 			parNodes[j] = parNodes[oldNum];
23615 
23616 			if (parBind->nbNodes != oldNum) {
23617 			    /*
23618 			    * If new items exist, move last new item to
23619 			    * last of old items.
23620 			    */
23621 			    parNodes[oldNum] =
23622 				parNodes[parBind->nbNodes];
23623 			}
23624 			if (parBind->dupls == NULL) {
23625 			    parBind->dupls = xmlSchemaItemListCreate();
23626 			    if (parBind->dupls == NULL)
23627 				goto internal_error;
23628 			}
23629 			xmlSchemaItemListAdd(parBind->dupls, parNode);
23630 		    } else {
23631 			/*
23632 			* Add the node-table entry (node and key-sequence) of
23633 			* the child node to the node table of the parent node.
23634 			*/
23635 			if (parBind->nodeTable == NULL) {
23636 			    parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23637 				xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
23638 			    if (parBind->nodeTable == NULL) {
23639 				xmlSchemaVErrMemory(NULL,
23640 				    "allocating IDC list of node-table items", NULL);
23641 				goto internal_error;
23642 			    }
23643 			    parBind->sizeNodes = 1;
23644 			} else if (parBind->nbNodes >= parBind->sizeNodes) {
23645 			    parBind->sizeNodes *= 2;
23646 			    parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23647 				xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
23648 				sizeof(xmlSchemaPSVIIDCNodePtr));
23649 			    if (parBind->nodeTable == NULL) {
23650 				xmlSchemaVErrMemory(NULL,
23651 				    "re-allocating IDC list of node-table items", NULL);
23652 				goto internal_error;
23653 			    }
23654 			}
23655 			parNodes = parBind->nodeTable;
23656 			/*
23657 			* Append the new node-table entry to the 'new node-table
23658 			* entries' section.
23659 			*/
23660 			parNodes[parBind->nbNodes++] = node;
23661 		    }
23662 
23663 		}
23664 
23665 	    }
23666 	} else {
23667 	    /*
23668 	    * No binding for the IDC was found: create a new one and
23669 	    * copy all node-tables.
23670 	    */
23671 	    parBind = xmlSchemaIDCNewBinding(bind->definition);
23672 	    if (parBind == NULL)
23673 		goto internal_error;
23674 
23675 	    /*
23676 	    * TODO: Hmm, how to optimize the initial number of
23677 	    * allocated entries?
23678 	    */
23679 	    if (bind->nbNodes != 0) {
23680 		/*
23681 		* Add all IDC node-table entries.
23682 		*/
23683 		if (! vctxt->psviExposeIDCNodeTables) {
23684 		    /*
23685 		    * Just move the entries.
23686 		    * NOTE: this is quite save here, since
23687 		    * all the keyref lookups have already been
23688 		    * performed.
23689 		    */
23690 		    parBind->nodeTable = bind->nodeTable;
23691 		    bind->nodeTable = NULL;
23692 		    parBind->sizeNodes = bind->sizeNodes;
23693 		    bind->sizeNodes = 0;
23694 		    parBind->nbNodes = bind->nbNodes;
23695 		    bind->nbNodes = 0;
23696 		} else {
23697 		    /*
23698 		    * Copy the entries.
23699 		    */
23700 		    parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23701 			xmlMalloc(bind->nbNodes *
23702 			sizeof(xmlSchemaPSVIIDCNodePtr));
23703 		    if (parBind->nodeTable == NULL) {
23704 			xmlSchemaVErrMemory(NULL,
23705 			    "allocating an array of IDC node-table "
23706 			    "items", NULL);
23707 			xmlSchemaIDCFreeBinding(parBind);
23708 			goto internal_error;
23709 		    }
23710 		    parBind->sizeNodes = bind->nbNodes;
23711 		    parBind->nbNodes = bind->nbNodes;
23712 		    memcpy(parBind->nodeTable, bind->nodeTable,
23713 			bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
23714 		}
23715 	    }
23716 	    if (bind->dupls) {
23717 		/*
23718 		* Move the duplicates.
23719 		*/
23720 		if (parBind->dupls != NULL)
23721 		    xmlSchemaItemListFree(parBind->dupls);
23722 		parBind->dupls = bind->dupls;
23723 		bind->dupls = NULL;
23724 	    }
23725             if (parTable != NULL) {
23726                 if (*parTable == NULL)
23727                     *parTable = parBind;
23728                 else {
23729                     parBind->next = *parTable;
23730                     *parTable = parBind;
23731                 }
23732             }
23733 	}
23734 
23735 next_binding:
23736 	bind = bind->next;
23737     }
23738     return (0);
23739 
23740 internal_error:
23741     return(-1);
23742 }
23743 
23744 /**
23745  * xmlSchemaCheckCVCIDCKeyRef:
23746  * @vctxt: the WXS validation context
23747  * @elemDecl: the element declaration
23748  *
23749  * Check the cvc-idc-keyref constraints.
23750  */
23751 static int
xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)23752 xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
23753 {
23754     xmlSchemaIDCMatcherPtr matcher;
23755     xmlSchemaPSVIIDCBindingPtr bind;
23756 
23757     matcher = vctxt->inode->idcMatchers;
23758     /*
23759     * Find a keyref.
23760     */
23761     while (matcher != NULL) {
23762 	if ((matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) &&
23763 	    matcher->targets &&
23764 	    matcher->targets->nbItems)
23765 	{
23766 	    int i, j, k, res, nbFields, hasDupls;
23767 	    xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
23768 	    xmlSchemaPSVIIDCNodePtr refNode = NULL;
23769 
23770 	    nbFields = matcher->aidc->def->nbFields;
23771 
23772 	    /*
23773 	    * Find the IDC node-table for the referenced IDC key/unique.
23774 	    */
23775 	    bind = vctxt->inode->idcTable;
23776 	    while (bind != NULL) {
23777 		if ((xmlSchemaIDCPtr) matcher->aidc->def->ref->item ==
23778 		    bind->definition)
23779 		    break;
23780 		bind = bind->next;
23781 	    }
23782 	    hasDupls = (bind && bind->dupls && bind->dupls->nbItems) ? 1 : 0;
23783 	    /*
23784 	    * Search for a matching key-sequences.
23785 	    */
23786 	    for (i = 0; i < matcher->targets->nbItems; i++) {
23787 		res = 0;
23788 		refNode = matcher->targets->items[i];
23789 		if (bind != NULL) {
23790 		    refKeys = refNode->keys;
23791 		    for (j = 0; j < bind->nbNodes; j++) {
23792 			keys = bind->nodeTable[j]->keys;
23793 			for (k = 0; k < nbFields; k++) {
23794 			    res = xmlSchemaAreValuesEqual(keys[k]->val,
23795 				refKeys[k]->val);
23796 			    if (res == 0)
23797 				break;
23798 			    else if (res == -1) {
23799 				return (-1);
23800 			    }
23801 			}
23802 			if (res == 1) {
23803 			    /*
23804 			    * Match found.
23805 			    */
23806 			    break;
23807 			}
23808 		    }
23809 		    if ((res == 0) && hasDupls) {
23810 			/*
23811 			* Search in duplicates
23812 			*/
23813 			for (j = 0; j < bind->dupls->nbItems; j++) {
23814 			    keys = ((xmlSchemaPSVIIDCNodePtr)
23815 				bind->dupls->items[j])->keys;
23816 			    for (k = 0; k < nbFields; k++) {
23817 				res = xmlSchemaAreValuesEqual(keys[k]->val,
23818 				    refKeys[k]->val);
23819 				if (res == 0)
23820 				    break;
23821 				else if (res == -1) {
23822 				    return (-1);
23823 				}
23824 			    }
23825 			    if (res == 1) {
23826 				/*
23827 				* Match in duplicates found.
23828 				*/
23829 				xmlChar *str = NULL, *strB = NULL;
23830 				xmlSchemaKeyrefErr(vctxt,
23831 				    XML_SCHEMAV_CVC_IDC, refNode,
23832 				    (xmlSchemaTypePtr) matcher->aidc->def,
23833 				    "More than one match found for "
23834 				    "key-sequence %s of keyref '%s'",
23835 				    xmlSchemaFormatIDCKeySequence(vctxt, &str,
23836 					refNode->keys, nbFields),
23837 				    xmlSchemaGetComponentQName(&strB,
23838 					matcher->aidc->def));
23839 				FREE_AND_NULL(str);
23840 				FREE_AND_NULL(strB);
23841 				break;
23842 			    }
23843 			}
23844 		    }
23845 		}
23846 
23847 		if (res == 0) {
23848 		    xmlChar *str = NULL, *strB = NULL;
23849 		    xmlSchemaKeyrefErr(vctxt,
23850 			XML_SCHEMAV_CVC_IDC, refNode,
23851 			(xmlSchemaTypePtr) matcher->aidc->def,
23852 			"No match found for key-sequence %s of keyref '%s'",
23853 			xmlSchemaFormatIDCKeySequence(vctxt, &str,
23854 			    refNode->keys, nbFields),
23855 			xmlSchemaGetComponentQName(&strB, matcher->aidc->def));
23856 		    FREE_AND_NULL(str);
23857 		    FREE_AND_NULL(strB);
23858 		}
23859 	    }
23860 	}
23861 	matcher = matcher->next;
23862     }
23863     /* TODO: Return an error if any error encountered. */
23864     return (0);
23865 }
23866 
23867 /************************************************************************
23868  * 									*
23869  * 			XML Reader validation code                      *
23870  * 									*
23871  ************************************************************************/
23872 
23873 static xmlSchemaAttrInfoPtr
xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)23874 xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
23875 {
23876     xmlSchemaAttrInfoPtr iattr;
23877     /*
23878     * Grow/create list of attribute infos.
23879     */
23880     if (vctxt->attrInfos == NULL) {
23881 	vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23882 	    xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
23883 	vctxt->sizeAttrInfos = 1;
23884 	if (vctxt->attrInfos == NULL) {
23885 	    xmlSchemaVErrMemory(vctxt,
23886 		"allocating attribute info list", NULL);
23887 	    return (NULL);
23888 	}
23889     } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
23890 	vctxt->sizeAttrInfos++;
23891 	vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23892 	    xmlRealloc(vctxt->attrInfos,
23893 		vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
23894 	if (vctxt->attrInfos == NULL) {
23895 	    xmlSchemaVErrMemory(vctxt,
23896 		"re-allocating attribute info list", NULL);
23897 	    return (NULL);
23898 	}
23899     } else {
23900 	iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
23901 	if (iattr->localName != NULL) {
23902 	    VERROR_INT("xmlSchemaGetFreshAttrInfo",
23903 		"attr info not cleared");
23904 	    return (NULL);
23905 	}
23906 	iattr->nodeType = XML_ATTRIBUTE_NODE;
23907 	return (iattr);
23908     }
23909     /*
23910     * Create an attribute info.
23911     */
23912     iattr = (xmlSchemaAttrInfoPtr)
23913 	xmlMalloc(sizeof(xmlSchemaAttrInfo));
23914     if (iattr == NULL) {
23915 	xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
23916 	return (NULL);
23917     }
23918     memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
23919     iattr->nodeType = XML_ATTRIBUTE_NODE;
23920     vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
23921 
23922     return (iattr);
23923 }
23924 
23925 static int
xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,xmlNodePtr attrNode,int nodeLine,const xmlChar * localName,const xmlChar * nsName,int ownedNames,xmlChar * value,int ownedValue)23926 xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
23927 			xmlNodePtr attrNode,
23928 			int nodeLine,
23929 			const xmlChar *localName,
23930 			const xmlChar *nsName,
23931 			int ownedNames,
23932 			xmlChar *value,
23933 			int ownedValue)
23934 {
23935     xmlSchemaAttrInfoPtr attr;
23936 
23937     attr = xmlSchemaGetFreshAttrInfo(vctxt);
23938     if (attr == NULL) {
23939 	VERROR_INT("xmlSchemaPushAttribute",
23940 	    "calling xmlSchemaGetFreshAttrInfo()");
23941 	return (-1);
23942     }
23943     attr->node = attrNode;
23944     attr->nodeLine = nodeLine;
23945     attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
23946     attr->localName = localName;
23947     attr->nsName = nsName;
23948     if (ownedNames)
23949 	attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
23950     /*
23951     * Evaluate if it's an XSI attribute.
23952     */
23953     if (nsName != NULL) {
23954 	if (xmlStrEqual(localName, BAD_CAST "nil")) {
23955 	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23956 		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
23957 	    }
23958 	} else if (xmlStrEqual(localName, BAD_CAST "type")) {
23959 	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23960 		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
23961 	    }
23962 	} else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
23963 	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23964 		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
23965 	    }
23966 	} else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
23967 	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23968 		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
23969 	    }
23970 	} else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
23971 	    attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
23972 	}
23973     }
23974     attr->value = value;
23975     if (ownedValue)
23976 	attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
23977     if (attr->metaType != 0)
23978 	attr->state = XML_SCHEMAS_ATTR_META;
23979     return (0);
23980 }
23981 
23982 /**
23983  * xmlSchemaClearElemInfo:
23984  * @vctxt: the WXS validation context
23985  * @ielem: the element information item
23986  */
23987 static void
xmlSchemaClearElemInfo(xmlSchemaValidCtxtPtr vctxt,xmlSchemaNodeInfoPtr ielem)23988 xmlSchemaClearElemInfo(xmlSchemaValidCtxtPtr vctxt,
23989 		       xmlSchemaNodeInfoPtr ielem)
23990 {
23991     ielem->hasKeyrefs = 0;
23992     ielem->appliedXPath = 0;
23993     if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
23994 	FREE_AND_NULL(ielem->localName);
23995 	FREE_AND_NULL(ielem->nsName);
23996     } else {
23997 	ielem->localName = NULL;
23998 	ielem->nsName = NULL;
23999     }
24000     if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
24001 	FREE_AND_NULL(ielem->value);
24002     } else {
24003 	ielem->value = NULL;
24004     }
24005     if (ielem->val != NULL) {
24006 	/*
24007 	* PSVI TODO: Be careful not to free it when the value is
24008 	* exposed via PSVI.
24009 	*/
24010 	xmlSchemaFreeValue(ielem->val);
24011 	ielem->val = NULL;
24012     }
24013     if (ielem->idcMatchers != NULL) {
24014 	/*
24015 	* REVISIT OPTIMIZE TODO: Use a pool of IDC matchers.
24016 	*   Does it work?
24017 	*/
24018 	xmlSchemaIDCReleaseMatcherList(vctxt, ielem->idcMatchers);
24019 #if 0
24020 	xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
24021 #endif
24022 	ielem->idcMatchers = NULL;
24023     }
24024     if (ielem->idcTable != NULL) {
24025 	/*
24026 	* OPTIMIZE TODO: Use a pool of IDC tables??.
24027 	*/
24028 	xmlSchemaIDCFreeIDCTable(ielem->idcTable);
24029 	ielem->idcTable = NULL;
24030     }
24031     if (ielem->regexCtxt != NULL) {
24032 	xmlRegFreeExecCtxt(ielem->regexCtxt);
24033 	ielem->regexCtxt = NULL;
24034     }
24035     if (ielem->nsBindings != NULL) {
24036 	xmlFree((xmlChar **)ielem->nsBindings);
24037 	ielem->nsBindings = NULL;
24038 	ielem->nbNsBindings = 0;
24039 	ielem->sizeNsBindings = 0;
24040     }
24041 }
24042 
24043 /**
24044  * xmlSchemaGetFreshElemInfo:
24045  * @vctxt: the schema validation context
24046  *
24047  * Creates/reuses and initializes the element info item for
24048  * the currect tree depth.
24049  *
24050  * Returns the element info item or NULL on API or internal errors.
24051  */
24052 static xmlSchemaNodeInfoPtr
xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)24053 xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
24054 {
24055     xmlSchemaNodeInfoPtr info = NULL;
24056 
24057     if (vctxt->depth > vctxt->sizeElemInfos) {
24058 	VERROR_INT("xmlSchemaGetFreshElemInfo",
24059 	    "inconsistent depth encountered");
24060 	return (NULL);
24061     }
24062     if (vctxt->elemInfos == NULL) {
24063 	vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24064 	    xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
24065 	if (vctxt->elemInfos == NULL) {
24066 	    xmlSchemaVErrMemory(vctxt,
24067 		"allocating the element info array", NULL);
24068 	    return (NULL);
24069 	}
24070 	memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
24071 	vctxt->sizeElemInfos = 10;
24072     } else if (vctxt->sizeElemInfos <= vctxt->depth) {
24073 	int i = vctxt->sizeElemInfos;
24074 
24075 	vctxt->sizeElemInfos *= 2;
24076 	vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24077 	    xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
24078 	    sizeof(xmlSchemaNodeInfoPtr));
24079 	if (vctxt->elemInfos == NULL) {
24080 	    xmlSchemaVErrMemory(vctxt,
24081 		"re-allocating the element info array", NULL);
24082 	    return (NULL);
24083 	}
24084 	/*
24085 	* We need the new memory to be NULLed.
24086 	* TODO: Use memset instead?
24087 	*/
24088 	for (; i < vctxt->sizeElemInfos; i++)
24089 	    vctxt->elemInfos[i] = NULL;
24090     } else
24091 	info = vctxt->elemInfos[vctxt->depth];
24092 
24093     if (info == NULL) {
24094 	info = (xmlSchemaNodeInfoPtr)
24095 	    xmlMalloc(sizeof(xmlSchemaNodeInfo));
24096 	if (info == NULL) {
24097 	    xmlSchemaVErrMemory(vctxt,
24098 		"allocating an element info", NULL);
24099 	    return (NULL);
24100 	}
24101 	vctxt->elemInfos[vctxt->depth] = info;
24102     } else {
24103 	if (info->localName != NULL) {
24104 	    VERROR_INT("xmlSchemaGetFreshElemInfo",
24105 		"elem info has not been cleared");
24106 	    return (NULL);
24107 	}
24108     }
24109     memset(info, 0, sizeof(xmlSchemaNodeInfo));
24110     info->nodeType = XML_ELEMENT_NODE;
24111     info->depth = vctxt->depth;
24112 
24113     return (info);
24114 }
24115 
24116 #define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
24117 #define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
24118 #define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
24119 
24120 static int
xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,xmlNodePtr node,xmlSchemaTypePtr type,xmlSchemaValType valType,const xmlChar * value,xmlSchemaValPtr val,unsigned long length,int fireErrors)24121 xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
24122 			xmlNodePtr node,
24123 			xmlSchemaTypePtr type,
24124 			xmlSchemaValType valType,
24125 			const xmlChar * value,
24126 			xmlSchemaValPtr val,
24127 			unsigned long length,
24128 			int fireErrors)
24129 {
24130     int ret, error = 0;
24131 
24132     xmlSchemaTypePtr tmpType;
24133     xmlSchemaFacetLinkPtr facetLink;
24134     xmlSchemaFacetPtr facet;
24135     unsigned long len = 0;
24136     xmlSchemaWhitespaceValueType ws;
24137 
24138     /*
24139     * In Libxml2, derived built-in types have currently no explicit facets.
24140     */
24141     if (type->type == XML_SCHEMA_TYPE_BASIC)
24142 	return (0);
24143 
24144     /*
24145     * NOTE: Do not jump away, if the facetSet of the given type is
24146     * empty: until now, "pattern" and "enumeration" facets of the
24147     * *base types* need to be checked as well.
24148     */
24149     if (type->facetSet == NULL)
24150 	goto pattern_and_enum;
24151 
24152     if (! WXS_IS_ATOMIC(type)) {
24153 	if (WXS_IS_LIST(type))
24154 	    goto WXS_IS_LIST;
24155 	else
24156 	    goto pattern_and_enum;
24157     }
24158     /*
24159     * Whitespace handling is only of importance for string-based
24160     * types.
24161     */
24162     tmpType = xmlSchemaGetPrimitiveType(type);
24163     if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
24164 	WXS_IS_ANY_SIMPLE_TYPE(tmpType)) {
24165 	ws = xmlSchemaGetWhiteSpaceFacetValue(type);
24166     } else
24167 	ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
24168     /*
24169     * If the value was not computed (for string or
24170     * anySimpleType based types), then use the provided
24171     * type.
24172     */
24173     if (val == NULL)
24174 	valType = valType;
24175     else
24176 	valType = xmlSchemaGetValType(val);
24177 
24178     ret = 0;
24179     for (facetLink = type->facetSet; facetLink != NULL;
24180 	facetLink = facetLink->next) {
24181 	/*
24182 	* Skip the pattern "whiteSpace": it is used to
24183 	* format the character content beforehand.
24184 	*/
24185 	switch (facetLink->facet->type) {
24186 	    case XML_SCHEMA_FACET_WHITESPACE:
24187 	    case XML_SCHEMA_FACET_PATTERN:
24188 	    case XML_SCHEMA_FACET_ENUMERATION:
24189 		continue;
24190 	    case XML_SCHEMA_FACET_LENGTH:
24191 	    case XML_SCHEMA_FACET_MINLENGTH:
24192 	    case XML_SCHEMA_FACET_MAXLENGTH:
24193 		ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
24194 		    valType, value, val, &len, ws);
24195 		break;
24196 	    default:
24197 		ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
24198 		    valType, value, val, ws);
24199 		break;
24200 	}
24201 	if (ret < 0) {
24202 	    AERROR_INT("xmlSchemaValidateFacets",
24203 		"validating against a atomic type facet");
24204 	    return (-1);
24205 	} else if (ret > 0) {
24206 	    if (fireErrors)
24207 		xmlSchemaFacetErr(actxt, ret, node,
24208 		value, len, type, facetLink->facet, NULL, NULL, NULL);
24209 	    else
24210 		return (ret);
24211 	    if (error == 0)
24212 		error = ret;
24213 	}
24214 	ret = 0;
24215     }
24216 
24217 WXS_IS_LIST:
24218     if (! WXS_IS_LIST(type))
24219 	goto pattern_and_enum;
24220     /*
24221     * "length", "minLength" and "maxLength" of list types.
24222     */
24223     ret = 0;
24224     for (facetLink = type->facetSet; facetLink != NULL;
24225 	facetLink = facetLink->next) {
24226 
24227 	switch (facetLink->facet->type) {
24228 	    case XML_SCHEMA_FACET_LENGTH:
24229 	    case XML_SCHEMA_FACET_MINLENGTH:
24230 	    case XML_SCHEMA_FACET_MAXLENGTH:
24231 		ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
24232 		    value, length, NULL);
24233 		break;
24234 	    default:
24235 		continue;
24236 	}
24237 	if (ret < 0) {
24238 	    AERROR_INT("xmlSchemaValidateFacets",
24239 		"validating against a list type facet");
24240 	    return (-1);
24241 	} else if (ret > 0) {
24242 	    if (fireErrors)
24243 		xmlSchemaFacetErr(actxt, ret, node,
24244 		value, length, type, facetLink->facet, NULL, NULL, NULL);
24245 	    else
24246 		return (ret);
24247 	    if (error == 0)
24248 		error = ret;
24249 	}
24250 	ret = 0;
24251     }
24252 
24253 pattern_and_enum:
24254     if (error >= 0) {
24255 	int found = 0;
24256 	/*
24257 	* Process enumerations. Facet values are in the value space
24258 	* of the defining type's base type. This seems to be a bug in the
24259 	* XML Schema 1.0 spec. Use the whitespace type of the base type.
24260 	* Only the first set of enumerations in the ancestor-or-self axis
24261 	* is used for validation.
24262 	*/
24263 	ret = 0;
24264 	tmpType = type;
24265 	do {
24266 	    for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
24267 		if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
24268 		    continue;
24269 		found = 1;
24270 		ret = xmlSchemaAreValuesEqual(facet->val, val);
24271 		if (ret == 1)
24272 		    break;
24273 		else if (ret < 0) {
24274 		    AERROR_INT("xmlSchemaValidateFacets",
24275 			"validating against an enumeration facet");
24276 		    return (-1);
24277 		}
24278 	    }
24279 	    if (ret != 0)
24280 		break;
24281 	    /*
24282 	    * Break on the first set of enumerations. Any additional
24283 	    *  enumerations which might be existent on the ancestors
24284 	    *  of the current type are restricted by this set; thus
24285 	    *  *must* *not* be taken into account.
24286 	    */
24287 	    if (found)
24288 		break;
24289 	    tmpType = tmpType->baseType;
24290 	} while ((tmpType != NULL) &&
24291 	    (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24292 	if (found && (ret == 0)) {
24293 	    ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
24294 	    if (fireErrors) {
24295 		xmlSchemaFacetErr(actxt, ret, node,
24296 		    value, 0, type, NULL, NULL, NULL, NULL);
24297 	    } else
24298 		return (ret);
24299 	    if (error == 0)
24300 		error = ret;
24301 	}
24302     }
24303 
24304     if (error >= 0) {
24305 	int found;
24306 	/*
24307 	* Process patters. Pattern facets are ORed at type level
24308 	* and ANDed if derived. Walk the base type axis.
24309 	*/
24310 	tmpType = type;
24311 	facet = NULL;
24312 	do {
24313 	    found = 0;
24314 	    for (facetLink = tmpType->facetSet; facetLink != NULL;
24315 		facetLink = facetLink->next) {
24316 		if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
24317 		    continue;
24318 		found = 1;
24319 		/*
24320 		* NOTE that for patterns, @value needs to be the
24321 		* normalized vaule.
24322 		*/
24323 		ret = xmlRegexpExec(facetLink->facet->regexp, value);
24324 		if (ret == 1)
24325 		    break;
24326 		else if (ret < 0) {
24327 		    AERROR_INT("xmlSchemaValidateFacets",
24328 			"validating against a pattern facet");
24329 		    return (-1);
24330 		} else {
24331 		    /*
24332 		    * Save the last non-validating facet.
24333 		    */
24334 		    facet = facetLink->facet;
24335 		}
24336 	    }
24337 	    if (found && (ret != 1)) {
24338 		ret = XML_SCHEMAV_CVC_PATTERN_VALID;
24339 		if (fireErrors) {
24340 		    xmlSchemaFacetErr(actxt, ret, node,
24341 			value, 0, type, facet, NULL, NULL, NULL);
24342 		} else
24343 		    return (ret);
24344 		if (error == 0)
24345 		    error = ret;
24346 		break;
24347 	    }
24348 	    tmpType = tmpType->baseType;
24349 	} while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24350     }
24351 
24352     return (error);
24353 }
24354 
24355 static xmlChar *
xmlSchemaNormalizeValue(xmlSchemaTypePtr type,const xmlChar * value)24356 xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
24357 			const xmlChar *value)
24358 {
24359     switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
24360 	case XML_SCHEMA_WHITESPACE_COLLAPSE:
24361 	    return (xmlSchemaCollapseString(value));
24362 	case XML_SCHEMA_WHITESPACE_REPLACE:
24363 	    return (xmlSchemaWhiteSpaceReplace(value));
24364 	default:
24365 	    return (NULL);
24366     }
24367 }
24368 
24369 static int
xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,const xmlChar * value,xmlSchemaValPtr * val,int valNeeded)24370 xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
24371 		       const xmlChar *value,
24372 		       xmlSchemaValPtr *val,
24373 		       int valNeeded)
24374 {
24375     int ret;
24376     const xmlChar *nsName;
24377     xmlChar *local, *prefix = NULL;
24378 
24379     ret = xmlValidateQName(value, 1);
24380     if (ret != 0) {
24381 	if (ret == -1) {
24382 	    VERROR_INT("xmlSchemaValidateQName",
24383 		"calling xmlValidateQName()");
24384 	    return (-1);
24385 	}
24386 	return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
24387     }
24388     /*
24389     * NOTE: xmlSplitQName2 will always return a duplicated
24390     * strings.
24391     */
24392     local = xmlSplitQName2(value, &prefix);
24393     if (local == NULL)
24394 	local = xmlStrdup(value);
24395     /*
24396     * OPTIMIZE TODO: Use flags for:
24397     *  - is there any namespace binding?
24398     *  - is there a default namespace?
24399     */
24400     nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24401 
24402     if (prefix != NULL) {
24403 	xmlFree(prefix);
24404 	/*
24405 	* A namespace must be found if the prefix is
24406 	* NOT NULL.
24407 	*/
24408 	if (nsName == NULL) {
24409 	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24410 	    xmlSchemaCustomErr(ACTXT_CAST vctxt, ret, NULL,
24411 		WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24412 		"The QName value '%s' has no "
24413 		"corresponding namespace declaration in "
24414 		"scope", value, NULL);
24415 	    if (local != NULL)
24416 		xmlFree(local);
24417 	    return (ret);
24418 	}
24419     }
24420     if (valNeeded && val) {
24421 	if (nsName != NULL)
24422 	    *val = xmlSchemaNewQNameValue(
24423 		BAD_CAST xmlStrdup(nsName), BAD_CAST local);
24424 	else
24425 	    *val = xmlSchemaNewQNameValue(NULL,
24426 		BAD_CAST local);
24427     } else
24428 	xmlFree(local);
24429     return (0);
24430 }
24431 
24432 /*
24433 * cvc-simple-type
24434 */
24435 static int
xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,xmlNodePtr node,xmlSchemaTypePtr type,const xmlChar * value,xmlSchemaValPtr * retVal,int fireErrors,int normalize,int isNormalized)24436 xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
24437 			     xmlNodePtr node,
24438 			     xmlSchemaTypePtr type,
24439 			     const xmlChar *value,
24440 			     xmlSchemaValPtr *retVal,
24441 			     int fireErrors,
24442 			     int normalize,
24443 			     int isNormalized)
24444 {
24445     int ret = 0, valNeeded = (retVal) ? 1 : 0;
24446     xmlSchemaValPtr val = NULL;
24447     /* xmlSchemaWhitespaceValueType ws; */
24448     xmlChar *normValue = NULL;
24449 
24450 #define NORMALIZE(atype) \
24451     if ((! isNormalized) && \
24452     (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
24453 	normValue = xmlSchemaNormalizeValue(atype, value); \
24454 	if (normValue != NULL) \
24455 	    value = normValue; \
24456 	isNormalized = 1; \
24457     }
24458 
24459     if ((retVal != NULL) && (*retVal != NULL)) {
24460 	xmlSchemaFreeValue(*retVal);
24461 	*retVal = NULL;
24462     }
24463     /*
24464     * 3.14.4 Simple Type Definition Validation Rules
24465     * Validation Rule: String Valid
24466     */
24467     /*
24468     * 1 It is schema-valid with respect to that definition as defined
24469     * by Datatype Valid in [XML Schemas: Datatypes].
24470     */
24471     /*
24472     * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
24473     * the empty set, as defined in Type Derivation OK (Simple) (�3.14.6), then
24474     * the string must be a �declared entity name�.
24475     */
24476     /*
24477     * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
24478     * given the empty set, as defined in Type Derivation OK (Simple) (�3.14.6),
24479     * then every whitespace-delimited substring of the string must be a �declared
24480     * entity name�.
24481     */
24482     /*
24483     * 2.3 otherwise no further condition applies.
24484     */
24485     if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
24486 	valNeeded = 1;
24487     if (value == NULL)
24488 	value = BAD_CAST "";
24489     if (WXS_IS_ANY_SIMPLE_TYPE(type) || WXS_IS_ATOMIC(type)) {
24490 	xmlSchemaTypePtr biType; /* The built-in type. */
24491 	/*
24492 	* SPEC (1.2.1) "if {variety} is �atomic� then the string must �match�
24493 	* a literal in the �lexical space� of {base type definition}"
24494 	*/
24495 	/*
24496 	* Whitespace-normalize.
24497 	*/
24498 	NORMALIZE(type);
24499 	if (type->type != XML_SCHEMA_TYPE_BASIC) {
24500 	    /*
24501 	    * Get the built-in type.
24502 	    */
24503 	    biType = type->baseType;
24504 	    while ((biType != NULL) &&
24505 		(biType->type != XML_SCHEMA_TYPE_BASIC))
24506 		biType = biType->baseType;
24507 
24508 	    if (biType == NULL) {
24509 		AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24510 		    "could not get the built-in type");
24511 		goto internal_error;
24512 	    }
24513 	} else
24514 	    biType = type;
24515 	/*
24516 	* NOTATIONs need to be processed here, since they need
24517 	* to lookup in the hashtable of NOTATION declarations of the schema.
24518 	*/
24519 	if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
24520 	    switch (biType->builtInType) {
24521 		case XML_SCHEMAS_NOTATION:
24522 		    ret = xmlSchemaValidateNotation(
24523 			(xmlSchemaValidCtxtPtr) actxt,
24524 			((xmlSchemaValidCtxtPtr) actxt)->schema,
24525 			NULL, value, &val, valNeeded);
24526 		    break;
24527 		case XML_SCHEMAS_QNAME:
24528 		    ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
24529 			value, &val, valNeeded);
24530 		    break;
24531 		default:
24532 		    /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24533 		    if (valNeeded)
24534 			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24535 			    value, &val, node);
24536 		    else
24537 			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24538 			    value, NULL, node);
24539 		    break;
24540 	    }
24541 	} else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
24542 	    switch (biType->builtInType) {
24543 		case XML_SCHEMAS_NOTATION:
24544 		    ret = xmlSchemaValidateNotation(NULL,
24545 			((xmlSchemaParserCtxtPtr) actxt)->schema, node,
24546 			value, &val, valNeeded);
24547 		    break;
24548 		default:
24549 		    /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24550 		    if (valNeeded)
24551 			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24552 			    value, &val, node);
24553 		    else
24554 			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24555 			    value, NULL, node);
24556 		    break;
24557 	    }
24558 	} else {
24559 	    /*
24560 	    * Validation via a public API is not implemented yet.
24561 	    */
24562 	    TODO
24563 	    goto internal_error;
24564 	}
24565 	if (ret != 0) {
24566 	    if (ret < 0) {
24567 		AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24568 		    "validating against a built-in type");
24569 		goto internal_error;
24570 	    }
24571 	    if (WXS_IS_LIST(type))
24572 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24573 	    else
24574 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24575 	}
24576 	if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24577 	    /*
24578 	    * Check facets.
24579 	    */
24580 	    ret = xmlSchemaValidateFacets(actxt, node, type,
24581 		(xmlSchemaValType) biType->builtInType, value, val,
24582 		0, fireErrors);
24583 	    if (ret != 0) {
24584 		if (ret < 0) {
24585 		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24586 			"validating facets of atomic simple type");
24587 		    goto internal_error;
24588 		}
24589 		if (WXS_IS_LIST(type))
24590 		    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24591 		else
24592 		    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24593 	    }
24594 	}
24595 	if (fireErrors && (ret > 0))
24596 	    xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24597     } else if (WXS_IS_LIST(type)) {
24598 
24599 	xmlSchemaTypePtr itemType;
24600 	const xmlChar *cur, *end;
24601 	xmlChar *tmpValue = NULL;
24602 	unsigned long len = 0;
24603 	xmlSchemaValPtr prevVal = NULL, curVal = NULL;
24604 	/* 1.2.2 if {variety} is �list� then the string must be a sequence
24605 	* of white space separated tokens, each of which �match�es a literal
24606 	* in the �lexical space� of {item type definition}
24607 	*/
24608 	/*
24609 	* Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
24610 	* the list type has an enum or pattern facet.
24611 	*/
24612 	NORMALIZE(type);
24613 	/*
24614 	* VAL TODO: Optimize validation of empty values.
24615 	* VAL TODO: We do not have computed values for lists.
24616 	*/
24617 	itemType = WXS_LIST_ITEMTYPE(type);
24618 	cur = value;
24619 	do {
24620 	    while (IS_BLANK_CH(*cur))
24621 		cur++;
24622 	    end = cur;
24623 	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
24624 		end++;
24625 	    if (end == cur)
24626 		break;
24627 	    tmpValue = xmlStrndup(cur, end - cur);
24628 	    len++;
24629 
24630 	    if (valNeeded)
24631 		ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24632 		    tmpValue, &curVal, fireErrors, 0, 1);
24633 	    else
24634 		ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24635 		    tmpValue, NULL, fireErrors, 0, 1);
24636 	    FREE_AND_NULL(tmpValue);
24637 	    if (curVal != NULL) {
24638 		/*
24639 		* Add to list of computed values.
24640 		*/
24641 		if (val == NULL)
24642 		    val = curVal;
24643 		else
24644 		    xmlSchemaValueAppend(prevVal, curVal);
24645 		prevVal = curVal;
24646 		curVal = NULL;
24647 	    }
24648 	    if (ret != 0) {
24649 		if (ret < 0) {
24650 		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24651 			"validating an item of list simple type");
24652 		    goto internal_error;
24653 		}
24654 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24655 		break;
24656 	    }
24657 	    cur = end;
24658 	} while (*cur != 0);
24659 	FREE_AND_NULL(tmpValue);
24660 	if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24661 	    /*
24662 	    * Apply facets (pattern, enumeration).
24663 	    */
24664 	    ret = xmlSchemaValidateFacets(actxt, node, type,
24665 		XML_SCHEMAS_UNKNOWN, value, val,
24666 		len, fireErrors);
24667 	    if (ret != 0) {
24668 		if (ret < 0) {
24669 		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24670 			"validating facets of list simple type");
24671 		    goto internal_error;
24672 		}
24673 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24674 	    }
24675 	}
24676 	if (fireErrors && (ret > 0)) {
24677 	    /*
24678 	    * Report the normalized value.
24679 	    */
24680 	    normalize = 1;
24681 	    NORMALIZE(type);
24682 	    xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24683 	}
24684     } else if (WXS_IS_UNION(type)) {
24685 	xmlSchemaTypeLinkPtr memberLink;
24686 	/*
24687 	* TODO: For all datatypes �derived� by �union�  whiteSpace does
24688 	* not apply directly; however, the normalization behavior of �union�
24689 	* types is controlled by the value of whiteSpace on that one of the
24690 	* �memberTypes� against which the �union� is successfully validated.
24691 	*
24692 	* This means that the value is normalized by the first validating
24693 	* member type, then the facets of the union type are applied. This
24694 	* needs changing of the value!
24695 	*/
24696 
24697 	/*
24698 	* 1.2.3 if {variety} is �union� then the string must �match� a
24699 	* literal in the �lexical space� of at least one member of
24700 	* {member type definitions}
24701 	*/
24702 	memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
24703 	if (memberLink == NULL) {
24704 	    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24705 		"union simple type has no member types");
24706 	    goto internal_error;
24707 	}
24708 	/*
24709 	* Always normalize union type values, since we currently
24710 	* cannot store the whitespace information with the value
24711 	* itself; otherwise a later value-comparison would be
24712 	* not possible.
24713 	*/
24714 	while (memberLink != NULL) {
24715 	    if (valNeeded)
24716 		ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24717 		    memberLink->type, value, &val, 0, 1, 0);
24718 	    else
24719 		ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24720 		    memberLink->type, value, NULL, 0, 1, 0);
24721 	    if (ret <= 0)
24722 		break;
24723 	    memberLink = memberLink->next;
24724 	}
24725 	if (ret != 0) {
24726 	    if (ret < 0) {
24727 		AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24728 		    "validating members of union simple type");
24729 		goto internal_error;
24730 	    }
24731 	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24732 	}
24733 	/*
24734 	* Apply facets (pattern, enumeration).
24735 	*/
24736 	if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24737 	    /*
24738 	    * The normalization behavior of �union� types is controlled by
24739 	    * the value of whiteSpace on that one of the �memberTypes�
24740 	    * against which the �union� is successfully validated.
24741 	    */
24742 	    NORMALIZE(memberLink->type);
24743 	    ret = xmlSchemaValidateFacets(actxt, node, type,
24744 		XML_SCHEMAS_UNKNOWN, value, val,
24745 		0, fireErrors);
24746 	    if (ret != 0) {
24747 		if (ret < 0) {
24748 		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24749 			"validating facets of union simple type");
24750 		    goto internal_error;
24751 		}
24752 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24753 	    }
24754 	}
24755 	if (fireErrors && (ret > 0))
24756 	    xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24757     }
24758 
24759     if (normValue != NULL)
24760 	xmlFree(normValue);
24761     if (ret == 0) {
24762 	if (retVal != NULL)
24763 	    *retVal = val;
24764 	else if (val != NULL)
24765 	    xmlSchemaFreeValue(val);
24766     } else if (val != NULL)
24767 	xmlSchemaFreeValue(val);
24768     return (ret);
24769 internal_error:
24770     if (normValue != NULL)
24771 	xmlFree(normValue);
24772     if (val != NULL)
24773 	xmlSchemaFreeValue(val);
24774     return (-1);
24775 }
24776 
24777 static int
xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,const xmlChar * value,const xmlChar ** nsName,const xmlChar ** localName)24778 xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
24779 			   const xmlChar *value,
24780 			   const xmlChar **nsName,
24781 			   const xmlChar **localName)
24782 {
24783     int ret = 0;
24784 
24785     if ((nsName == NULL) || (localName == NULL))
24786 	return (-1);
24787     *nsName = NULL;
24788     *localName = NULL;
24789 
24790     ret = xmlValidateQName(value, 1);
24791     if (ret == -1)
24792 	return (-1);
24793     if (ret > 0) {
24794 	xmlSchemaSimpleTypeErr(ACTXT_CAST vctxt,
24795 	    XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24796 	    value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
24797 	return (1);
24798     }
24799     {
24800 	xmlChar *local = NULL;
24801 	xmlChar *prefix;
24802 
24803 	/*
24804 	* NOTE: xmlSplitQName2 will return a duplicated
24805 	* string.
24806 	*/
24807 	local = xmlSplitQName2(value, &prefix);
24808 	if (local == NULL)
24809 	    *localName = xmlDictLookup(vctxt->dict, value, -1);
24810 	else {
24811 	    *localName = xmlDictLookup(vctxt->dict, local, -1);
24812 	    xmlFree(local);
24813 	}
24814 
24815 	*nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24816 
24817 	if (prefix != NULL) {
24818 	    xmlFree(prefix);
24819 	    /*
24820 	    * A namespace must be found if the prefix is NOT NULL.
24821 	    */
24822 	    if (*nsName == NULL) {
24823 		xmlSchemaCustomErr(ACTXT_CAST vctxt,
24824 		    XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24825 		    WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24826 		    "The QName value '%s' has no "
24827 		    "corresponding namespace declaration in scope",
24828 		    value, NULL);
24829 		return (2);
24830 	    }
24831 	}
24832     }
24833     return (0);
24834 }
24835 
24836 static int
xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,xmlSchemaAttrInfoPtr iattr,xmlSchemaTypePtr * localType,xmlSchemaElementPtr elemDecl)24837 xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
24838 			xmlSchemaAttrInfoPtr iattr,
24839 			xmlSchemaTypePtr *localType,
24840 			xmlSchemaElementPtr elemDecl)
24841 {
24842     int ret = 0;
24843     /*
24844     * cvc-elt (3.3.4) : (4)
24845     * AND
24846     * Schema-Validity Assessment (Element) (cvc-assess-elt)
24847     *   (1.2.1.2.1) - (1.2.1.2.4)
24848     * Handle 'xsi:type'.
24849     */
24850     if (localType == NULL)
24851 	return (-1);
24852     *localType = NULL;
24853     if (iattr == NULL)
24854 	return (0);
24855     else {
24856 	const xmlChar *nsName = NULL, *local = NULL;
24857 	/*
24858 	* TODO: We should report a *warning* that the type was overriden
24859 	* by the instance.
24860 	*/
24861 	ACTIVATE_ATTRIBUTE(iattr);
24862 	/*
24863 	* (cvc-elt) (3.3.4) : (4.1)
24864 	* (cvc-assess-elt) (1.2.1.2.2)
24865 	*/
24866 	ret = xmlSchemaVExpandQName(vctxt, iattr->value,
24867 	    &nsName, &local);
24868 	if (ret != 0) {
24869 	    if (ret < 0) {
24870 		VERROR_INT("xmlSchemaValidateElementByDeclaration",
24871 		    "calling xmlSchemaQNameExpand() to validate the "
24872 		    "attribute 'xsi:type'");
24873 		goto internal_error;
24874 	    }
24875 	    goto exit;
24876 	}
24877 	/*
24878 	* (cvc-elt) (3.3.4) : (4.2)
24879 	* (cvc-assess-elt) (1.2.1.2.3)
24880 	*/
24881 	*localType = xmlSchemaGetType(vctxt->schema, local, nsName);
24882 	if (*localType == NULL) {
24883 	    xmlChar *str = NULL;
24884 
24885 	    xmlSchemaCustomErr(ACTXT_CAST vctxt,
24886 		XML_SCHEMAV_CVC_ELT_4_2, NULL,
24887 		WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24888 		"The QName value '%s' of the xsi:type attribute does not "
24889 		"resolve to a type definition",
24890 		xmlSchemaFormatQName(&str, nsName, local), NULL);
24891 	    FREE_AND_NULL(str);
24892 	    ret = vctxt->err;
24893 	    goto exit;
24894 	}
24895 	if (elemDecl != NULL) {
24896 	    int set = 0;
24897 
24898 	    /*
24899 	    * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
24900 	    * "The �local type definition� must be validly
24901 	    * derived from the {type definition} given the union of
24902 	    * the {disallowed substitutions} and the {type definition}'s
24903 	    * {prohibited substitutions}, as defined in
24904 	    * Type Derivation OK (Complex) (�3.4.6)
24905 	    * (if it is a complex type definition),
24906 	    * or given {disallowed substitutions} as defined in Type
24907 	    * Derivation OK (Simple) (�3.14.6) (if it is a simple type
24908 	    * definition)."
24909 	    *
24910 	    * {disallowed substitutions}: the "block" on the element decl.
24911 	    * {prohibited substitutions}: the "block" on the type def.
24912 	    */
24913 	    /*
24914 	    * OPTIMIZE TODO: We could map types already evaluated
24915 	    * to be validly derived from other types to avoid checking
24916 	    * this over and over for the same types.
24917 	    */
24918 	    if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
24919 		(elemDecl->subtypes->flags &
24920 		    XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
24921 		set |= SUBSET_EXTENSION;
24922 
24923 	    if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
24924 		(elemDecl->subtypes->flags &
24925 		    XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
24926 		set |= SUBSET_RESTRICTION;
24927 
24928 	    /*
24929 	    * REMOVED and CHANGED since this produced a parser context
24930 	    * which adds to the string dict of the schema. So this would
24931 	    * change the schema and we don't want this. We don't need
24932 	    * the parser context anymore.
24933 	    *
24934 	    * if ((vctxt->pctxt == NULL) &&
24935 	    *	(xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
24936 	    *	    return (-1);
24937 	    */
24938 
24939 	    if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST vctxt, *localType,
24940 		elemDecl->subtypes, set) != 0) {
24941 		xmlChar *str = NULL;
24942 
24943 		xmlSchemaCustomErr(ACTXT_CAST vctxt,
24944 		    XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
24945 		    "The type definition '%s', specified by xsi:type, is "
24946 		    "blocked or not validly derived from the type definition "
24947 		    "of the element declaration",
24948 		    xmlSchemaFormatQName(&str,
24949 			(*localType)->targetNamespace,
24950 			(*localType)->name),
24951 		    NULL);
24952 		FREE_AND_NULL(str);
24953 		ret = vctxt->err;
24954 		*localType = NULL;
24955 	    }
24956 	}
24957     }
24958 exit:
24959     ACTIVATE_ELEM;
24960     return (ret);
24961 internal_error:
24962     ACTIVATE_ELEM;
24963     return (-1);
24964 }
24965 
24966 static int
xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)24967 xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
24968 {
24969     xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
24970     xmlSchemaTypePtr actualType;
24971 
24972     /*
24973     * cvc-elt (3.3.4) : 1
24974     */
24975     if (elemDecl == NULL) {
24976 	VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
24977 	    "No matching declaration available");
24978         return (vctxt->err);
24979     }
24980     actualType = WXS_ELEM_TYPEDEF(elemDecl);
24981     /*
24982     * cvc-elt (3.3.4) : 2
24983     */
24984     if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
24985 	VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
24986 	    "The element declaration is abstract");
24987         return (vctxt->err);
24988     }
24989     if (actualType == NULL) {
24990     	VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
24991     	    "The type definition is absent");
24992     	return (XML_SCHEMAV_CVC_TYPE_1);
24993     }
24994     if (vctxt->nbAttrInfos != 0) {
24995 	int ret;
24996 	xmlSchemaAttrInfoPtr iattr;
24997 	/*
24998 	* cvc-elt (3.3.4) : 3
24999 	* Handle 'xsi:nil'.
25000 	*/
25001 	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25002 	    XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
25003 	if (iattr) {
25004 	    ACTIVATE_ATTRIBUTE(iattr);
25005 	    /*
25006 	    * Validate the value.
25007 	    */
25008 	    ret = xmlSchemaVCheckCVCSimpleType(
25009 		ACTXT_CAST vctxt, NULL,
25010 		xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
25011 		iattr->value, &(iattr->val), 1, 0, 0);
25012 	    ACTIVATE_ELEM;
25013 	    if (ret < 0) {
25014 		VERROR_INT("xmlSchemaValidateElemDecl",
25015 		    "calling xmlSchemaVCheckCVCSimpleType() to "
25016 		    "validate the attribute 'xsi:nil'");
25017 		return (-1);
25018 	    }
25019 	    if (ret == 0) {
25020 		if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
25021 		    /*
25022 		    * cvc-elt (3.3.4) : 3.1
25023 		    */
25024 		    VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
25025 			"The element is not 'nillable'");
25026 		    /* Does not return an error on purpose. */
25027 		} else {
25028 		    if (xmlSchemaValueGetAsBoolean(iattr->val)) {
25029 			/*
25030 			* cvc-elt (3.3.4) : 3.2.2
25031 			*/
25032 			if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
25033 			    (elemDecl->value != NULL)) {
25034 			    VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
25035 				"The element cannot be 'nilled' because "
25036 				"there is a fixed value constraint defined "
25037 				"for it");
25038 			     /* Does not return an error on purpose. */
25039 			} else
25040 			    vctxt->inode->flags |=
25041 				XML_SCHEMA_ELEM_INFO_NILLED;
25042 		    }
25043 		}
25044 	    }
25045 	}
25046 	/*
25047 	* cvc-elt (3.3.4) : 4
25048 	* Handle 'xsi:type'.
25049 	*/
25050 	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25051 	    XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25052 	if (iattr) {
25053 	    xmlSchemaTypePtr localType = NULL;
25054 
25055 	    ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
25056 		elemDecl);
25057 	    if (ret != 0) {
25058 		if (ret == -1) {
25059 		    VERROR_INT("xmlSchemaValidateElemDecl",
25060 			"calling xmlSchemaProcessXSIType() to "
25061 			"process the attribute 'xsi:type'");
25062 		    return (-1);
25063 		}
25064 		/* Does not return an error on purpose. */
25065 	    }
25066 	    if (localType != NULL) {
25067 		vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
25068 		actualType = localType;
25069 	    }
25070 	}
25071     }
25072     /*
25073     * IDC: Register identity-constraint XPath matchers.
25074     */
25075     if ((elemDecl->idcs != NULL) &&
25076 	(xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
25077 	    return (-1);
25078     /*
25079     * No actual type definition.
25080     */
25081     if (actualType == NULL) {
25082     	VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
25083     	    "The type definition is absent");
25084     	return (XML_SCHEMAV_CVC_TYPE_1);
25085     }
25086     /*
25087     * Remember the actual type definition.
25088     */
25089     vctxt->inode->typeDef = actualType;
25090 
25091     return (0);
25092 }
25093 
25094 static int
xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)25095 xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
25096 {
25097     xmlSchemaAttrInfoPtr iattr;
25098     int ret = 0, i;
25099 
25100     /*
25101     * SPEC cvc-type (3.1.1)
25102     * "The attributes of must be empty, excepting those whose namespace
25103     * name is identical to http://www.w3.org/2001/XMLSchema-instance and
25104     * whose local name is one of type, nil, schemaLocation or
25105     * noNamespaceSchemaLocation."
25106     */
25107     if (vctxt->nbAttrInfos == 0)
25108 	return (0);
25109     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25110 	iattr = vctxt->attrInfos[i];
25111 	if (! iattr->metaType) {
25112 	    ACTIVATE_ATTRIBUTE(iattr)
25113 	    xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25114 		XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
25115 	    ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
25116         }
25117     }
25118     ACTIVATE_ELEM
25119     return (ret);
25120 }
25121 
25122 /*
25123 * Cleanup currently used attribute infos.
25124 */
25125 static void
xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)25126 xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
25127 {
25128     int i;
25129     xmlSchemaAttrInfoPtr attr;
25130 
25131     if (vctxt->nbAttrInfos == 0)
25132 	return;
25133     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25134 	attr = vctxt->attrInfos[i];
25135 	if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
25136 	    if (attr->localName != NULL)
25137 		xmlFree((xmlChar *) attr->localName);
25138 	    if (attr->nsName != NULL)
25139 		xmlFree((xmlChar *) attr->nsName);
25140 	}
25141 	if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
25142 	    if (attr->value != NULL)
25143 		xmlFree((xmlChar *) attr->value);
25144 	}
25145 	if (attr->val != NULL) {
25146 	    xmlSchemaFreeValue(attr->val);
25147 	    attr->val = NULL;
25148 	}
25149 	memset(attr, 0, sizeof(xmlSchemaAttrInfo));
25150     }
25151     vctxt->nbAttrInfos = 0;
25152 }
25153 
25154 /*
25155 * 3.4.4 Complex Type Definition Validation Rules
25156 *   Element Locally Valid (Complex Type) (cvc-complex-type)
25157 * 3.2.4 Attribute Declaration Validation Rules
25158 *   Validation Rule: Attribute Locally Valid (cvc-attribute)
25159 *   Attribute Locally Valid (Use) (cvc-au)
25160 *
25161 * Only "assessed" attribute information items will be visible to
25162 * IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
25163 */
25164 static int
xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)25165 xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
25166 {
25167     xmlSchemaTypePtr type = vctxt->inode->typeDef;
25168     xmlSchemaItemListPtr attrUseList;
25169     xmlSchemaAttributeUsePtr attrUse = NULL;
25170     xmlSchemaAttributePtr attrDecl = NULL;
25171     xmlSchemaAttrInfoPtr iattr, tmpiattr;
25172     int i, j, found, nbAttrs, nbUses;
25173     int xpathRes = 0, res, wildIDs = 0, fixed;
25174     xmlNodePtr defAttrOwnerElem = NULL;
25175 
25176     /*
25177     * SPEC (cvc-attribute)
25178     * (1) "The declaration must not be �absent� (see Missing
25179     * Sub-components (�5.3) for how this can fail to be
25180     * the case)."
25181     * (2) "Its {type definition} must not be absent."
25182     *
25183     * NOTE (1) + (2): This is not handled here, since we currently do not
25184     * allow validation against schemas which have missing sub-components.
25185     *
25186     * SPEC (cvc-complex-type)
25187     * (3) "For each attribute information item in the element information
25188     * item's [attributes] excepting those whose [namespace name] is
25189     * identical to http://www.w3.org/2001/XMLSchema-instance and whose
25190     * [local name] is one of type, nil, schemaLocation or
25191     * noNamespaceSchemaLocation, the appropriate case among the following
25192     * must be true:
25193     *
25194     */
25195     attrUseList = (xmlSchemaItemListPtr) type->attrUses;
25196     /*
25197     * @nbAttrs is the number of attributes present in the instance.
25198     */
25199     nbAttrs = vctxt->nbAttrInfos;
25200     if (attrUseList != NULL)
25201 	nbUses = attrUseList->nbItems;
25202     else
25203 	nbUses = 0;
25204     for (i = 0; i < nbUses; i++) {
25205         found = 0;
25206 	attrUse = attrUseList->items[i];
25207 	attrDecl = WXS_ATTRUSE_DECL(attrUse);
25208         for (j = 0; j < nbAttrs; j++) {
25209 	    iattr = vctxt->attrInfos[j];
25210 	    /*
25211 	    * SPEC (cvc-complex-type) (3)
25212 	    * Skip meta attributes.
25213 	    */
25214 	    if (iattr->metaType)
25215 		continue;
25216 	    if (iattr->localName[0] != attrDecl->name[0])
25217 		continue;
25218 	    if (!xmlStrEqual(iattr->localName, attrDecl->name))
25219 		continue;
25220 	    if (!xmlStrEqual(iattr->nsName, attrDecl->targetNamespace))
25221 		continue;
25222 	    found = 1;
25223 	    /*
25224 	    * SPEC (cvc-complex-type)
25225 	    * (3.1) "If there is among the {attribute uses} an attribute
25226 	    * use with an {attribute declaration} whose {name} matches
25227 	    * the attribute information item's [local name] and whose
25228 	    * {target namespace} is identical to the attribute information
25229 	    * item's [namespace name] (where an �absent� {target namespace}
25230 	    * is taken to be identical to a [namespace name] with no value),
25231 	    * then the attribute information must be �valid� with respect
25232 	    * to that attribute use as per Attribute Locally Valid (Use)
25233 	    * (�3.5.4). In this case the {attribute declaration} of that
25234 	    * attribute use is the �context-determined declaration� for the
25235 	    * attribute information item with respect to Schema-Validity
25236 	    * Assessment (Attribute) (�3.2.4) and
25237 	    * Assessment Outcome (Attribute) (�3.2.5).
25238 	    */
25239 	    iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25240 	    iattr->use = attrUse;
25241 	    /*
25242 	    * Context-determined declaration.
25243 	    */
25244 	    iattr->decl = attrDecl;
25245 	    iattr->typeDef = attrDecl->subtypes;
25246 	    break;
25247 	}
25248 
25249 	if (found)
25250 	    continue;
25251 
25252 	if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
25253 	    /*
25254 	    * Handle non-existent, required attributes.
25255 	    *
25256 	    * SPEC (cvc-complex-type)
25257 	    * (4) "The {attribute declaration} of each attribute use in
25258 	    * the {attribute uses} whose {required} is true matches one
25259 	    * of the attribute information items in the element information
25260 	    * item's [attributes] as per clause 3.1 above."
25261 	    */
25262 	    tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25263 	    if (tmpiattr == NULL) {
25264 		VERROR_INT(
25265 		    "xmlSchemaVAttributesComplex",
25266 		    "calling xmlSchemaGetFreshAttrInfo()");
25267 		return (-1);
25268 	    }
25269 	    tmpiattr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
25270 	    tmpiattr->use = attrUse;
25271 	    tmpiattr->decl = attrDecl;
25272 	} else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
25273 	    ((attrUse->defValue != NULL) ||
25274 	     (attrDecl->defValue != NULL))) {
25275 	    /*
25276 	    * Handle non-existent, optional, default/fixed attributes.
25277 	    */
25278 	    tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25279 	    if (tmpiattr == NULL) {
25280 		VERROR_INT(
25281 		    "xmlSchemaVAttributesComplex",
25282 		    "calling xmlSchemaGetFreshAttrInfo()");
25283 		return (-1);
25284 	    }
25285 	    tmpiattr->state = XML_SCHEMAS_ATTR_DEFAULT;
25286 	    tmpiattr->use = attrUse;
25287 	    tmpiattr->decl = attrDecl;
25288 	    tmpiattr->typeDef = attrDecl->subtypes;
25289 	    tmpiattr->localName = attrDecl->name;
25290 	    tmpiattr->nsName = attrDecl->targetNamespace;
25291 	}
25292     }
25293 
25294     if (vctxt->nbAttrInfos == 0)
25295 	return (0);
25296     /*
25297     * Validate against the wildcard.
25298     */
25299     if (type->attributeWildcard != NULL) {
25300 	/*
25301 	* SPEC (cvc-complex-type)
25302 	* (3.2.1) "There must be an {attribute wildcard}."
25303 	*/
25304 	for (i = 0; i < nbAttrs; i++) {
25305 	    iattr = vctxt->attrInfos[i];
25306 	    /*
25307 	    * SPEC (cvc-complex-type) (3)
25308 	    * Skip meta attributes.
25309 	    */
25310 	    if (iattr->state != XML_SCHEMAS_ATTR_UNKNOWN)
25311 		continue;
25312 	    /*
25313 	    * SPEC (cvc-complex-type)
25314 	    * (3.2.2) "The attribute information item must be �valid� with
25315 	    * respect to it as defined in Item Valid (Wildcard) (�3.10.4)."
25316 	    *
25317 	    * SPEC Item Valid (Wildcard) (cvc-wildcard)
25318 	    * "... its [namespace name] must be �valid� with respect to
25319 	    * the wildcard constraint, as defined in Wildcard allows
25320 	    * Namespace Name (�3.10.4)."
25321 	    */
25322 	    if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
25323 		    iattr->nsName) == 0) {
25324 		/*
25325 		* Handle processContents.
25326 		*
25327 		* SPEC (cvc-wildcard):
25328 		* processContents | context-determined declaration:
25329 		* "strict"          "mustFind"
25330 		* "lax"             "none"
25331 		* "skip"            "skip"
25332 		*/
25333 		if (type->attributeWildcard->processContents ==
25334 		    XML_SCHEMAS_ANY_SKIP) {
25335 		     /*
25336 		    * context-determined declaration = "skip"
25337 		    *
25338 		    * SPEC PSVI Assessment Outcome (Attribute)
25339 		    * [validity] = "notKnown"
25340 		    * [validation attempted] = "none"
25341 		    */
25342 		    iattr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
25343 		    continue;
25344 		}
25345 		/*
25346 		* Find an attribute declaration.
25347 		*/
25348 		iattr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
25349 		    iattr->localName, iattr->nsName);
25350 		if (iattr->decl != NULL) {
25351 		    iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25352 		    /*
25353 		    * SPEC (cvc-complex-type)
25354 		    * (5) "Let [Definition:]  the wild IDs be the set of
25355 		    * all attribute information item to which clause 3.2
25356 		    * applied and whose �validation� resulted in a
25357 		    * �context-determined declaration� of mustFind or no
25358 		    * �context-determined declaration� at all, and whose
25359 		    * [local name] and [namespace name] resolve (as
25360 		    * defined by QName resolution (Instance) (�3.15.4)) to
25361 		    * an attribute declaration whose {type definition} is
25362 		    * or is derived from ID. Then all of the following
25363 		    * must be true:"
25364 		    */
25365 		    iattr->typeDef = WXS_ATTR_TYPEDEF(iattr->decl);
25366 		    if (xmlSchemaIsDerivedFromBuiltInType(
25367 			iattr->typeDef, XML_SCHEMAS_ID)) {
25368 			/*
25369 			* SPEC (5.1) "There must be no more than one
25370 			* item in �wild IDs�."
25371 			*/
25372 			if (wildIDs != 0) {
25373 			    /* VAL TODO */
25374 			    iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
25375 			    TODO
25376 			    continue;
25377 			}
25378 			wildIDs++;
25379 			/*
25380 			* SPEC (cvc-complex-type)
25381 			* (5.2) "If �wild IDs� is non-empty, there must not
25382 			* be any attribute uses among the {attribute uses}
25383 			* whose {attribute declaration}'s {type definition}
25384 			* is or is derived from ID."
25385 			*/
25386                         if (attrUseList != NULL) {
25387                             for (j = 0; j < attrUseList->nbItems; j++) {
25388                                 if (xmlSchemaIsDerivedFromBuiltInType(
25389                                     WXS_ATTRUSE_TYPEDEF(attrUseList->items[j]),
25390                                     XML_SCHEMAS_ID)) {
25391                                     /* URGENT VAL TODO: implement */
25392                             iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
25393                                     TODO
25394                                     break;
25395                                 }
25396                             }
25397                         }
25398 		    }
25399 		} else if (type->attributeWildcard->processContents ==
25400 		    XML_SCHEMAS_ANY_LAX) {
25401 		    iattr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
25402 		    /*
25403 		    * SPEC PSVI Assessment Outcome (Attribute)
25404 		    * [validity] = "notKnown"
25405 		    * [validation attempted] = "none"
25406 		    */
25407 		} else {
25408 		    iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
25409 		}
25410 	    }
25411 	}
25412     }
25413 
25414     if (vctxt->nbAttrInfos == 0)
25415 	return (0);
25416 
25417     /*
25418     * Get the owner element; needed for creation of default attributes.
25419     * This fixes bug #341337, reported by David Grohmann.
25420     */
25421     if (vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
25422 	xmlSchemaNodeInfoPtr ielem = vctxt->elemInfos[vctxt->depth];
25423 	if (ielem && ielem->node && ielem->node->doc)
25424 	    defAttrOwnerElem = ielem->node;
25425     }
25426     /*
25427     * Validate values, create default attributes, evaluate IDCs.
25428     */
25429     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25430 	iattr = vctxt->attrInfos[i];
25431 	/*
25432 	* VAL TODO: Note that we won't try to resolve IDCs to
25433 	* "lax" and "skip" validated attributes. Check what to
25434 	* do in this case.
25435 	*/
25436 	if ((iattr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
25437 	    (iattr->state != XML_SCHEMAS_ATTR_DEFAULT))
25438 	    continue;
25439 	/*
25440 	* VAL TODO: What to do if the type definition is missing?
25441 	*/
25442 	if (iattr->typeDef == NULL) {
25443 	    iattr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
25444 	    continue;
25445 	}
25446 
25447 	ACTIVATE_ATTRIBUTE(iattr);
25448 	fixed = 0;
25449 	xpathRes = 0;
25450 
25451 	if (vctxt->xpathStates != NULL) {
25452 	    /*
25453 	    * Evaluate IDCs.
25454 	    */
25455 	    xpathRes = xmlSchemaXPathEvaluate(vctxt,
25456 		XML_ATTRIBUTE_NODE);
25457 	    if (xpathRes == -1) {
25458 		VERROR_INT("xmlSchemaVAttributesComplex",
25459 		    "calling xmlSchemaXPathEvaluate()");
25460 		goto internal_error;
25461 	    }
25462 	}
25463 
25464 	if (iattr->state == XML_SCHEMAS_ATTR_DEFAULT) {
25465 	    /*
25466 	    * Default/fixed attributes.
25467 	    * We need the value only if we need to resolve IDCs or
25468 	    * will create default attributes.
25469 	    */
25470 	    if ((xpathRes) || (defAttrOwnerElem)) {
25471 		if (iattr->use->defValue != NULL) {
25472 		    iattr->value = (xmlChar *) iattr->use->defValue;
25473 		    iattr->val = iattr->use->defVal;
25474 		} else {
25475 		    iattr->value = (xmlChar *) iattr->decl->defValue;
25476 		    iattr->val = iattr->decl->defVal;
25477 		}
25478 		/*
25479 		* IDCs will consume the precomputed default value,
25480 		* so we need to clone it.
25481 		*/
25482 		if (iattr->val == NULL) {
25483 		    VERROR_INT("xmlSchemaVAttributesComplex",
25484 			"default/fixed value on an attribute use was "
25485 			"not precomputed");
25486 		    goto internal_error;
25487 		}
25488 		iattr->val = xmlSchemaCopyValue(iattr->val);
25489 		if (iattr->val == NULL) {
25490 		    VERROR_INT("xmlSchemaVAttributesComplex",
25491 			"calling xmlSchemaCopyValue()");
25492 		    goto internal_error;
25493 		}
25494 	    }
25495 	    /*
25496 	    * PSVI: Add the default attribute to the current element.
25497 	    * VAL TODO: Should we use the *normalized* value? This currently
25498 	    *   uses the *initial* value.
25499 	    */
25500 
25501 	    if (defAttrOwnerElem) {
25502 		xmlChar *normValue;
25503 		const xmlChar *value;
25504 
25505 		value = iattr->value;
25506 		/*
25507 		* Normalize the value.
25508 		*/
25509 		normValue = xmlSchemaNormalizeValue(iattr->typeDef,
25510 		    iattr->value);
25511 		if (normValue != NULL)
25512 		    value = BAD_CAST normValue;
25513 
25514 		if (iattr->nsName == NULL) {
25515 		    if (xmlNewProp(defAttrOwnerElem,
25516 			iattr->localName, value) == NULL) {
25517 			VERROR_INT("xmlSchemaVAttributesComplex",
25518 			    "callling xmlNewProp()");
25519 			if (normValue != NULL)
25520 			    xmlFree(normValue);
25521 			goto internal_error;
25522 		    }
25523 		} else {
25524 		    xmlNsPtr ns;
25525 
25526 		    ns = xmlSearchNsByHref(defAttrOwnerElem->doc,
25527 			defAttrOwnerElem, iattr->nsName);
25528 		    if (ns == NULL) {
25529 			xmlChar prefix[12];
25530 			int counter = 0;
25531 
25532 			/*
25533 			* Create a namespace declaration on the validation
25534 			* root node if no namespace declaration is in scope.
25535 			*/
25536 			do {
25537 			    snprintf((char *) prefix, 12, "p%d", counter++);
25538 			    ns = xmlSearchNs(defAttrOwnerElem->doc,
25539 				defAttrOwnerElem, BAD_CAST prefix);
25540 			    if (counter > 1000) {
25541 				VERROR_INT(
25542 				    "xmlSchemaVAttributesComplex",
25543 				    "could not compute a ns prefix for a "
25544 				    "default/fixed attribute");
25545 				if (normValue != NULL)
25546 				    xmlFree(normValue);
25547 				goto internal_error;
25548 			    }
25549 			} while (ns != NULL);
25550 			ns = xmlNewNs(vctxt->validationRoot,
25551 			    iattr->nsName, BAD_CAST prefix);
25552 		    }
25553 		    /*
25554 		    * TODO:
25555 		    * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0406.html
25556 		    * If we have QNames: do we need to ensure there's a
25557 		    * prefix defined for the QName?
25558 		    */
25559 		    xmlNewNsProp(defAttrOwnerElem, ns, iattr->localName, value);
25560 		}
25561 		if (normValue != NULL)
25562 		    xmlFree(normValue);
25563 	    }
25564 	    /*
25565 	    * Go directly to IDC evaluation.
25566 	    */
25567 	    goto eval_idcs;
25568 	}
25569 	/*
25570 	* Validate the value.
25571 	*/
25572 	if (vctxt->value != NULL) {
25573 	    /*
25574 	    * Free last computed value; just for safety reasons.
25575 	    */
25576 	    xmlSchemaFreeValue(vctxt->value);
25577 	    vctxt->value = NULL;
25578 	}
25579 	/*
25580 	* Note that the attribute *use* can be unavailable, if
25581 	* the attribute was a wild attribute.
25582 	*/
25583 	if ((iattr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
25584 	    ((iattr->use != NULL) &&
25585 	     (iattr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
25586 	    fixed = 1;
25587 	else
25588 	    fixed = 0;
25589 	/*
25590 	* SPEC (cvc-attribute)
25591 	* (3) "The item's �normalized value� must be locally �valid�
25592 	* with respect to that {type definition} as per
25593 	* String Valid (�3.14.4)."
25594 	*
25595 	* VAL TODO: Do we already have the
25596 	* "normalized attribute value" here?
25597 	*/
25598 	if (xpathRes || fixed) {
25599 	    iattr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
25600 	    /*
25601 	    * Request a computed value.
25602 	    */
25603 	    res = xmlSchemaVCheckCVCSimpleType(
25604 		ACTXT_CAST vctxt,
25605 		iattr->node, iattr->typeDef, iattr->value, &(iattr->val),
25606 		1, 1, 0);
25607 	} else {
25608 	    res = xmlSchemaVCheckCVCSimpleType(
25609 		ACTXT_CAST vctxt,
25610 		iattr->node, iattr->typeDef, iattr->value, NULL,
25611 		1, 0, 0);
25612 	}
25613 
25614 	if (res != 0) {
25615 	    if (res == -1) {
25616 		VERROR_INT("xmlSchemaVAttributesComplex",
25617 		    "calling xmlSchemaStreamValidateSimpleTypeValue()");
25618 		goto internal_error;
25619 	    }
25620 	    iattr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
25621 	    /*
25622 	    * SPEC PSVI Assessment Outcome (Attribute)
25623 	    * [validity] = "invalid"
25624 	    */
25625 	    goto eval_idcs;
25626 	}
25627 
25628 	if (fixed) {
25629 	    /*
25630 	    * SPEC Attribute Locally Valid (Use) (cvc-au)
25631 	    * "For an attribute information item to be�valid�
25632 	    * with respect to an attribute use its *normalized*
25633 	    * value� must match the *canonical* lexical
25634 	    * representation of the attribute use's {value
25635 	    * constraint}value, if it is present and fixed."
25636 	    *
25637 	    * VAL TODO: The requirement for the *canonical* value
25638 	    * will be removed in XML Schema 1.1.
25639 	    */
25640 	    /*
25641 	    * SPEC Attribute Locally Valid (cvc-attribute)
25642 	    * (4) "The item's *actual* value� must match the *value* of
25643 	    * the {value constraint}, if it is present and fixed."
25644 	    */
25645 	    if (iattr->val == NULL) {
25646 		/* VAL TODO: A value was not precomputed. */
25647 		TODO
25648 		goto eval_idcs;
25649 	    }
25650 	    if ((iattr->use != NULL) &&
25651 		(iattr->use->defValue != NULL)) {
25652 		if (iattr->use->defVal == NULL) {
25653 		    /* VAL TODO: A default value was not precomputed. */
25654 		    TODO
25655 		    goto eval_idcs;
25656 		}
25657 		iattr->vcValue = iattr->use->defValue;
25658 		/*
25659 		if (xmlSchemaCompareValuesWhtsp(attr->val,
25660 		    (xmlSchemaWhitespaceValueType) ws,
25661 		    attr->use->defVal,
25662 		    (xmlSchemaWhitespaceValueType) ws) != 0) {
25663 		*/
25664 		if (! xmlSchemaAreValuesEqual(iattr->val, iattr->use->defVal))
25665 		    iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25666 	    } else {
25667 		if (iattr->decl->defVal == NULL) {
25668 		    /* VAL TODO: A default value was not precomputed. */
25669 		    TODO
25670 		    goto eval_idcs;
25671 		}
25672 		iattr->vcValue = iattr->decl->defValue;
25673 		/*
25674 		if (xmlSchemaCompareValuesWhtsp(attr->val,
25675 		    (xmlSchemaWhitespaceValueType) ws,
25676 		    attrDecl->defVal,
25677 		    (xmlSchemaWhitespaceValueType) ws) != 0) {
25678 		*/
25679 		if (! xmlSchemaAreValuesEqual(iattr->val, iattr->decl->defVal))
25680 		    iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25681 	    }
25682 	    /*
25683 	    * [validity] = "valid"
25684 	    */
25685 	}
25686 eval_idcs:
25687 	/*
25688 	* Evaluate IDCs.
25689 	*/
25690 	if (xpathRes) {
25691 	    if (xmlSchemaXPathProcessHistory(vctxt,
25692 		vctxt->depth +1) == -1) {
25693 		VERROR_INT("xmlSchemaVAttributesComplex",
25694 		    "calling xmlSchemaXPathEvaluate()");
25695 		goto internal_error;
25696 	    }
25697 	} else if (vctxt->xpathStates != NULL)
25698 	    xmlSchemaXPathPop(vctxt);
25699     }
25700 
25701     /*
25702     * Report errors.
25703     */
25704     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25705 	iattr = vctxt->attrInfos[i];
25706 	if ((iattr->state == XML_SCHEMAS_ATTR_META) ||
25707 	    (iattr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
25708 	    (iattr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
25709 	    (iattr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
25710 	    continue;
25711 	ACTIVATE_ATTRIBUTE(iattr);
25712 	switch (iattr->state) {
25713 	    case XML_SCHEMAS_ATTR_ERR_MISSING: {
25714 		    xmlChar *str = NULL;
25715 		    ACTIVATE_ELEM;
25716 		    xmlSchemaCustomErr(ACTXT_CAST vctxt,
25717 			XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
25718 			"The attribute '%s' is required but missing",
25719 			xmlSchemaFormatQName(&str,
25720 			    iattr->decl->targetNamespace,
25721 			    iattr->decl->name),
25722 			NULL);
25723 		    FREE_AND_NULL(str)
25724 		    break;
25725 		}
25726 	    case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
25727 		VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
25728 		    "The type definition is absent");
25729 		break;
25730 	    case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
25731 		xmlSchemaCustomErr(ACTXT_CAST vctxt,
25732 		    XML_SCHEMAV_CVC_AU, NULL, NULL,
25733 		    "The value '%s' does not match the fixed "
25734 		    "value constraint '%s'",
25735 		    iattr->value, iattr->vcValue);
25736 		break;
25737 	    case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
25738 		VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
25739 		    "No matching global attribute declaration available, but "
25740 		    "demanded by the strict wildcard");
25741 		break;
25742 	    case XML_SCHEMAS_ATTR_UNKNOWN:
25743 		if (iattr->metaType)
25744 		    break;
25745 		/*
25746 		* MAYBE VAL TODO: One might report different error messages
25747 		* for the following errors.
25748 		*/
25749 		if (type->attributeWildcard == NULL) {
25750 		    xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25751 			XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, iattr, NULL);
25752 		} else {
25753 		    xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25754 			XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, iattr, NULL);
25755 		}
25756 		break;
25757 	    default:
25758 		break;
25759 	}
25760     }
25761 
25762     ACTIVATE_ELEM;
25763     return (0);
25764 internal_error:
25765     ACTIVATE_ELEM;
25766     return (-1);
25767 }
25768 
25769 static int
xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,int * skip)25770 xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
25771 			      int *skip)
25772 {
25773     xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
25774     /*
25775     * The namespace of the element was already identified to be
25776     * matching the wildcard.
25777     */
25778     if ((skip == NULL) || (wild == NULL) ||
25779 	(wild->type != XML_SCHEMA_TYPE_ANY)) {
25780 	VERROR_INT("xmlSchemaValidateElemWildcard",
25781 	    "bad arguments");
25782 	return (-1);
25783     }
25784     *skip = 0;
25785     if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
25786 	/*
25787 	* URGENT VAL TODO: Either we need to position the stream to the
25788 	* next sibling, or walk the whole subtree.
25789 	*/
25790 	*skip = 1;
25791 	return (0);
25792     }
25793     {
25794 	xmlSchemaElementPtr decl = NULL;
25795 
25796 	decl = xmlSchemaGetElem(vctxt->schema,
25797 	    vctxt->inode->localName, vctxt->inode->nsName);
25798 	if (decl != NULL) {
25799 	    vctxt->inode->decl = decl;
25800 	    return (0);
25801 	}
25802     }
25803     if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
25804 	/* VAL TODO: Change to proper error code. */
25805 	VERROR(XML_SCHEMAV_CVC_ELT_1, NULL, /* WXS_BASIC_CAST wild */
25806 	    "No matching global element declaration available, but "
25807 	    "demanded by the strict wildcard");
25808 	return (vctxt->err);
25809     }
25810     if (vctxt->nbAttrInfos != 0) {
25811 	xmlSchemaAttrInfoPtr iattr;
25812 	/*
25813 	* SPEC Validation Rule: Schema-Validity Assessment (Element)
25814 	* (1.2.1.2.1) - (1.2.1.2.3 )
25815 	*
25816 	* Use the xsi:type attribute for the type definition.
25817 	*/
25818 	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25819 	    XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25820 	if (iattr != NULL) {
25821 	    if (xmlSchemaProcessXSIType(vctxt, iattr,
25822 		&(vctxt->inode->typeDef), NULL) == -1) {
25823 		VERROR_INT("xmlSchemaValidateElemWildcard",
25824 		    "calling xmlSchemaProcessXSIType() to "
25825 		    "process the attribute 'xsi:nil'");
25826 		return (-1);
25827 	    }
25828 	    /*
25829 	    * Don't return an error on purpose.
25830 	    */
25831 	    return (0);
25832 	}
25833     }
25834     /*
25835     * SPEC Validation Rule: Schema-Validity Assessment (Element)
25836     *
25837     * Fallback to "anyType".
25838     */
25839     vctxt->inode->typeDef =
25840 	xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
25841     return (0);
25842 }
25843 
25844 /*
25845 * xmlSchemaCheckCOSValidDefault:
25846 *
25847 * This will be called if: not nilled, no content and a default/fixed
25848 * value is provided.
25849 */
25850 
25851 static int
xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,const xmlChar * value,xmlSchemaValPtr * val)25852 xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
25853 			      const xmlChar *value,
25854 			      xmlSchemaValPtr *val)
25855 {
25856     int ret = 0;
25857     xmlSchemaNodeInfoPtr inode = vctxt->inode;
25858 
25859     /*
25860     * cos-valid-default:
25861     * Schema Component Constraint: Element Default Valid (Immediate)
25862     * For a string to be a valid default with respect to a type
25863     * definition the appropriate case among the following must be true:
25864     */
25865     if WXS_IS_COMPLEX(inode->typeDef) {
25866 	/*
25867 	* Complex type.
25868 	*
25869 	* SPEC (2.1) "its {content type} must be a simple type definition
25870 	* or mixed."
25871 	* SPEC (2.2.2) "If the {content type} is mixed, then the {content
25872 	* type}'s particle must be �emptiable� as defined by
25873 	* Particle Emptiable (�3.9.6)."
25874 	*/
25875 	if ((! WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) &&
25876 	    ((! WXS_HAS_MIXED_CONTENT(inode->typeDef)) ||
25877 	     (! WXS_EMPTIABLE(inode->typeDef)))) {
25878 	    ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
25879 	    /* NOTE that this covers (2.2.2) as well. */
25880 	    VERROR(ret, NULL,
25881 		"For a string to be a valid default, the type definition "
25882 		"must be a simple type or a complex type with simple content "
25883 		"or mixed content and a particle emptiable");
25884 	    return(ret);
25885 	}
25886     }
25887     /*
25888     * 1 If the type definition is a simple type definition, then the string
25889     * must be �valid� with respect to that definition as defined by String
25890     * Valid (�3.14.4).
25891     *
25892     * AND
25893     *
25894     * 2.2.1 If the {content type} is a simple type definition, then the
25895     * string must be �valid� with respect to that simple type definition
25896     * as defined by String Valid (�3.14.4).
25897     */
25898     if (WXS_IS_SIMPLE(inode->typeDef)) {
25899 
25900 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
25901 	    NULL, inode->typeDef, value, val, 1, 1, 0);
25902 
25903     } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
25904 
25905 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
25906 	    NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
25907     }
25908     if (ret < 0) {
25909 	VERROR_INT("xmlSchemaCheckCOSValidDefault",
25910 	    "calling xmlSchemaVCheckCVCSimpleType()");
25911     }
25912     return (ret);
25913 }
25914 
25915 static void
xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,const xmlChar * name ATTRIBUTE_UNUSED,xmlSchemaElementPtr item,xmlSchemaNodeInfoPtr inode)25916 xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
25917 			       const xmlChar * name ATTRIBUTE_UNUSED,
25918 			       xmlSchemaElementPtr item,
25919 			       xmlSchemaNodeInfoPtr inode)
25920 {
25921     inode->decl = item;
25922 #ifdef DEBUG_CONTENT
25923     {
25924 	xmlChar *str = NULL;
25925 
25926 	if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
25927 	    xmlGenericError(xmlGenericErrorContext,
25928 		"AUTOMATON callback for '%s' [declaration]\n",
25929 		xmlSchemaFormatQName(&str,
25930 		inode->localName, inode->nsName));
25931 	} else {
25932 	    xmlGenericError(xmlGenericErrorContext,
25933 		    "AUTOMATON callback for '%s' [wildcard]\n",
25934 		    xmlSchemaFormatQName(&str,
25935 		    inode->localName, inode->nsName));
25936 
25937 	}
25938 	FREE_AND_NULL(str)
25939     }
25940 #endif
25941 }
25942 
25943 static int
xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)25944 xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
25945 {
25946     vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
25947     if (vctxt->inode == NULL) {
25948 	VERROR_INT("xmlSchemaValidatorPushElem",
25949 	    "calling xmlSchemaGetFreshElemInfo()");
25950 	return (-1);
25951     }
25952     vctxt->nbAttrInfos = 0;
25953     return (0);
25954 }
25955 
25956 static int
xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,xmlSchemaNodeInfoPtr inode,xmlSchemaTypePtr type,const xmlChar * value)25957 xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
25958 			     xmlSchemaNodeInfoPtr inode,
25959 			     xmlSchemaTypePtr type,
25960 			     const xmlChar *value)
25961 {
25962     if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
25963 	return (xmlSchemaVCheckCVCSimpleType(
25964 	    ACTXT_CAST vctxt, NULL,
25965 	    type, value, &(inode->val), 1, 1, 0));
25966     else
25967 	return (xmlSchemaVCheckCVCSimpleType(
25968 	    ACTXT_CAST vctxt, NULL,
25969 	    type, value, NULL, 1, 0, 0));
25970 }
25971 
25972 
25973 
25974 /*
25975 * Process END of element.
25976 */
25977 static int
xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)25978 xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
25979 {
25980     int ret = 0;
25981     xmlSchemaNodeInfoPtr inode = vctxt->inode;
25982 
25983     if (vctxt->nbAttrInfos != 0)
25984 	xmlSchemaClearAttrInfos(vctxt);
25985     if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
25986 	/*
25987 	* This element was not expected;
25988 	* we will not validate child elements of broken parents.
25989 	* Skip validation of all content of the parent.
25990 	*/
25991 	vctxt->skipDepth = vctxt->depth -1;
25992 	goto end_elem;
25993     }
25994     if ((inode->typeDef == NULL) ||
25995 	(inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
25996 	/*
25997 	* 1. the type definition might be missing if the element was
25998 	*    error prone
25999 	* 2. it might be abstract.
26000 	*/
26001 	goto end_elem;
26002     }
26003     /*
26004     * Check the content model.
26005     */
26006     if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
26007 	(inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
26008 
26009 	/*
26010 	* Workaround for "anyType".
26011 	*/
26012 	if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
26013 	    goto character_content;
26014 
26015 	if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
26016 	    xmlChar *values[10];
26017 	    int terminal, nbval = 10, nbneg;
26018 
26019 	    if (inode->regexCtxt == NULL) {
26020 		/*
26021 		* Create the regex context.
26022 		*/
26023 		inode->regexCtxt =
26024 		    xmlRegNewExecCtxt(inode->typeDef->contModel,
26025 		    (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
26026 		    vctxt);
26027 		if (inode->regexCtxt == NULL) {
26028 		    VERROR_INT("xmlSchemaValidatorPopElem",
26029 			"failed to create a regex context");
26030 		    goto internal_error;
26031 		}
26032 #ifdef DEBUG_AUTOMATA
26033 		xmlGenericError(xmlGenericErrorContext,
26034 		    "AUTOMATON create on '%s'\n", inode->localName);
26035 #endif
26036 	    }
26037 	    /*
26038 	    * Get hold of the still expected content, since a further
26039 	    * call to xmlRegExecPushString() will loose this information.
26040 	    */
26041 	    xmlRegExecNextValues(inode->regexCtxt,
26042 		&nbval, &nbneg, &values[0], &terminal);
26043 	    ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
26044 	    if ((ret<0) || ((ret==0) && (!INODE_NILLED(inode)))) {
26045 		/*
26046 		* Still missing something.
26047 		*/
26048 		ret = 1;
26049 		inode->flags |=
26050 		    XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26051 		xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26052 		    XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
26053 		    "Missing child element(s)",
26054 		    nbval, nbneg, values);
26055 #ifdef DEBUG_AUTOMATA
26056 		xmlGenericError(xmlGenericErrorContext,
26057 		    "AUTOMATON missing ERROR on '%s'\n",
26058 		    inode->localName);
26059 #endif
26060 	    } else {
26061 		/*
26062 		* Content model is satisfied.
26063 		*/
26064 		ret = 0;
26065 #ifdef DEBUG_AUTOMATA
26066 		xmlGenericError(xmlGenericErrorContext,
26067 		    "AUTOMATON succeeded on '%s'\n",
26068 		    inode->localName);
26069 #endif
26070 	    }
26071 
26072 	}
26073     }
26074     if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
26075 	goto end_elem;
26076 
26077 character_content:
26078 
26079     if (vctxt->value != NULL) {
26080 	xmlSchemaFreeValue(vctxt->value);
26081 	vctxt->value = NULL;
26082     }
26083     /*
26084     * Check character content.
26085     */
26086     if (inode->decl == NULL) {
26087 	/*
26088 	* Speedup if no declaration exists.
26089 	*/
26090 	if (WXS_IS_SIMPLE(inode->typeDef)) {
26091 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26092 		inode, inode->typeDef, inode->value);
26093 	} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26094 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26095 		inode, inode->typeDef->contentTypeDef,
26096 		inode->value);
26097 	}
26098 	if (ret < 0) {
26099 	    VERROR_INT("xmlSchemaValidatorPopElem",
26100 		"calling xmlSchemaVCheckCVCSimpleType()");
26101 	    goto internal_error;
26102 	}
26103 	goto end_elem;
26104     }
26105     /*
26106     * cvc-elt (3.3.4) : 5
26107     * The appropriate case among the following must be true:
26108     */
26109     /*
26110     * cvc-elt (3.3.4) : 5.1
26111     * If the declaration has a {value constraint},
26112     * the item has neither element nor character [children] and
26113     * clause 3.2 has not applied, then all of the following must be true:
26114     */
26115     if ((inode->decl->value != NULL) &&
26116 	(inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
26117 	(! INODE_NILLED(inode))) {
26118 	/*
26119 	* cvc-elt (3.3.4) : 5.1.1
26120 	* If the �actual type definition� is a �local type definition�
26121 	* then the canonical lexical representation of the {value constraint}
26122 	* value must be a valid default for the �actual type definition� as
26123 	* defined in Element Default Valid (Immediate) (�3.3.6).
26124 	*/
26125 	/*
26126 	* NOTE: 'local' above means types acquired by xsi:type.
26127 	* NOTE: Although the *canonical* value is stated, it is not
26128 	* relevant if canonical or not. Additionally XML Schema 1.1
26129 	* will removed this requirement as well.
26130 	*/
26131 	if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
26132 
26133 	    ret = xmlSchemaCheckCOSValidDefault(vctxt,
26134 		inode->decl->value, &(inode->val));
26135 	    if (ret != 0) {
26136 		if (ret < 0) {
26137 		    VERROR_INT("xmlSchemaValidatorPopElem",
26138 			"calling xmlSchemaCheckCOSValidDefault()");
26139 		    goto internal_error;
26140 		}
26141 		goto end_elem;
26142 	    }
26143 	    /*
26144 	    * Stop here, to avoid redundant validation of the value
26145 	    * (see following).
26146 	    */
26147 	    goto default_psvi;
26148 	}
26149 	/*
26150 	* cvc-elt (3.3.4) : 5.1.2
26151 	* The element information item with the canonical lexical
26152 	* representation of the {value constraint} value used as its
26153 	* �normalized value� must be �valid� with respect to the
26154 	* �actual type definition� as defined by Element Locally Valid (Type)
26155 	* (�3.3.4).
26156 	*/
26157 	if (WXS_IS_SIMPLE(inode->typeDef)) {
26158 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26159 		inode, inode->typeDef, inode->decl->value);
26160 	} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26161 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26162 		inode, inode->typeDef->contentTypeDef,
26163 		inode->decl->value);
26164 	}
26165 	if (ret != 0) {
26166 	    if (ret < 0) {
26167 		VERROR_INT("xmlSchemaValidatorPopElem",
26168 		    "calling xmlSchemaVCheckCVCSimpleType()");
26169 		goto internal_error;
26170 	    }
26171 	    goto end_elem;
26172 	}
26173 
26174 default_psvi:
26175 	/*
26176 	* PSVI: Create a text node on the instance element.
26177 	*/
26178 	if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
26179 	    (inode->node != NULL)) {
26180 	    xmlNodePtr textChild;
26181 	    xmlChar *normValue;
26182 	    /*
26183 	    * VAL TODO: Normalize the value.
26184 	    */
26185 	    normValue = xmlSchemaNormalizeValue(inode->typeDef,
26186 		inode->decl->value);
26187 	    if (normValue != NULL) {
26188 		textChild = xmlNewText(BAD_CAST normValue);
26189 		xmlFree(normValue);
26190 	    } else
26191 		textChild = xmlNewText(inode->decl->value);
26192 	    if (textChild == NULL) {
26193 		VERROR_INT("xmlSchemaValidatorPopElem",
26194 		    "calling xmlNewText()");
26195 		goto internal_error;
26196 	    } else
26197 		xmlAddChild(inode->node, textChild);
26198 	}
26199 
26200     } else if (! INODE_NILLED(inode)) {
26201 	/*
26202 	* 5.2.1 The element information item must be �valid� with respect
26203 	* to the �actual type definition� as defined by Element Locally
26204 	* Valid (Type) (�3.3.4).
26205 	*/
26206 	if (WXS_IS_SIMPLE(inode->typeDef)) {
26207 	     /*
26208 	    * SPEC (cvc-type) (3.1)
26209 	    * "If the type definition is a simple type definition, ..."
26210 	    * (3.1.3) "If clause 3.2 of Element Locally Valid
26211 	    * (Element) (�3.3.4) did not apply, then the �normalized value�
26212 	    * must be �valid� with respect to the type definition as defined
26213 	    * by String Valid (�3.14.4).
26214 	    */
26215 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26216 		    inode, inode->typeDef, inode->value);
26217 	} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26218 	    /*
26219 	    * SPEC (cvc-type) (3.2) "If the type definition is a complex type
26220 	    * definition, then the element information item must be
26221 	    * �valid� with respect to the type definition as per
26222 	    * Element Locally Valid (Complex Type) (�3.4.4);"
26223 	    *
26224 	    * SPEC (cvc-complex-type) (2.2)
26225 	    * "If the {content type} is a simple type definition, ...
26226 	    * the �normalized value� of the element information item is
26227 	    * �valid� with respect to that simple type definition as
26228 	    * defined by String Valid (�3.14.4)."
26229 	    */
26230 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26231 		inode, inode->typeDef->contentTypeDef, inode->value);
26232 	}
26233 	if (ret != 0) {
26234 	    if (ret < 0) {
26235 		VERROR_INT("xmlSchemaValidatorPopElem",
26236 		    "calling xmlSchemaVCheckCVCSimpleType()");
26237 		goto internal_error;
26238 	    }
26239 	    goto end_elem;
26240 	}
26241 	/*
26242 	* 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
26243 	* not applied, all of the following must be true:
26244 	*/
26245 	if ((inode->decl->value != NULL) &&
26246 	    (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
26247 
26248 	    /*
26249 	    * TODO: We will need a computed value, when comparison is
26250 	    * done on computed values.
26251 	    */
26252 	    /*
26253 	    * 5.2.2.1 The element information item must have no element
26254 	    * information item [children].
26255 	    */
26256 	    if (inode->flags &
26257 		    XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
26258 		ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
26259 		VERROR(ret, NULL,
26260 		    "The content must not containt element nodes since "
26261 		    "there is a fixed value constraint");
26262 		goto end_elem;
26263 	    } else {
26264 		/*
26265 		* 5.2.2.2 The appropriate case among the following must
26266 		* be true:
26267 		*/
26268 		if (WXS_HAS_MIXED_CONTENT(inode->typeDef)) {
26269 		    /*
26270 		    * 5.2.2.2.1 If the {content type} of the �actual type
26271 		    * definition� is mixed, then the *initial value* of the
26272 		    * item must match the canonical lexical representation
26273 		    * of the {value constraint} value.
26274 		    *
26275 		    * ... the *initial value* of an element information
26276 		    * item is the string composed of, in order, the
26277 		    * [character code] of each character information item in
26278 		    * the [children] of that element information item.
26279 		    */
26280 		    if (! xmlStrEqual(inode->value, inode->decl->value)){
26281 			/*
26282 			* VAL TODO: Report invalid & expected values as well.
26283 			* VAL TODO: Implement the canonical stuff.
26284 			*/
26285 			ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
26286 			xmlSchemaCustomErr(ACTXT_CAST vctxt,
26287 			    ret, NULL, NULL,
26288 			    "The initial value '%s' does not match the fixed "
26289 			    "value constraint '%s'",
26290 			    inode->value, inode->decl->value);
26291 			goto end_elem;
26292 		    }
26293 		} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26294 		    /*
26295 		    * 5.2.2.2.2 If the {content type} of the �actual type
26296 		    * definition� is a simple type definition, then the
26297 		    * *actual value* of the item must match the canonical
26298 		    * lexical representation of the {value constraint} value.
26299 		    */
26300 		    /*
26301 		    * VAL TODO: *actual value* is the normalized value, impl.
26302 		    *           this.
26303 		    * VAL TODO: Report invalid & expected values as well.
26304 		    * VAL TODO: Implement a comparison with the computed values.
26305 		    */
26306 		    if (! xmlStrEqual(inode->value,
26307 			    inode->decl->value)) {
26308 			ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
26309 			xmlSchemaCustomErr(ACTXT_CAST vctxt,
26310 			    ret, NULL, NULL,
26311 			    "The actual value '%s' does not match the fixed "
26312 			    "value constraint '%s'",
26313 			    inode->value,
26314 			    inode->decl->value);
26315 			goto end_elem;
26316 		    }
26317 		}
26318 	    }
26319 	}
26320     }
26321 
26322 end_elem:
26323     if (vctxt->depth < 0) {
26324 	/* TODO: raise error? */
26325 	return (0);
26326     }
26327     if (vctxt->depth == vctxt->skipDepth)
26328 	vctxt->skipDepth = -1;
26329     /*
26330     * Evaluate the history of XPath state objects.
26331     */
26332     if (inode->appliedXPath &&
26333 	(xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1))
26334 	goto internal_error;
26335     /*
26336     * MAYBE TODO:
26337     * SPEC (6) "The element information item must be �valid� with
26338     * respect to each of the {identity-constraint definitions} as per
26339     * Identity-constraint Satisfied (�3.11.4)."
26340     */
26341     /*
26342     * PSVI TODO: If we expose IDC node-tables via PSVI then the tables
26343     *   need to be built in any case.
26344     *   We will currently build IDC node-tables and bubble them only if
26345     *   keyrefs do exist.
26346     */
26347 
26348     /*
26349     * Add the current IDC target-nodes to the IDC node-tables.
26350     */
26351     if ((inode->idcMatchers != NULL) &&
26352 	(vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26353     {
26354 	if (xmlSchemaIDCFillNodeTables(vctxt, inode) == -1)
26355 	    goto internal_error;
26356     }
26357     /*
26358     * Validate IDC keyrefs.
26359     */
26360     if (vctxt->inode->hasKeyrefs)
26361 	if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
26362 	    goto internal_error;
26363     /*
26364     * Merge/free the IDC table.
26365     */
26366     if (inode->idcTable != NULL) {
26367 #ifdef DEBUG_IDC_NODE_TABLE
26368 	xmlSchemaDebugDumpIDCTable(stdout,
26369 	    inode->nsName,
26370 	    inode->localName,
26371 	    inode->idcTable);
26372 #endif
26373 	if ((vctxt->depth > 0) &&
26374 	    (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26375 	{
26376 	    /*
26377 	    * Merge the IDC node table with the table of the parent node.
26378 	    */
26379 	    if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
26380 		goto internal_error;
26381 	}
26382     }
26383     /*
26384     * Clear the current ielem.
26385     * VAL TODO: Don't free the PSVI IDC tables if they are
26386     * requested for the PSVI.
26387     */
26388     xmlSchemaClearElemInfo(vctxt, inode);
26389     /*
26390     * Skip further processing if we are on the validation root.
26391     */
26392     if (vctxt->depth == 0) {
26393 	vctxt->depth--;
26394 	vctxt->inode = NULL;
26395 	return (0);
26396     }
26397     /*
26398     * Reset the keyrefDepth if needed.
26399     */
26400     if (vctxt->aidcs != NULL) {
26401 	xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
26402 	do {
26403 	    if (aidc->keyrefDepth == vctxt->depth) {
26404 		/*
26405 		* A 'keyrefDepth' of a key/unique IDC matches the current
26406 		* depth, this means that we are leaving the scope of the
26407 		* top-most keyref IDC which refers to this IDC.
26408 		*/
26409 		aidc->keyrefDepth = -1;
26410 	    }
26411 	    aidc = aidc->next;
26412 	} while (aidc != NULL);
26413     }
26414     vctxt->depth--;
26415     vctxt->inode = vctxt->elemInfos[vctxt->depth];
26416     /*
26417     * VAL TODO: 7 If the element information item is the �validation root�, it must be
26418     * �valid� per Validation Root Valid (ID/IDREF) (�3.3.4).
26419     */
26420     return (ret);
26421 
26422 internal_error:
26423     vctxt->err = -1;
26424     return (-1);
26425 }
26426 
26427 /*
26428 * 3.4.4 Complex Type Definition Validation Rules
26429 * Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
26430 */
26431 static int
xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)26432 xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
26433 {
26434     xmlSchemaNodeInfoPtr pielem;
26435     xmlSchemaTypePtr ptype;
26436     int ret = 0;
26437 
26438     if (vctxt->depth <= 0) {
26439 	VERROR_INT("xmlSchemaValidateChildElem",
26440 	    "not intended for the validation root");
26441 	return (-1);
26442     }
26443     pielem = vctxt->elemInfos[vctxt->depth -1];
26444     if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26445 	pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26446     /*
26447     * Handle 'nilled' elements.
26448     */
26449     if (INODE_NILLED(pielem)) {
26450 	/*
26451 	* SPEC (cvc-elt) (3.3.4) : (3.2.1)
26452 	*/
26453 	ACTIVATE_PARENT_ELEM;
26454 	ret = XML_SCHEMAV_CVC_ELT_3_2_1;
26455 	VERROR(ret, NULL,
26456 	    "Neither character nor element content is allowed, "
26457 	    "because the element was 'nilled'");
26458 	ACTIVATE_ELEM;
26459 	goto unexpected_elem;
26460     }
26461 
26462     ptype = pielem->typeDef;
26463 
26464     if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
26465 	/*
26466 	* Workaround for "anyType": we have currently no content model
26467 	* assigned for "anyType", so handle it explicitely.
26468 	* "anyType" has an unbounded, lax "any" wildcard.
26469 	*/
26470 	vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26471 	    vctxt->inode->localName,
26472 	    vctxt->inode->nsName);
26473 
26474 	if (vctxt->inode->decl == NULL) {
26475 	    xmlSchemaAttrInfoPtr iattr;
26476 	    /*
26477 	    * Process "xsi:type".
26478 	    * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
26479 	    */
26480 	    iattr = xmlSchemaGetMetaAttrInfo(vctxt,
26481 		XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
26482 	    if (iattr != NULL) {
26483 		ret = xmlSchemaProcessXSIType(vctxt, iattr,
26484 		    &(vctxt->inode->typeDef), NULL);
26485 		if (ret != 0) {
26486 		    if (ret == -1) {
26487 			VERROR_INT("xmlSchemaValidateChildElem",
26488 			    "calling xmlSchemaProcessXSIType() to "
26489 			    "process the attribute 'xsi:nil'");
26490 			return (-1);
26491 		    }
26492 		    return (ret);
26493 		}
26494 	    } else {
26495 		 /*
26496 		 * Fallback to "anyType".
26497 		 *
26498 		 * SPEC (cvc-assess-elt)
26499 		 * "If the item cannot be �strictly assessed�, [...]
26500 		 * an element information item's schema validity may be laxly
26501 		 * assessed if its �context-determined declaration� is not
26502 		 * skip by �validating� with respect to the �ur-type
26503 		 * definition� as per Element Locally Valid (Type) (�3.3.4)."
26504 		*/
26505 		vctxt->inode->typeDef =
26506 		    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
26507 	    }
26508 	}
26509 	return (0);
26510     }
26511 
26512     switch (ptype->contentType) {
26513 	case XML_SCHEMA_CONTENT_EMPTY:
26514 	    /*
26515 	    * SPEC (2.1) "If the {content type} is empty, then the
26516 	    * element information item has no character or element
26517 	    * information item [children]."
26518 	    */
26519 	    ACTIVATE_PARENT_ELEM
26520 	    ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
26521 	    VERROR(ret, NULL,
26522 		"Element content is not allowed, "
26523 		"because the content type is empty");
26524 	    ACTIVATE_ELEM
26525 	    goto unexpected_elem;
26526 	    break;
26527 
26528 	case XML_SCHEMA_CONTENT_MIXED:
26529         case XML_SCHEMA_CONTENT_ELEMENTS: {
26530 	    xmlRegExecCtxtPtr regexCtxt;
26531 	    xmlChar *values[10];
26532 	    int terminal, nbval = 10, nbneg;
26533 
26534 	    /* VAL TODO: Optimized "anyType" validation.*/
26535 
26536 	    if (ptype->contModel == NULL) {
26537 		VERROR_INT("xmlSchemaValidateChildElem",
26538 		    "type has elem content but no content model");
26539 		return (-1);
26540 	    }
26541 	    /*
26542 	    * Safety belf for evaluation if the cont. model was already
26543 	    * examined to be invalid.
26544 	    */
26545 	    if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
26546 		VERROR_INT("xmlSchemaValidateChildElem",
26547 		    "validating elem, but elem content is already invalid");
26548 		return (-1);
26549 	    }
26550 
26551 	    regexCtxt = pielem->regexCtxt;
26552 	    if (regexCtxt == NULL) {
26553 		/*
26554 		* Create the regex context.
26555 		*/
26556 		regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
26557 		    (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
26558 		    vctxt);
26559 		if (regexCtxt == NULL) {
26560 		    VERROR_INT("xmlSchemaValidateChildElem",
26561 			"failed to create a regex context");
26562 		    return (-1);
26563 		}
26564 		pielem->regexCtxt = regexCtxt;
26565 #ifdef DEBUG_AUTOMATA
26566 		xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
26567 		    pielem->localName);
26568 #endif
26569 	    }
26570 
26571 	    /*
26572 	    * SPEC (2.4) "If the {content type} is element-only or mixed,
26573 	    * then the sequence of the element information item's
26574 	    * element information item [children], if any, taken in
26575 	    * order, is �valid� with respect to the {content type}'s
26576 	    * particle, as defined in Element Sequence Locally Valid
26577 	    * (Particle) (�3.9.4)."
26578 	    */
26579 	    ret = xmlRegExecPushString2(regexCtxt,
26580 		vctxt->inode->localName,
26581 		vctxt->inode->nsName,
26582 		vctxt->inode);
26583 #ifdef DEBUG_AUTOMATA
26584 	    if (ret < 0)
26585 		xmlGenericError(xmlGenericErrorContext,
26586 		"AUTOMATON push ERROR for '%s' on '%s'\n",
26587 		vctxt->inode->localName, pielem->localName);
26588 	    else
26589 		xmlGenericError(xmlGenericErrorContext,
26590 		"AUTOMATON push OK for '%s' on '%s'\n",
26591 		vctxt->inode->localName, pielem->localName);
26592 #endif
26593 	    if (vctxt->err == XML_SCHEMAV_INTERNAL) {
26594 		VERROR_INT("xmlSchemaValidateChildElem",
26595 		    "calling xmlRegExecPushString2()");
26596 		return (-1);
26597 	    }
26598 	    if (ret < 0) {
26599 		xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
26600 		    &values[0], &terminal);
26601 		xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26602 		    XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
26603 		    "This element is not expected",
26604 		    nbval, nbneg, values);
26605 		ret = vctxt->err;
26606 		goto unexpected_elem;
26607 	    } else
26608 		ret = 0;
26609 	}
26610 	    break;
26611 	case XML_SCHEMA_CONTENT_SIMPLE:
26612 	case XML_SCHEMA_CONTENT_BASIC:
26613 	    ACTIVATE_PARENT_ELEM
26614 	    if (WXS_IS_COMPLEX(ptype)) {
26615 		/*
26616 		* SPEC (cvc-complex-type) (2.2)
26617 		* "If the {content type} is a simple type definition, then
26618 		* the element information item has no element information
26619 		* item [children], ..."
26620 		*/
26621 		ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
26622 		VERROR(ret, NULL, "Element content is not allowed, "
26623 		    "because the content type is a simple type definition");
26624 	    } else {
26625 		/*
26626 		* SPEC (cvc-type) (3.1.2) "The element information item must
26627 		* have no element information item [children]."
26628 		*/
26629 		ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
26630 		VERROR(ret, NULL, "Element content is not allowed, "
26631 		    "because the type definition is simple");
26632 	    }
26633 	    ACTIVATE_ELEM
26634 	    ret = vctxt->err;
26635 	    goto unexpected_elem;
26636 	    break;
26637 
26638 	default:
26639 	    break;
26640     }
26641     return (ret);
26642 unexpected_elem:
26643     /*
26644     * Pop this element and set the skipDepth to skip
26645     * all further content of the parent element.
26646     */
26647     vctxt->skipDepth = vctxt->depth;
26648     vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
26649     pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26650     return (ret);
26651 }
26652 
26653 #define XML_SCHEMA_PUSH_TEXT_PERSIST 1
26654 #define XML_SCHEMA_PUSH_TEXT_CREATED 2
26655 #define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
26656 
26657 static int
xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,int nodeType,const xmlChar * value,int len,int mode,int * consumed)26658 xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
26659 		  int nodeType, const xmlChar *value, int len,
26660 		  int mode, int *consumed)
26661 {
26662     /*
26663     * Unfortunately we have to duplicate the text sometimes.
26664     * OPTIMIZE: Maybe we could skip it, if:
26665     *   1. content type is simple
26666     *   2. whitespace is "collapse"
26667     *   3. it consists of whitespace only
26668     *
26669     * Process character content.
26670     */
26671     if (consumed != NULL)
26672 	*consumed = 0;
26673     if (INODE_NILLED(vctxt->inode)) {
26674 	/*
26675 	* SPEC cvc-elt (3.3.4 - 3.2.1)
26676 	* "The element information item must have no character or
26677 	* element information item [children]."
26678 	*/
26679 	VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
26680 	    "Neither character nor element content is allowed "
26681 	    "because the element is 'nilled'");
26682 	return (vctxt->err);
26683     }
26684     /*
26685     * SPEC (2.1) "If the {content type} is empty, then the
26686     * element information item has no character or element
26687     * information item [children]."
26688     */
26689     if (vctxt->inode->typeDef->contentType ==
26690 	    XML_SCHEMA_CONTENT_EMPTY) {
26691 	VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
26692 	    "Character content is not allowed, "
26693 	    "because the content type is empty");
26694 	return (vctxt->err);
26695     }
26696 
26697     if (vctxt->inode->typeDef->contentType ==
26698 	    XML_SCHEMA_CONTENT_ELEMENTS) {
26699 	if ((nodeType != XML_TEXT_NODE) ||
26700 	    (! xmlSchemaIsBlank((xmlChar *) value, len))) {
26701 	    /*
26702 	    * SPEC cvc-complex-type (2.3)
26703 	    * "If the {content type} is element-only, then the
26704 	    * element information item has no character information
26705 	    * item [children] other than those whose [character
26706 	    * code] is defined as a white space in [XML 1.0 (Second
26707 	    * Edition)]."
26708 	    */
26709 	    VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
26710 		"Character content other than whitespace is not allowed "
26711 		"because the content type is 'element-only'");
26712 	    return (vctxt->err);
26713 	}
26714 	return (0);
26715     }
26716 
26717     if ((value == NULL) || (value[0] == 0))
26718 	return (0);
26719     /*
26720     * Save the value.
26721     * NOTE that even if the content type is *mixed*, we need the
26722     * *initial value* for default/fixed value constraints.
26723     */
26724     if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
26725 	((vctxt->inode->decl == NULL) ||
26726 	(vctxt->inode->decl->value == NULL)))
26727 	return (0);
26728 
26729     if (vctxt->inode->value == NULL) {
26730 	/*
26731 	* Set the value.
26732 	*/
26733 	switch (mode) {
26734 	    case XML_SCHEMA_PUSH_TEXT_PERSIST:
26735 		/*
26736 		* When working on a tree.
26737 		*/
26738 		vctxt->inode->value = value;
26739 		break;
26740 	    case XML_SCHEMA_PUSH_TEXT_CREATED:
26741 		/*
26742 		* When working with the reader.
26743 		* The value will be freed by the element info.
26744 		*/
26745 		vctxt->inode->value = value;
26746 		if (consumed != NULL)
26747 		    *consumed = 1;
26748 		vctxt->inode->flags |=
26749 		    XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26750 		break;
26751 	    case XML_SCHEMA_PUSH_TEXT_VOLATILE:
26752 		/*
26753 		* When working with SAX.
26754 		* The value will be freed by the element info.
26755 		*/
26756 		if (len != -1)
26757 		    vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
26758 		else
26759 		    vctxt->inode->value = BAD_CAST xmlStrdup(value);
26760 		vctxt->inode->flags |=
26761 		    XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26762 		break;
26763 	    default:
26764 		break;
26765 	}
26766     } else {
26767 	if (len < 0)
26768 	    len = xmlStrlen(value);
26769 	/*
26770 	* Concat the value.
26771 	*/
26772 	if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
26773 	    vctxt->inode->value = BAD_CAST xmlStrncat(
26774 		(xmlChar *) vctxt->inode->value, value, len);
26775 	} else {
26776 	    vctxt->inode->value =
26777 		BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
26778 	    vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26779 	}
26780     }
26781 
26782     return (0);
26783 }
26784 
26785 static int
xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)26786 xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
26787 {
26788     int ret = 0;
26789 
26790     if ((vctxt->skipDepth != -1) &&
26791 	(vctxt->depth >= vctxt->skipDepth)) {
26792 	VERROR_INT("xmlSchemaValidateElem",
26793 	    "in skip-state");
26794 	goto internal_error;
26795     }
26796     if (vctxt->xsiAssemble) {
26797 	/*
26798 	* We will stop validation if there was an error during
26799 	* dynamic schema construction.
26800 	* Note that we simply set @skipDepth to 0, this could
26801 	* mean that a streaming document via SAX would be
26802 	* still read to the end but it won't be validated any more.
26803 	* TODO: If we are sure how to stop the validation at once
26804 	*   for all input scenarios, then this should be changed to
26805 	*   instantly stop the validation.
26806 	*/
26807 	ret = xmlSchemaAssembleByXSI(vctxt);
26808 	if (ret != 0) {
26809 	    if (ret == -1)
26810 		goto internal_error;
26811 	    vctxt->skipDepth = 0;
26812 	    return(ret);
26813 	}
26814         /*
26815          * Augment the IDC definitions for the main schema and all imported ones
26816          * NOTE: main schema is the first in the imported list
26817          */
26818         xmlHashScan(vctxt->schema->schemasImports,(xmlHashScanner)xmlSchemaAugmentImportedIDC, vctxt);
26819     }
26820     if (vctxt->depth > 0) {
26821 	/*
26822 	* Validate this element against the content model
26823 	* of the parent.
26824 	*/
26825 	ret = xmlSchemaValidateChildElem(vctxt);
26826 	if (ret != 0) {
26827 	    if (ret < 0) {
26828 		VERROR_INT("xmlSchemaValidateElem",
26829 		    "calling xmlSchemaStreamValidateChildElement()");
26830 		goto internal_error;
26831 	    }
26832 	    goto exit;
26833 	}
26834 	if (vctxt->depth == vctxt->skipDepth)
26835 	    goto exit;
26836 	if ((vctxt->inode->decl == NULL) &&
26837 	    (vctxt->inode->typeDef == NULL)) {
26838 	    VERROR_INT("xmlSchemaValidateElem",
26839 		"the child element was valid but neither the "
26840 		"declaration nor the type was set");
26841 	    goto internal_error;
26842 	}
26843     } else {
26844 	/*
26845 	* Get the declaration of the validation root.
26846 	*/
26847 	vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26848 	    vctxt->inode->localName,
26849 	    vctxt->inode->nsName);
26850 	if (vctxt->inode->decl == NULL) {
26851 	    ret = XML_SCHEMAV_CVC_ELT_1;
26852 	    VERROR(ret, NULL,
26853 		"No matching global declaration available "
26854 		"for the validation root");
26855 	    goto exit;
26856 	}
26857     }
26858 
26859     if (vctxt->inode->decl == NULL)
26860 	goto type_validation;
26861 
26862     if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
26863 	int skip;
26864 	/*
26865 	* Wildcards.
26866 	*/
26867 	ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
26868 	if (ret != 0) {
26869 	    if (ret < 0) {
26870 		VERROR_INT("xmlSchemaValidateElem",
26871 		    "calling xmlSchemaValidateElemWildcard()");
26872 		goto internal_error;
26873 	    }
26874 	    goto exit;
26875 	}
26876 	if (skip) {
26877 	    vctxt->skipDepth = vctxt->depth;
26878 	    goto exit;
26879 	}
26880 	/*
26881 	* The declaration might be set by the wildcard validation,
26882 	* when the processContents is "lax" or "strict".
26883 	*/
26884 	if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
26885 	    /*
26886 	    * Clear the "decl" field to not confuse further processing.
26887 	    */
26888 	    vctxt->inode->decl = NULL;
26889 	    goto type_validation;
26890 	}
26891     }
26892     /*
26893     * Validate against the declaration.
26894     */
26895     ret = xmlSchemaValidateElemDecl(vctxt);
26896     if (ret != 0) {
26897 	if (ret < 0) {
26898 	    VERROR_INT("xmlSchemaValidateElem",
26899 		"calling xmlSchemaValidateElemDecl()");
26900 	    goto internal_error;
26901 	}
26902 	goto exit;
26903     }
26904     /*
26905     * Validate against the type definition.
26906     */
26907 type_validation:
26908 
26909     if (vctxt->inode->typeDef == NULL) {
26910 	vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26911 	ret = XML_SCHEMAV_CVC_TYPE_1;
26912     	VERROR(ret, NULL,
26913     	    "The type definition is absent");
26914 	goto exit;
26915     }
26916     if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
26917 	vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26918 	ret = XML_SCHEMAV_CVC_TYPE_2;
26919     	    VERROR(ret, NULL,
26920     	    "The type definition is abstract");
26921 	goto exit;
26922     }
26923     /*
26924     * Evaluate IDCs. Do it here, since new IDC matchers are registered
26925     * during validation against the declaration. This must be done
26926     * _before_ attribute validation.
26927     */
26928     if (vctxt->xpathStates != NULL) {
26929 	ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
26930 	vctxt->inode->appliedXPath = 1;
26931 	if (ret == -1) {
26932 	    VERROR_INT("xmlSchemaValidateElem",
26933 		"calling xmlSchemaXPathEvaluate()");
26934 	    goto internal_error;
26935 	}
26936     }
26937     /*
26938     * Validate attributes.
26939     */
26940     if (WXS_IS_COMPLEX(vctxt->inode->typeDef)) {
26941 	if ((vctxt->nbAttrInfos != 0) ||
26942 	    (vctxt->inode->typeDef->attrUses != NULL)) {
26943 
26944 	    ret = xmlSchemaVAttributesComplex(vctxt);
26945 	}
26946     } else if (vctxt->nbAttrInfos != 0) {
26947 
26948 	ret = xmlSchemaVAttributesSimple(vctxt);
26949     }
26950     /*
26951     * Clear registered attributes.
26952     */
26953     if (vctxt->nbAttrInfos != 0)
26954 	xmlSchemaClearAttrInfos(vctxt);
26955     if (ret == -1) {
26956 	VERROR_INT("xmlSchemaValidateElem",
26957 	    "calling attributes validation");
26958 	goto internal_error;
26959     }
26960     /*
26961     * Don't return an error if attributes are invalid on purpose.
26962     */
26963     ret = 0;
26964 
26965 exit:
26966     if (ret != 0)
26967 	vctxt->skipDepth = vctxt->depth;
26968     return (ret);
26969 internal_error:
26970     return (-1);
26971 }
26972 
26973 #ifdef XML_SCHEMA_READER_ENABLED
26974 static int
xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)26975 xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
26976 {
26977     const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
26978     int depth, nodeType, ret = 0, consumed;
26979     xmlSchemaNodeInfoPtr ielem;
26980 
26981     vctxt->depth = -1;
26982     ret = xmlTextReaderRead(vctxt->reader);
26983     /*
26984     * Move to the document element.
26985     */
26986     while (ret == 1) {
26987 	nodeType = xmlTextReaderNodeType(vctxt->reader);
26988 	if (nodeType == XML_ELEMENT_NODE)
26989 	    goto root_found;
26990 	ret = xmlTextReaderRead(vctxt->reader);
26991     }
26992     goto exit;
26993 
26994 root_found:
26995 
26996     do {
26997 	depth = xmlTextReaderDepth(vctxt->reader);
26998 	nodeType = xmlTextReaderNodeType(vctxt->reader);
26999 
27000 	if (nodeType == XML_ELEMENT_NODE) {
27001 
27002 	    vctxt->depth++;
27003 	    if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27004 		VERROR_INT("xmlSchemaVReaderWalk",
27005 		    "calling xmlSchemaValidatorPushElem()");
27006 		goto internal_error;
27007 	    }
27008 	    ielem = vctxt->inode;
27009 	    ielem->localName = xmlTextReaderLocalName(vctxt->reader);
27010 	    ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
27011 	    ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
27012 	    /*
27013 	    * Is the element empty?
27014 	    */
27015 	    ret = xmlTextReaderIsEmptyElement(vctxt->reader);
27016 	    if (ret == -1) {
27017 		VERROR_INT("xmlSchemaVReaderWalk",
27018 		    "calling xmlTextReaderIsEmptyElement()");
27019 		goto internal_error;
27020 	    }
27021 	    if (ret) {
27022 		ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27023 	    }
27024 	    /*
27025 	    * Register attributes.
27026 	    */
27027 	    vctxt->nbAttrInfos = 0;
27028 	    ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
27029 	    if (ret == -1) {
27030 		VERROR_INT("xmlSchemaVReaderWalk",
27031 		    "calling xmlTextReaderMoveToFirstAttribute()");
27032 		goto internal_error;
27033 	    }
27034 	    if (ret == 1) {
27035 		do {
27036 		    /*
27037 		    * VAL TODO: How do we know that the reader works on a
27038 		    * node tree, to be able to pass a node here?
27039 		    */
27040 		    if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
27041 			(const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
27042 			xmlTextReaderNamespaceUri(vctxt->reader), 1,
27043 			xmlTextReaderValue(vctxt->reader), 1) == -1) {
27044 
27045 			VERROR_INT("xmlSchemaVReaderWalk",
27046 			    "calling xmlSchemaValidatorPushAttribute()");
27047 			goto internal_error;
27048 		    }
27049 		    ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
27050 		    if (ret == -1) {
27051 			VERROR_INT("xmlSchemaVReaderWalk",
27052 			    "calling xmlTextReaderMoveToFirstAttribute()");
27053 			goto internal_error;
27054 		    }
27055 		} while (ret == 1);
27056 		/*
27057 		* Back to element position.
27058 		*/
27059 		ret = xmlTextReaderMoveToElement(vctxt->reader);
27060 		if (ret == -1) {
27061 		    VERROR_INT("xmlSchemaVReaderWalk",
27062 			"calling xmlTextReaderMoveToElement()");
27063 		    goto internal_error;
27064 		}
27065 	    }
27066 	    /*
27067 	    * Validate the element.
27068 	    */
27069 	    ret= xmlSchemaValidateElem(vctxt);
27070 	    if (ret != 0) {
27071 		if (ret == -1) {
27072 		    VERROR_INT("xmlSchemaVReaderWalk",
27073 			"calling xmlSchemaValidateElem()");
27074 		    goto internal_error;
27075 		}
27076 		goto exit;
27077 	    }
27078 	    if (vctxt->depth == vctxt->skipDepth) {
27079 		int curDepth;
27080 		/*
27081 		* Skip all content.
27082 		*/
27083 		if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
27084 		    ret = xmlTextReaderRead(vctxt->reader);
27085 		    curDepth = xmlTextReaderDepth(vctxt->reader);
27086 		    while ((ret == 1) && (curDepth != depth)) {
27087 			ret = xmlTextReaderRead(vctxt->reader);
27088 			curDepth = xmlTextReaderDepth(vctxt->reader);
27089 		    }
27090 		    if (ret < 0) {
27091 			/*
27092 			* VAL TODO: A reader error occured; what to do here?
27093 			*/
27094 			ret = 1;
27095 			goto exit;
27096 		    }
27097 		}
27098 		goto leave_elem;
27099 	    }
27100 	    /*
27101 	    * READER VAL TODO: Is an END_ELEM really never called
27102 	    * if the elem is empty?
27103 	    */
27104 	    if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27105 		goto leave_elem;
27106 	} else if (nodeType == END_ELEM) {
27107 	    /*
27108 	    * Process END of element.
27109 	    */
27110 leave_elem:
27111 	    ret = xmlSchemaValidatorPopElem(vctxt);
27112 	    if (ret != 0) {
27113 		if (ret < 0) {
27114 		    VERROR_INT("xmlSchemaVReaderWalk",
27115 			"calling xmlSchemaValidatorPopElem()");
27116 		    goto internal_error;
27117 		}
27118 		goto exit;
27119 	    }
27120 	    if (vctxt->depth >= 0)
27121 		ielem = vctxt->inode;
27122 	    else
27123 		ielem = NULL;
27124 	} else if ((nodeType == XML_TEXT_NODE) ||
27125 	    (nodeType == XML_CDATA_SECTION_NODE) ||
27126 	    (nodeType == WHTSP) ||
27127 	    (nodeType == SIGN_WHTSP)) {
27128 	    /*
27129 	    * Process character content.
27130 	    */
27131 	    xmlChar *value;
27132 
27133 	    if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
27134 		nodeType = XML_TEXT_NODE;
27135 
27136 	    value = xmlTextReaderValue(vctxt->reader);
27137 	    ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
27138 		-1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
27139 	    if (! consumed)
27140 		xmlFree(value);
27141 	    if (ret == -1) {
27142 		VERROR_INT("xmlSchemaVReaderWalk",
27143 		    "calling xmlSchemaVPushText()");
27144 		goto internal_error;
27145 	    }
27146 	} else if ((nodeType == XML_ENTITY_NODE) ||
27147 	    (nodeType == XML_ENTITY_REF_NODE)) {
27148 	    /*
27149 	    * VAL TODO: What to do with entities?
27150 	    */
27151 	    TODO
27152 	}
27153 	/*
27154 	* Read next node.
27155 	*/
27156 	ret = xmlTextReaderRead(vctxt->reader);
27157     } while (ret == 1);
27158 
27159 exit:
27160     return (ret);
27161 internal_error:
27162     return (-1);
27163 }
27164 #endif
27165 
27166 /************************************************************************
27167  * 									*
27168  * 			SAX validation handlers				*
27169  * 									*
27170  ************************************************************************/
27171 
27172 /*
27173 * Process text content.
27174 */
27175 static void
xmlSchemaSAXHandleText(void * ctx,const xmlChar * ch,int len)27176 xmlSchemaSAXHandleText(void *ctx,
27177 		       const xmlChar * ch,
27178 		       int len)
27179 {
27180     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27181 
27182     if (vctxt->depth < 0)
27183 	return;
27184     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27185 	return;
27186     if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27187 	vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27188     if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
27189 	XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27190 	VERROR_INT("xmlSchemaSAXHandleCDataSection",
27191 	    "calling xmlSchemaVPushText()");
27192 	vctxt->err = -1;
27193 	xmlStopParser(vctxt->parserCtxt);
27194     }
27195 }
27196 
27197 /*
27198 * Process CDATA content.
27199 */
27200 static void
xmlSchemaSAXHandleCDataSection(void * ctx,const xmlChar * ch,int len)27201 xmlSchemaSAXHandleCDataSection(void *ctx,
27202 			     const xmlChar * ch,
27203 			     int len)
27204 {
27205     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27206 
27207     if (vctxt->depth < 0)
27208 	return;
27209     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27210 	return;
27211     if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27212 	vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27213     if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
27214 	XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27215 	VERROR_INT("xmlSchemaSAXHandleCDataSection",
27216 	    "calling xmlSchemaVPushText()");
27217 	vctxt->err = -1;
27218 	xmlStopParser(vctxt->parserCtxt);
27219     }
27220 }
27221 
27222 static void
xmlSchemaSAXHandleReference(void * ctx ATTRIBUTE_UNUSED,const xmlChar * name ATTRIBUTE_UNUSED)27223 xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
27224 			    const xmlChar * name ATTRIBUTE_UNUSED)
27225 {
27226     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27227 
27228     if (vctxt->depth < 0)
27229 	return;
27230     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27231 	return;
27232     /* SAX VAL TODO: What to do here? */
27233     TODO
27234 }
27235 
27236 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)27237 xmlSchemaSAXHandleStartElementNs(void *ctx,
27238 				 const xmlChar * localname,
27239 				 const xmlChar * prefix ATTRIBUTE_UNUSED,
27240 				 const xmlChar * URI,
27241 				 int nb_namespaces,
27242 				 const xmlChar ** namespaces,
27243 				 int nb_attributes,
27244 				 int nb_defaulted ATTRIBUTE_UNUSED,
27245 				 const xmlChar ** attributes)
27246 {
27247     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27248     int ret;
27249     xmlSchemaNodeInfoPtr ielem;
27250     int i, j;
27251 
27252     /*
27253     * SAX VAL TODO: What to do with nb_defaulted?
27254     */
27255     /*
27256     * Skip elements if inside a "skip" wildcard or invalid.
27257     */
27258     vctxt->depth++;
27259     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27260 	return;
27261     /*
27262     * Push the element.
27263     */
27264     if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27265 	VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27266 	    "calling xmlSchemaValidatorPushElem()");
27267 	goto internal_error;
27268     }
27269     ielem = vctxt->inode;
27270     /*
27271     * TODO: Is this OK?
27272     */
27273     ielem->nodeLine = xmlSAX2GetLineNumber(vctxt->parserCtxt);
27274     ielem->localName = localname;
27275     ielem->nsName = URI;
27276     ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27277     /*
27278     * Register namespaces on the elem info.
27279     */
27280     if (nb_namespaces != 0) {
27281 	/*
27282 	* Although the parser builds its own namespace list,
27283 	* we have no access to it, so we'll use an own one.
27284 	*/
27285         for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
27286 	    /*
27287 	    * Store prefix and namespace name.
27288 	    */
27289 	    if (ielem->nsBindings == NULL) {
27290 		ielem->nsBindings =
27291 		    (const xmlChar **) xmlMalloc(10 *
27292 			sizeof(const xmlChar *));
27293 		if (ielem->nsBindings == NULL) {
27294 		    xmlSchemaVErrMemory(vctxt,
27295 			"allocating namespace bindings for SAX validation",
27296 			NULL);
27297 		    goto internal_error;
27298 		}
27299 		ielem->nbNsBindings = 0;
27300 		ielem->sizeNsBindings = 5;
27301 	    } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
27302 		ielem->sizeNsBindings *= 2;
27303 		ielem->nsBindings =
27304 		    (const xmlChar **) xmlRealloc(
27305 			(void *) ielem->nsBindings,
27306 			ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
27307 		if (ielem->nsBindings == NULL) {
27308 		    xmlSchemaVErrMemory(vctxt,
27309 			"re-allocating namespace bindings for SAX validation",
27310 			NULL);
27311 		    goto internal_error;
27312 		}
27313 	    }
27314 
27315 	    ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
27316 	    if (namespaces[j+1][0] == 0) {
27317 		/*
27318 		* Handle xmlns="".
27319 		*/
27320 		ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
27321 	    } else
27322 		ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
27323 		    namespaces[j+1];
27324 	    ielem->nbNsBindings++;
27325 	}
27326     }
27327     /*
27328     * Register attributes.
27329     * SAX VAL TODO: We are not adding namespace declaration
27330     * attributes yet.
27331     */
27332     if (nb_attributes != 0) {
27333 	xmlChar *value;
27334 
27335         for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
27336 	    /*
27337 	    * Duplicate the value.
27338 	    */
27339 	    value = xmlStrndup(attributes[j+3],
27340 		attributes[j+4] - attributes[j+3]);
27341 	    /*
27342 	    * TODO: Set the node line.
27343 	    */
27344 	    ret = xmlSchemaValidatorPushAttribute(vctxt,
27345 		NULL, ielem->nodeLine, attributes[j], attributes[j+2], 0,
27346 		value, 1);
27347 	    if (ret == -1) {
27348 		VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27349 		    "calling xmlSchemaValidatorPushAttribute()");
27350 		goto internal_error;
27351 	    }
27352 	}
27353     }
27354     /*
27355     * Validate the element.
27356     */
27357     ret = xmlSchemaValidateElem(vctxt);
27358     if (ret != 0) {
27359 	if (ret == -1) {
27360 	    VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27361 		"calling xmlSchemaValidateElem()");
27362 	    goto internal_error;
27363 	}
27364 	goto exit;
27365     }
27366 
27367 exit:
27368     return;
27369 internal_error:
27370     vctxt->err = -1;
27371     xmlStopParser(vctxt->parserCtxt);
27372     return;
27373 }
27374 
27375 static void
xmlSchemaSAXHandleEndElementNs(void * ctx,const xmlChar * localname ATTRIBUTE_UNUSED,const xmlChar * prefix ATTRIBUTE_UNUSED,const xmlChar * URI ATTRIBUTE_UNUSED)27376 xmlSchemaSAXHandleEndElementNs(void *ctx,
27377 			       const xmlChar * localname ATTRIBUTE_UNUSED,
27378 			       const xmlChar * prefix ATTRIBUTE_UNUSED,
27379 			       const xmlChar * URI ATTRIBUTE_UNUSED)
27380 {
27381     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27382     int res;
27383 
27384     /*
27385     * Skip elements if inside a "skip" wildcard or if invalid.
27386     */
27387     if (vctxt->skipDepth != -1) {
27388 	if (vctxt->depth > vctxt->skipDepth) {
27389 	    vctxt->depth--;
27390 	    return;
27391 	} else
27392 	    vctxt->skipDepth = -1;
27393     }
27394     /*
27395     * SAX VAL TODO: Just a temporary check.
27396     */
27397     if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
27398 	(!xmlStrEqual(vctxt->inode->nsName, URI))) {
27399 	VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27400 	    "elem pop mismatch");
27401     }
27402     res = xmlSchemaValidatorPopElem(vctxt);
27403     if (res != 0) {
27404 	if (res < 0) {
27405 	    VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27406 		"calling xmlSchemaValidatorPopElem()");
27407 	    goto internal_error;
27408 	}
27409 	goto exit;
27410     }
27411 exit:
27412     return;
27413 internal_error:
27414     vctxt->err = -1;
27415     xmlStopParser(vctxt->parserCtxt);
27416     return;
27417 }
27418 
27419 /************************************************************************
27420  * 									*
27421  * 			Validation interfaces				*
27422  * 									*
27423  ************************************************************************/
27424 
27425 /**
27426  * xmlSchemaNewValidCtxt:
27427  * @schema:  a precompiled XML Schemas
27428  *
27429  * Create an XML Schemas validation context based on the given schema.
27430  *
27431  * Returns the validation context or NULL in case of error
27432  */
27433 xmlSchemaValidCtxtPtr
xmlSchemaNewValidCtxt(xmlSchemaPtr schema)27434 xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
27435 {
27436     xmlSchemaValidCtxtPtr ret;
27437 
27438     ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
27439     if (ret == NULL) {
27440         xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
27441         return (NULL);
27442     }
27443     memset(ret, 0, sizeof(xmlSchemaValidCtxt));
27444     ret->type = XML_SCHEMA_CTXT_VALIDATOR;
27445     ret->dict = xmlDictCreate();
27446     ret->nodeQNames = xmlSchemaItemListCreate();
27447     ret->schema = schema;
27448     return (ret);
27449 }
27450 
27451 /**
27452  * xmlSchemaClearValidCtxt:
27453  * @ctxt: the schema validation context
27454  *
27455  * Free the resources associated to the schema validation context;
27456  * leaves some fields alive intended for reuse of the context.
27457  */
27458 static void
xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)27459 xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
27460 {
27461     if (vctxt == NULL)
27462         return;
27463 
27464     /*
27465     * TODO: Should we clear the flags?
27466     *   Might be problematic if one reuses the context
27467     *   and assumes that the options remain the same.
27468     */
27469     vctxt->flags = 0;
27470     vctxt->validationRoot = NULL;
27471     vctxt->doc = NULL;
27472 #ifdef LIBXML_READER_ENABLED
27473     vctxt->reader = NULL;
27474 #endif
27475     vctxt->hasKeyrefs = 0;
27476 
27477     if (vctxt->value != NULL) {
27478         xmlSchemaFreeValue(vctxt->value);
27479 	vctxt->value = NULL;
27480     }
27481     /*
27482     * Augmented IDC information.
27483     */
27484     if (vctxt->aidcs != NULL) {
27485 	xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
27486 	do {
27487 	    next = cur->next;
27488 	    xmlFree(cur);
27489 	    cur = next;
27490 	} while (cur != NULL);
27491 	vctxt->aidcs = NULL;
27492     }
27493     if (vctxt->idcMatcherCache != NULL) {
27494 	xmlSchemaIDCMatcherPtr matcher = vctxt->idcMatcherCache, tmp;
27495 
27496 	while (matcher) {
27497 	    tmp = matcher;
27498 	    matcher = matcher->nextCached;
27499 	    xmlSchemaIDCFreeMatcherList(tmp);
27500 	}
27501 	vctxt->idcMatcherCache = NULL;
27502     }
27503 
27504 
27505     if (vctxt->idcNodes != NULL) {
27506 	int i;
27507 	xmlSchemaPSVIIDCNodePtr item;
27508 
27509 	for (i = 0; i < vctxt->nbIdcNodes; i++) {
27510 	    item = vctxt->idcNodes[i];
27511 	    xmlFree(item->keys);
27512 	    xmlFree(item);
27513 	}
27514 	xmlFree(vctxt->idcNodes);
27515 	vctxt->idcNodes = NULL;
27516 	vctxt->nbIdcNodes = 0;
27517 	vctxt->sizeIdcNodes = 0;
27518     }
27519     /*
27520     * Note that we won't delete the XPath state pool here.
27521     */
27522     if (vctxt->xpathStates != NULL) {
27523 	xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
27524 	vctxt->xpathStates = NULL;
27525     }
27526     /*
27527     * Attribute info.
27528     */
27529     if (vctxt->nbAttrInfos != 0) {
27530 	xmlSchemaClearAttrInfos(vctxt);
27531     }
27532     /*
27533     * Element info.
27534     */
27535     if (vctxt->elemInfos != NULL) {
27536 	int i;
27537 	xmlSchemaNodeInfoPtr ei;
27538 
27539 	for (i = 0; i < vctxt->sizeElemInfos; i++) {
27540 	    ei = vctxt->elemInfos[i];
27541 	    if (ei == NULL)
27542 		break;
27543 	    xmlSchemaClearElemInfo(vctxt, ei);
27544 	}
27545     }
27546     xmlSchemaItemListClear(vctxt->nodeQNames);
27547     /* Recreate the dict. */
27548     xmlDictFree(vctxt->dict);
27549     /*
27550     * TODO: Is is save to recreate it? Do we have a scenario
27551     * where the user provides the dict?
27552     */
27553     vctxt->dict = xmlDictCreate();
27554 }
27555 
27556 /**
27557  * xmlSchemaFreeValidCtxt:
27558  * @ctxt:  the schema validation context
27559  *
27560  * Free the resources associated to the schema validation context
27561  */
27562 void
xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)27563 xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
27564 {
27565     if (ctxt == NULL)
27566         return;
27567     if (ctxt->value != NULL)
27568         xmlSchemaFreeValue(ctxt->value);
27569     if (ctxt->pctxt != NULL)
27570 	xmlSchemaFreeParserCtxt(ctxt->pctxt);
27571     if (ctxt->idcNodes != NULL) {
27572 	int i;
27573 	xmlSchemaPSVIIDCNodePtr item;
27574 
27575 	for (i = 0; i < ctxt->nbIdcNodes; i++) {
27576 	    item = ctxt->idcNodes[i];
27577 	    xmlFree(item->keys);
27578 	    xmlFree(item);
27579 	}
27580 	xmlFree(ctxt->idcNodes);
27581     }
27582     if (ctxt->idcKeys != NULL) {
27583 	int i;
27584 	for (i = 0; i < ctxt->nbIdcKeys; i++)
27585 	    xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
27586 	xmlFree(ctxt->idcKeys);
27587     }
27588 
27589     if (ctxt->xpathStates != NULL) {
27590 	xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
27591 	ctxt->xpathStates = NULL;
27592     }
27593     if (ctxt->xpathStatePool != NULL) {
27594 	xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
27595 	ctxt->xpathStatePool = NULL;
27596     }
27597 
27598     /*
27599     * Augmented IDC information.
27600     */
27601     if (ctxt->aidcs != NULL) {
27602 	xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
27603 	do {
27604 	    next = cur->next;
27605 	    xmlFree(cur);
27606 	    cur = next;
27607 	} while (cur != NULL);
27608     }
27609     if (ctxt->attrInfos != NULL) {
27610 	int i;
27611 	xmlSchemaAttrInfoPtr attr;
27612 
27613 	/* Just a paranoid call to the cleanup. */
27614 	if (ctxt->nbAttrInfos != 0)
27615 	    xmlSchemaClearAttrInfos(ctxt);
27616 	for (i = 0; i < ctxt->sizeAttrInfos; i++) {
27617 	    attr = ctxt->attrInfos[i];
27618 	    xmlFree(attr);
27619 	}
27620 	xmlFree(ctxt->attrInfos);
27621     }
27622     if (ctxt->elemInfos != NULL) {
27623 	int i;
27624 	xmlSchemaNodeInfoPtr ei;
27625 
27626 	for (i = 0; i < ctxt->sizeElemInfos; i++) {
27627 	    ei = ctxt->elemInfos[i];
27628 	    if (ei == NULL)
27629 		break;
27630 	    xmlSchemaClearElemInfo(ctxt, ei);
27631 	    xmlFree(ei);
27632 	}
27633 	xmlFree(ctxt->elemInfos);
27634     }
27635     if (ctxt->nodeQNames != NULL)
27636 	xmlSchemaItemListFree(ctxt->nodeQNames);
27637     if (ctxt->dict != NULL)
27638 	xmlDictFree(ctxt->dict);
27639     xmlFree(ctxt);
27640 }
27641 
27642 /**
27643  * xmlSchemaIsValid:
27644  * @ctxt: the schema validation context
27645  *
27646  * Check if any error was detected during validation.
27647  *
27648  * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
27649  *         of internal error.
27650  */
27651 int
xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)27652 xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
27653 {
27654     if (ctxt == NULL)
27655         return(-1);
27656     return(ctxt->err == 0);
27657 }
27658 
27659 /**
27660  * xmlSchemaSetValidErrors:
27661  * @ctxt:  a schema validation context
27662  * @err:  the error function
27663  * @warn: the warning function
27664  * @ctx: the functions context
27665  *
27666  * Set the error and warning callback informations
27667  */
27668 void
xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,xmlSchemaValidityErrorFunc err,xmlSchemaValidityWarningFunc warn,void * ctx)27669 xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
27670                         xmlSchemaValidityErrorFunc err,
27671                         xmlSchemaValidityWarningFunc warn, void *ctx)
27672 {
27673     if (ctxt == NULL)
27674         return;
27675     ctxt->error = err;
27676     ctxt->warning = warn;
27677     ctxt->errCtxt = ctx;
27678     if (ctxt->pctxt != NULL)
27679 	xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
27680 }
27681 
27682 /**
27683  * xmlSchemaSetValidStructuredErrors:
27684  * @ctxt:  a schema validation context
27685  * @serror:  the structured error function
27686  * @ctx: the functions context
27687  *
27688  * Set the structured error callback
27689  */
27690 void
xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,xmlStructuredErrorFunc serror,void * ctx)27691 xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
27692 				  xmlStructuredErrorFunc serror, void *ctx)
27693 {
27694     if (ctxt == NULL)
27695         return;
27696 	ctxt->serror = serror;
27697     ctxt->error = NULL;
27698     ctxt->warning = NULL;
27699     ctxt->errCtxt = ctx;
27700     if (ctxt->pctxt != NULL)
27701 	xmlSchemaSetParserStructuredErrors(ctxt->pctxt, serror, ctx);
27702 }
27703 
27704 /**
27705  * xmlSchemaGetValidErrors:
27706  * @ctxt: a XML-Schema validation context
27707  * @err: the error function result
27708  * @warn: the warning function result
27709  * @ctx: the functions context result
27710  *
27711  * Get the error and warning callback informations
27712  *
27713  * Returns -1 in case of error and 0 otherwise
27714  */
27715 int
xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,xmlSchemaValidityErrorFunc * err,xmlSchemaValidityWarningFunc * warn,void ** ctx)27716 xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
27717 			xmlSchemaValidityErrorFunc * err,
27718 			xmlSchemaValidityWarningFunc * warn, void **ctx)
27719 {
27720 	if (ctxt == NULL)
27721 		return (-1);
27722 	if (err != NULL)
27723 		*err = ctxt->error;
27724 	if (warn != NULL)
27725 		*warn = ctxt->warning;
27726 	if (ctx != NULL)
27727 		*ctx = ctxt->errCtxt;
27728 	return (0);
27729 }
27730 
27731 
27732 /**
27733  * xmlSchemaSetValidOptions:
27734  * @ctxt:	a schema validation context
27735  * @options: a combination of xmlSchemaValidOption
27736  *
27737  * Sets the options to be used during the validation.
27738  *
27739  * Returns 0 in case of success, -1 in case of an
27740  * API error.
27741  */
27742 int
xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,int options)27743 xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
27744 			 int options)
27745 
27746 {
27747     int i;
27748 
27749     if (ctxt == NULL)
27750 	return (-1);
27751     /*
27752     * WARNING: Change the start value if adding to the
27753     * xmlSchemaValidOption.
27754     * TODO: Is there an other, more easy to maintain,
27755     * way?
27756     */
27757     for (i = 1; i < (int) sizeof(int) * 8; i++) {
27758         if (options & 1<<i)
27759 	    return (-1);
27760     }
27761     ctxt->options = options;
27762     return (0);
27763 }
27764 
27765 /**
27766  * xmlSchemaValidCtxtGetOptions:
27767  * @ctxt: a schema validation context
27768  *
27769  * Get the validation context options.
27770  *
27771  * Returns the option combination or -1 on error.
27772  */
27773 int
xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)27774 xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
27775 
27776 {
27777     if (ctxt == NULL)
27778 	return (-1);
27779     else
27780 	return (ctxt->options);
27781 }
27782 
27783 static int
xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)27784 xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
27785 {
27786     xmlAttrPtr attr;
27787     int ret = 0;
27788     xmlSchemaNodeInfoPtr ielem = NULL;
27789     xmlNodePtr node, valRoot;
27790     const xmlChar *nsName;
27791 
27792     /* DOC VAL TODO: Move this to the start function. */
27793     valRoot = xmlDocGetRootElement(vctxt->doc);
27794     if (valRoot == NULL) {
27795 	/* VAL TODO: Error code? */
27796 	VERROR(1, NULL, "The document has no document element");
27797 	return (1);
27798     }
27799     vctxt->depth = -1;
27800     vctxt->validationRoot = valRoot;
27801     node = valRoot;
27802     while (node != NULL) {
27803 	if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27804 	    goto next_sibling;
27805 	if (node->type == XML_ELEMENT_NODE) {
27806 
27807 	    /*
27808 	    * Init the node-info.
27809 	    */
27810 	    vctxt->depth++;
27811 	    if (xmlSchemaValidatorPushElem(vctxt) == -1)
27812 		goto internal_error;
27813 	    ielem = vctxt->inode;
27814 	    ielem->node = node;
27815 	    ielem->nodeLine = node->line;
27816 	    ielem->localName = node->name;
27817 	    if (node->ns != NULL)
27818 		ielem->nsName = node->ns->href;
27819 	    ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27820 	    /*
27821 	    * Register attributes.
27822 	    * DOC VAL TODO: We do not register namespace declaration
27823 	    * attributes yet.
27824 	    */
27825 	    vctxt->nbAttrInfos = 0;
27826 	    if (node->properties != NULL) {
27827 		attr = node->properties;
27828 		do {
27829 		    if (attr->ns != NULL)
27830 			nsName = attr->ns->href;
27831 		    else
27832 			nsName = NULL;
27833 		    ret = xmlSchemaValidatorPushAttribute(vctxt,
27834 			(xmlNodePtr) attr,
27835 			/*
27836 			* Note that we give it the line number of the
27837 			* parent element.
27838 			*/
27839 			ielem->nodeLine,
27840 			attr->name, nsName, 0,
27841 			xmlNodeListGetString(attr->doc, attr->children, 1), 1);
27842 		    if (ret == -1) {
27843 			VERROR_INT("xmlSchemaDocWalk",
27844 			    "calling xmlSchemaValidatorPushAttribute()");
27845 			goto internal_error;
27846 		    }
27847 		    attr = attr->next;
27848 		} while (attr);
27849 	    }
27850 	    /*
27851 	    * Validate the element.
27852 	    */
27853 	    ret = xmlSchemaValidateElem(vctxt);
27854 	    if (ret != 0) {
27855 		if (ret == -1) {
27856 		    VERROR_INT("xmlSchemaDocWalk",
27857 			"calling xmlSchemaValidateElem()");
27858 		    goto internal_error;
27859 		}
27860 		/*
27861 		* Don't stop validation; just skip the content
27862 		* of this element.
27863 		*/
27864 		goto leave_node;
27865 	    }
27866 	    if ((vctxt->skipDepth != -1) &&
27867 		(vctxt->depth >= vctxt->skipDepth))
27868 		goto leave_node;
27869 	} else if ((node->type == XML_TEXT_NODE) ||
27870 	    (node->type == XML_CDATA_SECTION_NODE)) {
27871 	    /*
27872 	    * Process character content.
27873 	    */
27874 	    if ((ielem != NULL) && (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY))
27875 		ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27876 	    ret = xmlSchemaVPushText(vctxt, node->type, node->content,
27877 		-1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
27878 	    if (ret < 0) {
27879 		VERROR_INT("xmlSchemaVDocWalk",
27880 		    "calling xmlSchemaVPushText()");
27881 		goto internal_error;
27882 	    }
27883 	    /*
27884 	    * DOC VAL TODO: Should we skip further validation of the
27885 	    * element content here?
27886 	    */
27887 	} else if ((node->type == XML_ENTITY_NODE) ||
27888 	    (node->type == XML_ENTITY_REF_NODE)) {
27889 	    /*
27890 	    * DOC VAL TODO: What to do with entities?
27891 	    */
27892 	    VERROR_INT("xmlSchemaVDocWalk",
27893 		"there is at least one entity reference in the node-tree "
27894 		"currently being validated. Processing of entities with "
27895 		"this XML Schema processor is not supported (yet). Please "
27896 		"substitute entities before validation.");
27897 	    goto internal_error;
27898 	} else {
27899 	    goto leave_node;
27900 	    /*
27901 	    * DOC VAL TODO: XInclude nodes, etc.
27902 	    */
27903 	}
27904 	/*
27905 	* Walk the doc.
27906 	*/
27907 	if (node->children != NULL) {
27908 	    node = node->children;
27909 	    continue;
27910 	}
27911 leave_node:
27912 	if (node->type == XML_ELEMENT_NODE) {
27913 	    /*
27914 	    * Leaving the scope of an element.
27915 	    */
27916 	    if (node != vctxt->inode->node) {
27917 		VERROR_INT("xmlSchemaVDocWalk",
27918 		    "element position mismatch");
27919 		goto internal_error;
27920 	    }
27921 	    ret = xmlSchemaValidatorPopElem(vctxt);
27922 	    if (ret != 0) {
27923 		if (ret < 0) {
27924 		    VERROR_INT("xmlSchemaVDocWalk",
27925 			"calling xmlSchemaValidatorPopElem()");
27926 		    goto internal_error;
27927 		}
27928 	    }
27929 	    if (node == valRoot)
27930 		goto exit;
27931 	}
27932 next_sibling:
27933 	if (node->next != NULL)
27934 	    node = node->next;
27935 	else {
27936 	    node = node->parent;
27937 	    goto leave_node;
27938 	}
27939     }
27940 
27941 exit:
27942     return (ret);
27943 internal_error:
27944     return (-1);
27945 }
27946 
27947 static int
xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt)27948 xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
27949     /*
27950     * Some initialization.
27951     */
27952     vctxt->err = 0;
27953     vctxt->nberrors = 0;
27954     vctxt->depth = -1;
27955     vctxt->skipDepth = -1;
27956     vctxt->xsiAssemble = 0;
27957     vctxt->hasKeyrefs = 0;
27958 #ifdef ENABLE_IDC_NODE_TABLES_TEST
27959     vctxt->createIDCNodeTables = 1;
27960 #else
27961     vctxt->createIDCNodeTables = 0;
27962 #endif
27963     /*
27964     * Create a schema + parser if necessary.
27965     */
27966     if (vctxt->schema == NULL) {
27967 	xmlSchemaParserCtxtPtr pctxt;
27968 
27969 	vctxt->xsiAssemble = 1;
27970 	/*
27971 	* If not schema was given then we will create a schema
27972 	* dynamically using XSI schema locations.
27973 	*
27974 	* Create the schema parser context.
27975 	*/
27976 	if ((vctxt->pctxt == NULL) &&
27977 	   (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
27978 	   return (-1);
27979 	pctxt = vctxt->pctxt;
27980 	pctxt->xsiAssemble = 1;
27981 	/*
27982 	* Create the schema.
27983 	*/
27984 	vctxt->schema = xmlSchemaNewSchema(pctxt);
27985 	if (vctxt->schema == NULL)
27986 	    return (-1);
27987 	/*
27988 	* Create the schema construction context.
27989 	*/
27990 	pctxt->constructor = xmlSchemaConstructionCtxtCreate(pctxt->dict);
27991 	if (pctxt->constructor == NULL)
27992 	    return(-1);
27993 	pctxt->constructor->mainSchema = vctxt->schema;
27994 	/*
27995 	* Take ownership of the constructor to be able to free it.
27996 	*/
27997 	pctxt->ownsConstructor = 1;
27998     }
27999     /*
28000     * Augment the IDC definitions for the main schema and all imported ones
28001     * NOTE: main schema if the first in the imported list
28002     */
28003     xmlHashScan(vctxt->schema->schemasImports,(xmlHashScanner)xmlSchemaAugmentImportedIDC, vctxt);
28004 
28005     return(0);
28006 }
28007 
28008 static void
xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt)28009 xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
28010     if (vctxt->xsiAssemble) {
28011 	if (vctxt->schema != NULL) {
28012 	    xmlSchemaFree(vctxt->schema);
28013 	    vctxt->schema = NULL;
28014 	}
28015     }
28016     xmlSchemaClearValidCtxt(vctxt);
28017 }
28018 
28019 static int
xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)28020 xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
28021 {
28022     int ret = 0;
28023 
28024     if (xmlSchemaPreRun(vctxt) < 0)
28025         return(-1);
28026 
28027     if (vctxt->doc != NULL) {
28028 	/*
28029 	 * Tree validation.
28030 	 */
28031 	ret = xmlSchemaVDocWalk(vctxt);
28032 #ifdef LIBXML_READER_ENABLED
28033     } else if (vctxt->reader != NULL) {
28034 	/*
28035 	 * XML Reader validation.
28036 	 */
28037 #ifdef XML_SCHEMA_READER_ENABLED
28038 	ret = xmlSchemaVReaderWalk(vctxt);
28039 #endif
28040 #endif
28041     } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
28042 	/*
28043 	 * SAX validation.
28044 	 */
28045 	ret = xmlParseDocument(vctxt->parserCtxt);
28046     } else {
28047 	VERROR_INT("xmlSchemaVStart",
28048 	    "no instance to validate");
28049 	ret = -1;
28050     }
28051 
28052     xmlSchemaPostRun(vctxt);
28053     if (ret == 0)
28054 	ret = vctxt->err;
28055     return (ret);
28056 }
28057 
28058 /**
28059  * xmlSchemaValidateOneElement:
28060  * @ctxt:  a schema validation context
28061  * @elem:  an element node
28062  *
28063  * Validate a branch of a tree, starting with the given @elem.
28064  *
28065  * Returns 0 if the element and its subtree is valid, a positive error
28066  * code number otherwise and -1 in case of an internal or API error.
28067  */
28068 int
xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt,xmlNodePtr elem)28069 xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
28070 {
28071     if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
28072 	return (-1);
28073 
28074     if (ctxt->schema == NULL)
28075 	return (-1);
28076 
28077     ctxt->doc = elem->doc;
28078     ctxt->node = elem;
28079     ctxt->validationRoot = elem;
28080     return(xmlSchemaVStart(ctxt));
28081 }
28082 
28083 /**
28084  * xmlSchemaValidateDoc:
28085  * @ctxt:  a schema validation context
28086  * @doc:  a parsed document tree
28087  *
28088  * Validate a document tree in memory.
28089  *
28090  * Returns 0 if the document is schemas valid, a positive error code
28091  *     number otherwise and -1 in case of internal or API error.
28092  */
28093 int
xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt,xmlDocPtr doc)28094 xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
28095 {
28096     if ((ctxt == NULL) || (doc == NULL))
28097         return (-1);
28098 
28099     ctxt->doc = doc;
28100     ctxt->node = xmlDocGetRootElement(doc);
28101     if (ctxt->node == NULL) {
28102         xmlSchemaCustomErr(ACTXT_CAST ctxt,
28103 	    XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
28104 	    (xmlNodePtr) doc, NULL,
28105 	    "The document has no document element", NULL, NULL);
28106         return (ctxt->err);
28107     }
28108     ctxt->validationRoot = ctxt->node;
28109     return (xmlSchemaVStart(ctxt));
28110 }
28111 
28112 
28113 /************************************************************************
28114  * 									*
28115  * 		Function and data for SAX streaming API			*
28116  * 									*
28117  ************************************************************************/
28118 typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
28119 typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
28120 
28121 struct _xmlSchemaSplitSAXData {
28122     xmlSAXHandlerPtr      user_sax;
28123     void                 *user_data;
28124     xmlSchemaValidCtxtPtr ctxt;
28125     xmlSAXHandlerPtr      schemas_sax;
28126 };
28127 
28128 #define XML_SAX_PLUG_MAGIC 0xdc43ba21
28129 
28130 struct _xmlSchemaSAXPlug {
28131     unsigned int magic;
28132 
28133     /* the original callbacks informations */
28134     xmlSAXHandlerPtr     *user_sax_ptr;
28135     xmlSAXHandlerPtr      user_sax;
28136     void                **user_data_ptr;
28137     void                 *user_data;
28138 
28139     /* the block plugged back and validation informations */
28140     xmlSAXHandler         schemas_sax;
28141     xmlSchemaValidCtxtPtr ctxt;
28142 };
28143 
28144 /* All those functions just bounces to the user provided SAX handlers */
28145 static void
internalSubsetSplit(void * ctx,const xmlChar * name,const xmlChar * ExternalID,const xmlChar * SystemID)28146 internalSubsetSplit(void *ctx, const xmlChar *name,
28147 	       const xmlChar *ExternalID, const xmlChar *SystemID)
28148 {
28149     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28150     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28151         (ctxt->user_sax->internalSubset != NULL))
28152 	ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
28153 	                               SystemID);
28154 }
28155 
28156 static int
isStandaloneSplit(void * ctx)28157 isStandaloneSplit(void *ctx)
28158 {
28159     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28160     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28161         (ctxt->user_sax->isStandalone != NULL))
28162 	return(ctxt->user_sax->isStandalone(ctxt->user_data));
28163     return(0);
28164 }
28165 
28166 static int
hasInternalSubsetSplit(void * ctx)28167 hasInternalSubsetSplit(void *ctx)
28168 {
28169     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28170     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28171         (ctxt->user_sax->hasInternalSubset != NULL))
28172 	return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
28173     return(0);
28174 }
28175 
28176 static int
hasExternalSubsetSplit(void * ctx)28177 hasExternalSubsetSplit(void *ctx)
28178 {
28179     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28180     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28181         (ctxt->user_sax->hasExternalSubset != NULL))
28182 	return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
28183     return(0);
28184 }
28185 
28186 static void
externalSubsetSplit(void * ctx,const xmlChar * name,const xmlChar * ExternalID,const xmlChar * SystemID)28187 externalSubsetSplit(void *ctx, const xmlChar *name,
28188 	       const xmlChar *ExternalID, const xmlChar *SystemID)
28189 {
28190     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28191     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28192         (ctxt->user_sax->externalSubset != NULL))
28193 	ctxt->user_sax->externalSubset(ctxt->user_data, name, ExternalID,
28194 	                               SystemID);
28195 }
28196 
28197 static xmlParserInputPtr
resolveEntitySplit(void * ctx,const xmlChar * publicId,const xmlChar * systemId)28198 resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
28199 {
28200     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28201     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28202         (ctxt->user_sax->resolveEntity != NULL))
28203 	return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
28204 	                                     systemId));
28205     return(NULL);
28206 }
28207 
28208 static xmlEntityPtr
getEntitySplit(void * ctx,const xmlChar * name)28209 getEntitySplit(void *ctx, const xmlChar *name)
28210 {
28211     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28212     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28213         (ctxt->user_sax->getEntity != NULL))
28214 	return(ctxt->user_sax->getEntity(ctxt->user_data, name));
28215     return(NULL);
28216 }
28217 
28218 static xmlEntityPtr
getParameterEntitySplit(void * ctx,const xmlChar * name)28219 getParameterEntitySplit(void *ctx, const xmlChar *name)
28220 {
28221     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28222     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28223         (ctxt->user_sax->getParameterEntity != NULL))
28224 	return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
28225     return(NULL);
28226 }
28227 
28228 
28229 static void
entityDeclSplit(void * ctx,const xmlChar * name,int type,const xmlChar * publicId,const xmlChar * systemId,xmlChar * content)28230 entityDeclSplit(void *ctx, const xmlChar *name, int type,
28231           const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
28232 {
28233     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28234     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28235         (ctxt->user_sax->entityDecl != NULL))
28236 	ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
28237 	                           systemId, content);
28238 }
28239 
28240 static void
attributeDeclSplit(void * ctx,const xmlChar * elem,const xmlChar * name,int type,int def,const xmlChar * defaultValue,xmlEnumerationPtr tree)28241 attributeDeclSplit(void *ctx, const xmlChar * elem,
28242                    const xmlChar * name, int type, int def,
28243                    const xmlChar * defaultValue, xmlEnumerationPtr tree)
28244 {
28245     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28246     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28247         (ctxt->user_sax->attributeDecl != NULL)) {
28248 	ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
28249 	                              def, defaultValue, tree);
28250     } else {
28251 	xmlFreeEnumeration(tree);
28252     }
28253 }
28254 
28255 static void
elementDeclSplit(void * ctx,const xmlChar * name,int type,xmlElementContentPtr content)28256 elementDeclSplit(void *ctx, const xmlChar *name, int type,
28257 	    xmlElementContentPtr content)
28258 {
28259     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28260     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28261         (ctxt->user_sax->elementDecl != NULL))
28262 	ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
28263 }
28264 
28265 static void
notationDeclSplit(void * ctx,const xmlChar * name,const xmlChar * publicId,const xmlChar * systemId)28266 notationDeclSplit(void *ctx, const xmlChar *name,
28267 	     const xmlChar *publicId, const xmlChar *systemId)
28268 {
28269     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28270     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28271         (ctxt->user_sax->notationDecl != NULL))
28272 	ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
28273 	                             systemId);
28274 }
28275 
28276 static void
unparsedEntityDeclSplit(void * ctx,const xmlChar * name,const xmlChar * publicId,const xmlChar * systemId,const xmlChar * notationName)28277 unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
28278 		   const xmlChar *publicId, const xmlChar *systemId,
28279 		   const xmlChar *notationName)
28280 {
28281     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28282     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28283         (ctxt->user_sax->unparsedEntityDecl != NULL))
28284 	ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
28285 	                                   systemId, notationName);
28286 }
28287 
28288 static void
setDocumentLocatorSplit(void * ctx,xmlSAXLocatorPtr loc)28289 setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
28290 {
28291     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28292     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28293         (ctxt->user_sax->setDocumentLocator != NULL))
28294 	ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
28295 }
28296 
28297 static void
startDocumentSplit(void * ctx)28298 startDocumentSplit(void *ctx)
28299 {
28300     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28301     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28302         (ctxt->user_sax->startDocument != NULL))
28303 	ctxt->user_sax->startDocument(ctxt->user_data);
28304 }
28305 
28306 static void
endDocumentSplit(void * ctx)28307 endDocumentSplit(void *ctx)
28308 {
28309     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28310     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28311         (ctxt->user_sax->endDocument != NULL))
28312 	ctxt->user_sax->endDocument(ctxt->user_data);
28313 }
28314 
28315 static void
processingInstructionSplit(void * ctx,const xmlChar * target,const xmlChar * data)28316 processingInstructionSplit(void *ctx, const xmlChar *target,
28317                       const xmlChar *data)
28318 {
28319     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28320     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28321         (ctxt->user_sax->processingInstruction != NULL))
28322 	ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
28323 }
28324 
28325 static void
commentSplit(void * ctx,const xmlChar * value)28326 commentSplit(void *ctx, const xmlChar *value)
28327 {
28328     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28329     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28330         (ctxt->user_sax->comment != NULL))
28331 	ctxt->user_sax->comment(ctxt->user_data, value);
28332 }
28333 
28334 /*
28335  * Varargs error callbacks to the user application, harder ...
28336  */
28337 
28338 static void XMLCDECL
warningSplit(void * ctx,const char * msg ATTRIBUTE_UNUSED,...)28339 warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28340     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28341     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28342         (ctxt->user_sax->warning != NULL)) {
28343 	TODO
28344     }
28345 }
28346 static void XMLCDECL
errorSplit(void * ctx,const char * msg ATTRIBUTE_UNUSED,...)28347 errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28348     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28349     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28350         (ctxt->user_sax->error != NULL)) {
28351 	TODO
28352     }
28353 }
28354 static void XMLCDECL
fatalErrorSplit(void * ctx,const char * msg ATTRIBUTE_UNUSED,...)28355 fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28356     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28357     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28358         (ctxt->user_sax->fatalError != NULL)) {
28359 	TODO
28360     }
28361 }
28362 
28363 /*
28364  * Those are function where both the user handler and the schemas handler
28365  * need to be called.
28366  */
28367 static void
charactersSplit(void * ctx,const xmlChar * ch,int len)28368 charactersSplit(void *ctx, const xmlChar *ch, int len)
28369 {
28370     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28371     if (ctxt == NULL)
28372         return;
28373     if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
28374 	ctxt->user_sax->characters(ctxt->user_data, ch, len);
28375     if (ctxt->ctxt != NULL)
28376 	xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28377 }
28378 
28379 static void
ignorableWhitespaceSplit(void * ctx,const xmlChar * ch,int len)28380 ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
28381 {
28382     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28383     if (ctxt == NULL)
28384         return;
28385     if ((ctxt->user_sax != NULL) &&
28386         (ctxt->user_sax->ignorableWhitespace != NULL))
28387 	ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
28388     if (ctxt->ctxt != NULL)
28389 	xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28390 }
28391 
28392 static void
cdataBlockSplit(void * ctx,const xmlChar * value,int len)28393 cdataBlockSplit(void *ctx, const xmlChar *value, int len)
28394 {
28395     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28396     if (ctxt == NULL)
28397         return;
28398     if ((ctxt->user_sax != NULL) &&
28399         (ctxt->user_sax->cdataBlock != NULL))
28400 	ctxt->user_sax->cdataBlock(ctxt->user_data, value, len);
28401     if (ctxt->ctxt != NULL)
28402 	xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
28403 }
28404 
28405 static void
referenceSplit(void * ctx,const xmlChar * name)28406 referenceSplit(void *ctx, const xmlChar *name)
28407 {
28408     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28409     if (ctxt == NULL)
28410         return;
28411     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28412         (ctxt->user_sax->reference != NULL))
28413 	ctxt->user_sax->reference(ctxt->user_data, name);
28414     if (ctxt->ctxt != NULL)
28415         xmlSchemaSAXHandleReference(ctxt->user_data, name);
28416 }
28417 
28418 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)28419 startElementNsSplit(void *ctx, const xmlChar * localname,
28420 		    const xmlChar * prefix, const xmlChar * URI,
28421 		    int nb_namespaces, const xmlChar ** namespaces,
28422 		    int nb_attributes, int nb_defaulted,
28423 		    const xmlChar ** attributes) {
28424     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28425     if (ctxt == NULL)
28426         return;
28427     if ((ctxt->user_sax != NULL) &&
28428         (ctxt->user_sax->startElementNs != NULL))
28429 	ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
28430 	                               URI, nb_namespaces, namespaces,
28431 				       nb_attributes, nb_defaulted,
28432 				       attributes);
28433     if (ctxt->ctxt != NULL)
28434 	xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
28435 	                                 URI, nb_namespaces, namespaces,
28436 					 nb_attributes, nb_defaulted,
28437 					 attributes);
28438 }
28439 
28440 static void
endElementNsSplit(void * ctx,const xmlChar * localname,const xmlChar * prefix,const xmlChar * URI)28441 endElementNsSplit(void *ctx, const xmlChar * localname,
28442 		    const xmlChar * prefix, const xmlChar * URI) {
28443     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28444     if (ctxt == NULL)
28445         return;
28446     if ((ctxt->user_sax != NULL) &&
28447         (ctxt->user_sax->endElementNs != NULL))
28448 	ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
28449     if (ctxt->ctxt != NULL)
28450 	xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
28451 }
28452 
28453 /**
28454  * xmlSchemaSAXPlug:
28455  * @ctxt:  a schema validation context
28456  * @sax:  a pointer to the original xmlSAXHandlerPtr
28457  * @user_data:  a pointer to the original SAX user data pointer
28458  *
28459  * Plug a SAX based validation layer in a SAX parsing event flow.
28460  * The original @saxptr and @dataptr data are replaced by new pointers
28461  * but the calls to the original will be maintained.
28462  *
28463  * Returns a pointer to a data structure needed to unplug the validation layer
28464  *         or NULL in case of errors.
28465  */
28466 xmlSchemaSAXPlugPtr
xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,xmlSAXHandlerPtr * sax,void ** user_data)28467 xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
28468 		 xmlSAXHandlerPtr *sax, void **user_data)
28469 {
28470     xmlSchemaSAXPlugPtr ret;
28471     xmlSAXHandlerPtr old_sax;
28472 
28473     if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
28474         return(NULL);
28475 
28476     /*
28477      * We only allow to plug into SAX2 event streams
28478      */
28479     old_sax = *sax;
28480     if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
28481         return(NULL);
28482     if ((old_sax != NULL) &&
28483         (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
28484         ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
28485         return(NULL);
28486 
28487     /*
28488      * everything seems right allocate the local data needed for that layer
28489      */
28490     ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
28491     if (ret == NULL) {
28492         return(NULL);
28493     }
28494     memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
28495     ret->magic = XML_SAX_PLUG_MAGIC;
28496     ret->schemas_sax.initialized = XML_SAX2_MAGIC;
28497     ret->ctxt = ctxt;
28498     ret->user_sax_ptr = sax;
28499     ret->user_sax = old_sax;
28500     if (old_sax == NULL) {
28501         /*
28502 	 * go direct, no need for the split block and functions.
28503 	 */
28504 	ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
28505 	ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
28506 	/*
28507 	 * Note that we use the same text-function for both, to prevent
28508 	 * the parser from testing for ignorable whitespace.
28509 	 */
28510 	ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
28511 	ret->schemas_sax.characters = xmlSchemaSAXHandleText;
28512 
28513 	ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
28514 	ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
28515 
28516 	ret->user_data = ctxt;
28517 	*user_data = ctxt;
28518     } else {
28519        /*
28520         * for each callback unused by Schemas initialize it to the Split
28521 	* routine only if non NULL in the user block, this can speed up
28522 	* things at the SAX level.
28523 	*/
28524         if (old_sax->internalSubset != NULL)
28525             ret->schemas_sax.internalSubset = internalSubsetSplit;
28526         if (old_sax->isStandalone != NULL)
28527             ret->schemas_sax.isStandalone = isStandaloneSplit;
28528         if (old_sax->hasInternalSubset != NULL)
28529             ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
28530         if (old_sax->hasExternalSubset != NULL)
28531             ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
28532         if (old_sax->resolveEntity != NULL)
28533             ret->schemas_sax.resolveEntity = resolveEntitySplit;
28534         if (old_sax->getEntity != NULL)
28535             ret->schemas_sax.getEntity = getEntitySplit;
28536         if (old_sax->entityDecl != NULL)
28537             ret->schemas_sax.entityDecl = entityDeclSplit;
28538         if (old_sax->notationDecl != NULL)
28539             ret->schemas_sax.notationDecl = notationDeclSplit;
28540         if (old_sax->attributeDecl != NULL)
28541             ret->schemas_sax.attributeDecl = attributeDeclSplit;
28542         if (old_sax->elementDecl != NULL)
28543             ret->schemas_sax.elementDecl = elementDeclSplit;
28544         if (old_sax->unparsedEntityDecl != NULL)
28545             ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
28546         if (old_sax->setDocumentLocator != NULL)
28547             ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
28548         if (old_sax->startDocument != NULL)
28549             ret->schemas_sax.startDocument = startDocumentSplit;
28550         if (old_sax->endDocument != NULL)
28551             ret->schemas_sax.endDocument = endDocumentSplit;
28552         if (old_sax->processingInstruction != NULL)
28553             ret->schemas_sax.processingInstruction = processingInstructionSplit;
28554         if (old_sax->comment != NULL)
28555             ret->schemas_sax.comment = commentSplit;
28556         if (old_sax->warning != NULL)
28557             ret->schemas_sax.warning = warningSplit;
28558         if (old_sax->error != NULL)
28559             ret->schemas_sax.error = errorSplit;
28560         if (old_sax->fatalError != NULL)
28561             ret->schemas_sax.fatalError = fatalErrorSplit;
28562         if (old_sax->getParameterEntity != NULL)
28563             ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
28564         if (old_sax->externalSubset != NULL)
28565             ret->schemas_sax.externalSubset = externalSubsetSplit;
28566 
28567 	/*
28568 	 * the 6 schemas callback have to go to the splitter functions
28569 	 * Note that we use the same text-function for ignorableWhitespace
28570 	 * if possible, to prevent the parser from testing for ignorable
28571 	 * whitespace.
28572 	 */
28573         ret->schemas_sax.characters = charactersSplit;
28574 	if ((old_sax->ignorableWhitespace != NULL) &&
28575 	    (old_sax->ignorableWhitespace != old_sax->characters))
28576 	    ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
28577 	else
28578 	    ret->schemas_sax.ignorableWhitespace = charactersSplit;
28579         ret->schemas_sax.cdataBlock = cdataBlockSplit;
28580         ret->schemas_sax.reference = referenceSplit;
28581         ret->schemas_sax.startElementNs = startElementNsSplit;
28582         ret->schemas_sax.endElementNs = endElementNsSplit;
28583 
28584 	ret->user_data_ptr = user_data;
28585 	ret->user_data = *user_data;
28586 	*user_data = ret;
28587     }
28588 
28589     /*
28590      * plug the pointers back.
28591      */
28592     *sax = &(ret->schemas_sax);
28593     ctxt->sax = *sax;
28594     ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28595     xmlSchemaPreRun(ctxt);
28596     return(ret);
28597 }
28598 
28599 /**
28600  * xmlSchemaSAXUnplug:
28601  * @plug:  a data structure returned by xmlSchemaSAXPlug
28602  *
28603  * Unplug a SAX based validation layer in a SAX parsing event flow.
28604  * The original pointers used in the call are restored.
28605  *
28606  * Returns 0 in case of success and -1 in case of failure.
28607  */
28608 int
xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)28609 xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
28610 {
28611     xmlSAXHandlerPtr *sax;
28612     void **user_data;
28613 
28614     if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
28615         return(-1);
28616     plug->magic = 0;
28617 
28618     xmlSchemaPostRun(plug->ctxt);
28619     /* restore the data */
28620     sax = plug->user_sax_ptr;
28621     *sax = plug->user_sax;
28622     if (plug->user_sax != NULL) {
28623 	user_data = plug->user_data_ptr;
28624 	*user_data = plug->user_data;
28625     }
28626 
28627     /* free and return */
28628     xmlFree(plug);
28629     return(0);
28630 }
28631 
28632 /**
28633  * xmlSchemaValidateStream:
28634  * @ctxt:  a schema validation context
28635  * @input:  the input to use for reading the data
28636  * @enc:  an optional encoding information
28637  * @sax:  a SAX handler for the resulting events
28638  * @user_data:  the context to provide to the SAX handler.
28639  *
28640  * Validate an input based on a flow of SAX event from the parser
28641  * and forward the events to the @sax handler with the provided @user_data
28642  * the user provided @sax handler must be a SAX2 one.
28643  *
28644  * Returns 0 if the document is schemas valid, a positive error code
28645  *     number otherwise and -1 in case of internal or API error.
28646  */
28647 int
xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,xmlParserInputBufferPtr input,xmlCharEncoding enc,xmlSAXHandlerPtr sax,void * user_data)28648 xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
28649                         xmlParserInputBufferPtr input, xmlCharEncoding enc,
28650                         xmlSAXHandlerPtr sax, void *user_data)
28651 {
28652     xmlSchemaSAXPlugPtr plug = NULL;
28653     xmlSAXHandlerPtr old_sax = NULL;
28654     xmlParserCtxtPtr pctxt = NULL;
28655     xmlParserInputPtr inputStream = NULL;
28656     int ret;
28657 
28658     if ((ctxt == NULL) || (input == NULL))
28659         return (-1);
28660 
28661     /*
28662      * prepare the parser
28663      */
28664     pctxt = xmlNewParserCtxt();
28665     if (pctxt == NULL)
28666         return (-1);
28667     old_sax = pctxt->sax;
28668     pctxt->sax = sax;
28669     pctxt->userData = user_data;
28670 #if 0
28671     if (options)
28672         xmlCtxtUseOptions(pctxt, options);
28673 #endif
28674     pctxt->linenumbers = 1;
28675 
28676     inputStream = xmlNewIOInputStream(pctxt, input, enc);;
28677     if (inputStream == NULL) {
28678         ret = -1;
28679 	goto done;
28680     }
28681     inputPush(pctxt, inputStream);
28682     ctxt->parserCtxt = pctxt;
28683     ctxt->input = input;
28684 
28685     /*
28686      * Plug the validation and launch the parsing
28687      */
28688     plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
28689     if (plug == NULL) {
28690         ret = -1;
28691 	goto done;
28692     }
28693     ctxt->input = input;
28694     ctxt->enc = enc;
28695     ctxt->sax = pctxt->sax;
28696     ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28697     ret = xmlSchemaVStart(ctxt);
28698 
28699     if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
28700 	ret = ctxt->parserCtxt->errNo;
28701 	if (ret == 0)
28702 	    ret = 1;
28703     }
28704 
28705 done:
28706     ctxt->parserCtxt = NULL;
28707     ctxt->sax = NULL;
28708     ctxt->input = NULL;
28709     if (plug != NULL) {
28710         xmlSchemaSAXUnplug(plug);
28711     }
28712     /* cleanup */
28713     if (pctxt != NULL) {
28714 	pctxt->sax = old_sax;
28715 	xmlFreeParserCtxt(pctxt);
28716     }
28717     return (ret);
28718 }
28719 
28720 /**
28721  * xmlSchemaValidateFile:
28722  * @ctxt: a schema validation context
28723  * @filename: the URI of the instance
28724  * @options: a future set of options, currently unused
28725  *
28726  * Do a schemas validation of the given resource, it will use the
28727  * SAX streamable validation internally.
28728  *
28729  * Returns 0 if the document is valid, a positive error code
28730  *     number otherwise and -1 in case of an internal or API error.
28731  */
28732 int
xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,const char * filename,int options ATTRIBUTE_UNUSED)28733 xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
28734                       const char * filename,
28735 		      int options ATTRIBUTE_UNUSED)
28736 {
28737     int ret;
28738     xmlParserInputBufferPtr input;
28739 
28740     if ((ctxt == NULL) || (filename == NULL))
28741         return (-1);
28742 
28743     input = xmlParserInputBufferCreateFilename(filename,
28744 	XML_CHAR_ENCODING_NONE);
28745     if (input == NULL)
28746 	return (-1);
28747     ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
28748 	NULL, NULL);
28749     return (ret);
28750 }
28751 
28752 /**
28753  * xmlSchemaValidCtxtGetParserCtxt:
28754  * @ctxt: a schema validation context
28755  *
28756  * allow access to the parser context of the schema validation context
28757  *
28758  * Returns the parser context of the schema validation context or NULL
28759  *         in case of error.
28760  */
28761 xmlParserCtxtPtr
xmlSchemaValidCtxtGetParserCtxt(xmlSchemaValidCtxtPtr ctxt)28762 xmlSchemaValidCtxtGetParserCtxt(xmlSchemaValidCtxtPtr ctxt)
28763 {
28764     if (ctxt == NULL)
28765         return(NULL);
28766     return (ctxt->parserCtxt);
28767 }
28768 
28769 #define bottom_xmlschemas
28770 #include "elfgcchack.h"
28771 #endif /* LIBXML_SCHEMAS_ENABLED */
28772