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  *   - Eliminated 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 
48 /* To avoid EBCDIC trouble when parsing on zOS */
49 #if defined(__MVS__)
50 #pragma convert("ISO8859-1")
51 #endif
52 
53 #define IN_LIBXML
54 #include "libxml.h"
55 
56 #ifdef LIBXML_SCHEMAS_ENABLED
57 
58 #include <string.h>
59 #include <libxml/xmlmemory.h>
60 #include <libxml/parser.h>
61 #include <libxml/parserInternals.h>
62 #include <libxml/hash.h>
63 #include <libxml/uri.h>
64 #include <libxml/xmlschemas.h>
65 #include <libxml/schemasInternals.h>
66 #include <libxml/xmlschemastypes.h>
67 #include <libxml/xmlautomata.h>
68 #include <libxml/xmlregexp.h>
69 #include <libxml/dict.h>
70 #include <libxml/encoding.h>
71 #include <libxml/xmlIO.h>
72 #ifdef LIBXML_PATTERN_ENABLED
73 #include <libxml/pattern.h>
74 #endif
75 #ifdef LIBXML_READER_ENABLED
76 #include <libxml/xmlreader.h>
77 #endif
78 
79 /* #define DEBUG 1 */
80 
81 /* #define DEBUG_CONTENT 1 */
82 
83 /* #define DEBUG_TYPE 1 */
84 
85 /* #define DEBUG_CONTENT_REGEXP 1 */
86 
87 /* #define DEBUG_AUTOMATA 1 */
88 
89 /* #define DEBUG_IDC */
90 
91 /* #define DEBUG_IDC_NODE_TABLE */
92 
93 /* #define WXS_ELEM_DECL_CONS_ENABLED */
94 
95 #ifdef DEBUG_IDC
96  #ifndef DEBUG_IDC_NODE_TABLE
97   #define DEBUG_IDC_NODE_TABLE
98  #endif
99 #endif
100 
101 /* #define ENABLE_PARTICLE_RESTRICTION 1 */
102 
103 #define ENABLE_REDEFINE
104 
105 /* #define ENABLE_NAMED_LOCALS */
106 
107 /* #define ENABLE_IDC_NODE_TABLES_TEST */
108 
109 #define DUMP_CONTENT_MODEL
110 
111 #ifdef LIBXML_READER_ENABLED
112 /* #define XML_SCHEMA_READER_ENABLED */
113 #endif
114 
115 #define UNBOUNDED (1 << 30)
116 #define TODO								\
117     xmlGenericError(xmlGenericErrorContext,				\
118 	    "Unimplemented block at %s:%d\n",				\
119             __FILE__, __LINE__);
120 
121 #define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
122 
123 /*
124  * The XML Schemas namespaces
125  */
126 static const xmlChar *xmlSchemaNs = (const xmlChar *)
127     "http://www.w3.org/2001/XMLSchema";
128 
129 static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
130     "http://www.w3.org/2001/XMLSchema-instance";
131 
132 static const xmlChar *xmlNamespaceNs = (const xmlChar *)
133     "http://www.w3.org/2000/xmlns/";
134 
135 /*
136 * Come casting macros.
137 */
138 #define ACTXT_CAST (xmlSchemaAbstractCtxtPtr)
139 #define PCTXT_CAST (xmlSchemaParserCtxtPtr)
140 #define VCTXT_CAST (xmlSchemaValidCtxtPtr)
141 #define WXS_BASIC_CAST (xmlSchemaBasicItemPtr)
142 #define WXS_TREE_CAST (xmlSchemaTreeItemPtr)
143 #define WXS_PTC_CAST (xmlSchemaParticlePtr)
144 #define WXS_TYPE_CAST (xmlSchemaTypePtr)
145 #define WXS_ELEM_CAST (xmlSchemaElementPtr)
146 #define WXS_ATTR_GROUP_CAST (xmlSchemaAttributeGroupPtr)
147 #define WXS_ATTR_CAST (xmlSchemaAttributePtr)
148 #define WXS_ATTR_USE_CAST (xmlSchemaAttributeUsePtr)
149 #define WXS_ATTR_PROHIB_CAST (xmlSchemaAttributeUseProhibPtr)
150 #define WXS_MODEL_GROUPDEF_CAST (xmlSchemaModelGroupDefPtr)
151 #define WXS_MODEL_GROUP_CAST (xmlSchemaModelGroupPtr)
152 #define WXS_IDC_CAST (xmlSchemaIDCPtr)
153 #define WXS_QNAME_CAST (xmlSchemaQNameRefPtr)
154 #define WXS_LIST_CAST (xmlSchemaItemListPtr)
155 
156 /*
157 * Macros to query common properties of components.
158 */
159 #define WXS_ITEM_NODE(i) xmlSchemaGetComponentNode(WXS_BASIC_CAST (i))
160 
161 #define WXS_ITEM_TYPE_NAME(i) xmlSchemaGetComponentTypeStr(WXS_BASIC_CAST (i))
162 /*
163 * Macros for element declarations.
164 */
165 #define WXS_ELEM_TYPEDEF(e) (e)->subtypes
166 
167 #define WXS_SUBST_HEAD(item) (item)->refDecl
168 /*
169 * Macros for attribute declarations.
170 */
171 #define WXS_ATTR_TYPEDEF(a) (a)->subtypes
172 /*
173 * Macros for attribute uses.
174 */
175 #define WXS_ATTRUSE_DECL(au) (WXS_ATTR_USE_CAST (au))->attrDecl
176 
177 #define WXS_ATTRUSE_TYPEDEF(au) WXS_ATTR_TYPEDEF(WXS_ATTRUSE_DECL( WXS_ATTR_USE_CAST au))
178 
179 #define WXS_ATTRUSE_DECL_NAME(au) (WXS_ATTRUSE_DECL(au))->name
180 
181 #define WXS_ATTRUSE_DECL_TNS(au) (WXS_ATTRUSE_DECL(au))->targetNamespace
182 /*
183 * Macros for attribute groups.
184 */
185 #define WXS_ATTR_GROUP_HAS_REFS(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS)
186 #define WXS_ATTR_GROUP_EXPANDED(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED)
187 /*
188 * Macros for particles.
189 */
190 #define WXS_PARTICLE(p) WXS_PTC_CAST (p)
191 
192 #define WXS_PARTICLE_TERM(p) (WXS_PARTICLE(p))->children
193 
194 #define WXS_PARTICLE_TERM_AS_ELEM(p) (WXS_ELEM_CAST WXS_PARTICLE_TERM(p))
195 
196 #define WXS_PARTICLE_MODEL(p) WXS_MODEL_GROUP_CAST WXS_PARTICLE(p)->children
197 /*
198 * Macros for model groups definitions.
199 */
200 #define WXS_MODELGROUPDEF_MODEL(mgd) (WXS_MODEL_GROUP_CAST (mgd))->children
201 /*
202 * Macros for model groups.
203 */
204 #define WXS_IS_MODEL_GROUP(i) \
205     (((i)->type == XML_SCHEMA_TYPE_SEQUENCE) || \
206      ((i)->type == XML_SCHEMA_TYPE_CHOICE) || \
207      ((i)->type == XML_SCHEMA_TYPE_ALL))
208 
209 #define WXS_MODELGROUP_PARTICLE(mg) WXS_PTC_CAST (mg)->children
210 /*
211 * Macros for schema buckets.
212 */
213 #define WXS_IS_BUCKET_INCREDEF(t) (((t) == XML_SCHEMA_SCHEMA_INCLUDE) || \
214     ((t) == XML_SCHEMA_SCHEMA_REDEFINE))
215 
216 #define WXS_IS_BUCKET_IMPMAIN(t) (((t) == XML_SCHEMA_SCHEMA_MAIN) || \
217     ((t) == XML_SCHEMA_SCHEMA_IMPORT))
218 
219 #define WXS_IMPBUCKET(b) ((xmlSchemaImportPtr) (b))
220 
221 #define WXS_INCBUCKET(b) ((xmlSchemaIncludePtr) (b))
222 /*
223 * Macros for complex/simple types.
224 */
225 #define WXS_IS_ANYTYPE(i) \
226      (( (i)->type == XML_SCHEMA_TYPE_BASIC) && \
227       ( (WXS_TYPE_CAST (i))->builtInType == XML_SCHEMAS_ANYTYPE))
228 
229 #define WXS_IS_COMPLEX(i) \
230     (((i)->type == XML_SCHEMA_TYPE_COMPLEX) || \
231      ((i)->builtInType == XML_SCHEMAS_ANYTYPE))
232 
233 #define WXS_IS_SIMPLE(item) \
234     ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
235      ((item->type == XML_SCHEMA_TYPE_BASIC) && \
236       (item->builtInType != XML_SCHEMAS_ANYTYPE)))
237 
238 #define WXS_IS_ANY_SIMPLE_TYPE(i) \
239     (((i)->type == XML_SCHEMA_TYPE_BASIC) && \
240       ((i)->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
241 
242 #define WXS_IS_RESTRICTION(t) \
243     ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)
244 
245 #define WXS_IS_EXTENSION(t) \
246     ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
247 
248 #define WXS_IS_TYPE_NOT_FIXED(i) \
249     (((i)->type != XML_SCHEMA_TYPE_BASIC) && \
250      (((i)->flags & XML_SCHEMAS_TYPE_INTERNAL_RESOLVED) == 0))
251 
252 #define WXS_IS_TYPE_NOT_FIXED_1(item) \
253     (((item)->type != XML_SCHEMA_TYPE_BASIC) && \
254      (((item)->flags & XML_SCHEMAS_TYPE_FIXUP_1) == 0))
255 
256 #define WXS_TYPE_IS_GLOBAL(t) ((t)->flags & XML_SCHEMAS_TYPE_GLOBAL)
257 
258 #define WXS_TYPE_IS_LOCAL(t) (((t)->flags & XML_SCHEMAS_TYPE_GLOBAL) == 0)
259 /*
260 * Macros for exclusively for complex types.
261 */
262 #define WXS_HAS_COMPLEX_CONTENT(item) \
263     ((item->contentType == XML_SCHEMA_CONTENT_MIXED) || \
264      (item->contentType == XML_SCHEMA_CONTENT_EMPTY) || \
265      (item->contentType == XML_SCHEMA_CONTENT_ELEMENTS))
266 
267 #define WXS_HAS_SIMPLE_CONTENT(item) \
268     ((item->contentType == XML_SCHEMA_CONTENT_SIMPLE) || \
269      (item->contentType == XML_SCHEMA_CONTENT_BASIC))
270 
271 #define WXS_HAS_MIXED_CONTENT(item) \
272     (item->contentType == XML_SCHEMA_CONTENT_MIXED)
273 
274 #define WXS_EMPTIABLE(t) \
275     (xmlSchemaIsParticleEmptiable(WXS_PTC_CAST (t)->subtypes))
276 
277 #define WXS_TYPE_CONTENTTYPE(t) (t)->subtypes
278 
279 #define WXS_TYPE_PARTICLE(t) WXS_PTC_CAST (t)->subtypes
280 
281 #define WXS_TYPE_PARTICLE_TERM(t) WXS_PARTICLE_TERM(WXS_TYPE_PARTICLE(t))
282 /*
283 * Macros for exclusively for simple types.
284 */
285 #define WXS_LIST_ITEMTYPE(t) (t)->subtypes
286 
287 #define WXS_IS_ATOMIC(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
288 
289 #define WXS_IS_LIST(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
290 
291 #define WXS_IS_UNION(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)
292 /*
293 * Misc parser context macros.
294 */
295 #define WXS_CONSTRUCTOR(ctx) (ctx)->constructor
296 
297 #define WXS_HAS_BUCKETS(ctx) \
298 ( (WXS_CONSTRUCTOR((ctx))->buckets != NULL) && \
299 (WXS_CONSTRUCTOR((ctx))->buckets->nbItems > 0) )
300 
301 #define WXS_SUBST_GROUPS(ctx) WXS_CONSTRUCTOR((ctx))->substGroups
302 
303 #define WXS_BUCKET(ctx) WXS_CONSTRUCTOR((ctx))->bucket
304 
305 #define WXS_SCHEMA(ctx) (ctx)->schema
306 
307 #define WXS_ADD_LOCAL(ctx, item) \
308     xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->locals), 10, item)
309 
310 #define WXS_ADD_GLOBAL(ctx, item) \
311     xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->globals), 5, item)
312 
313 #define WXS_ADD_PENDING(ctx, item) \
314     xmlSchemaAddItemSize(&((ctx)->constructor->pending), 10, item)
315 /*
316 * xmlSchemaItemList macros.
317 */
318 #define WXS_ILIST_IS_EMPTY(l) ((l == NULL) || ((l)->nbItems == 0))
319 /*
320 * Misc macros.
321 */
322 #define IS_SCHEMA(node, type) \
323    ((node != NULL) && (node->ns != NULL) && \
324     (xmlStrEqual(node->name, (const xmlChar *) type)) && \
325     (xmlStrEqual(node->ns->href, xmlSchemaNs)))
326 
327 #define FREE_AND_NULL(str) if ((str) != NULL) { xmlFree((xmlChar *) (str)); str = NULL; }
328 
329 /*
330 * Since we put the default/fixed values into the dict, we can
331 * use pointer comparison for those values.
332 * REMOVED: (xmlStrEqual((v1), (v2)))
333 */
334 #define WXS_ARE_DEFAULT_STR_EQUAL(v1, v2) ((v1) == (v2))
335 
336 #define INODE_NILLED(item) (item->flags & XML_SCHEMA_ELEM_INFO_NILLED)
337 
338 #define CAN_PARSE_SCHEMA(b) (((b)->doc != NULL) && ((b)->parsed == 0))
339 
340 #define HFAILURE if (res == -1) goto exit_failure;
341 
342 #define HERROR if (res != 0) goto exit_error;
343 
344 #define HSTOP(ctx) if ((ctx)->stop) goto exit;
345 /*
346 * Some flags used for various schema constraints.
347 */
348 #define SUBSET_RESTRICTION  1<<0
349 #define SUBSET_EXTENSION    1<<1
350 #define SUBSET_SUBSTITUTION 1<<2
351 #define SUBSET_LIST         1<<3
352 #define SUBSET_UNION        1<<4
353 
354 typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
355 typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
356 
357 typedef struct _xmlSchemaItemList xmlSchemaItemList;
358 typedef xmlSchemaItemList *xmlSchemaItemListPtr;
359 struct _xmlSchemaItemList {
360     void **items;  /* used for dynamic addition of schemata */
361     int nbItems; /* used for dynamic addition of schemata */
362     int sizeItems; /* used for dynamic addition of schemata */
363 };
364 
365 #define XML_SCHEMA_CTXT_PARSER 1
366 #define XML_SCHEMA_CTXT_VALIDATOR 2
367 
368 typedef struct _xmlSchemaAbstractCtxt xmlSchemaAbstractCtxt;
369 typedef xmlSchemaAbstractCtxt *xmlSchemaAbstractCtxtPtr;
370 struct _xmlSchemaAbstractCtxt {
371     int type; /* E.g. XML_SCHEMA_CTXT_VALIDATOR */
372     void *dummy; /* Fix alignment issues */
373 };
374 
375 typedef struct _xmlSchemaBucket xmlSchemaBucket;
376 typedef xmlSchemaBucket *xmlSchemaBucketPtr;
377 
378 #define XML_SCHEMA_SCHEMA_MAIN 0
379 #define XML_SCHEMA_SCHEMA_IMPORT 1
380 #define XML_SCHEMA_SCHEMA_INCLUDE 2
381 #define XML_SCHEMA_SCHEMA_REDEFINE 3
382 
383 /**
384  * xmlSchemaSchemaRelation:
385  *
386  * Used to create a graph of schema relationships.
387  */
388 typedef struct _xmlSchemaSchemaRelation xmlSchemaSchemaRelation;
389 typedef xmlSchemaSchemaRelation *xmlSchemaSchemaRelationPtr;
390 struct _xmlSchemaSchemaRelation {
391     xmlSchemaSchemaRelationPtr next;
392     int type; /* E.g. XML_SCHEMA_SCHEMA_IMPORT */
393     const xmlChar *importNamespace;
394     xmlSchemaBucketPtr bucket;
395 };
396 
397 #define XML_SCHEMA_BUCKET_MARKED 1<<0
398 #define XML_SCHEMA_BUCKET_COMPS_ADDED 1<<1
399 
400 struct _xmlSchemaBucket {
401     int type;
402     int flags;
403     const xmlChar *schemaLocation;
404     const xmlChar *origTargetNamespace;
405     const xmlChar *targetNamespace;
406     xmlDocPtr doc;
407     xmlSchemaSchemaRelationPtr relations;
408     int located;
409     int parsed;
410     int imported;
411     int preserveDoc;
412     xmlSchemaItemListPtr globals; /* Global components. */
413     xmlSchemaItemListPtr locals; /* Local components. */
414 };
415 
416 /**
417  * xmlSchemaImport:
418  * (extends xmlSchemaBucket)
419  *
420  * Reflects a schema. Holds some information
421  * about the schema and its toplevel components. Duplicate
422  * toplevel components are not checked at this level.
423  */
424 typedef struct _xmlSchemaImport xmlSchemaImport;
425 typedef xmlSchemaImport *xmlSchemaImportPtr;
426 struct _xmlSchemaImport {
427     int type; /* Main OR import OR include. */
428     int flags;
429     const xmlChar *schemaLocation; /* The URI of the schema document. */
430     /* For chameleon includes, @origTargetNamespace will be NULL */
431     const xmlChar *origTargetNamespace;
432     /*
433     * For chameleon includes, @targetNamespace will be the
434     * targetNamespace of the including schema.
435     */
436     const xmlChar *targetNamespace;
437     xmlDocPtr doc; /* The schema node-tree. */
438     /* @relations will hold any included/imported/redefined schemas. */
439     xmlSchemaSchemaRelationPtr relations;
440     int located;
441     int parsed;
442     int imported;
443     int preserveDoc;
444     xmlSchemaItemListPtr globals;
445     xmlSchemaItemListPtr locals;
446     /* The imported schema. */
447     xmlSchemaPtr schema;
448 };
449 
450 /*
451 * (extends xmlSchemaBucket)
452 */
453 typedef struct _xmlSchemaInclude xmlSchemaInclude;
454 typedef xmlSchemaInclude *xmlSchemaIncludePtr;
455 struct _xmlSchemaInclude {
456     int type;
457     int flags;
458     const xmlChar *schemaLocation;
459     const xmlChar *origTargetNamespace;
460     const xmlChar *targetNamespace;
461     xmlDocPtr doc;
462     xmlSchemaSchemaRelationPtr relations;
463     int located;
464     int parsed;
465     int imported;
466     int preserveDoc;
467     xmlSchemaItemListPtr globals; /* Global components. */
468     xmlSchemaItemListPtr locals; /* Local components. */
469 
470     /* The owning main or import schema bucket. */
471     xmlSchemaImportPtr ownerImport;
472 };
473 
474 /**
475  * xmlSchemaBasicItem:
476  *
477  * The abstract base type for schema components.
478  */
479 typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
480 typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
481 struct _xmlSchemaBasicItem {
482     xmlSchemaTypeType type;
483     void *dummy; /* Fix alignment issues */
484 };
485 
486 /**
487  * xmlSchemaAnnotItem:
488  *
489  * The abstract base type for annotated schema components.
490  * (Extends xmlSchemaBasicItem)
491  */
492 typedef struct _xmlSchemaAnnotItem xmlSchemaAnnotItem;
493 typedef xmlSchemaAnnotItem *xmlSchemaAnnotItemPtr;
494 struct _xmlSchemaAnnotItem {
495     xmlSchemaTypeType type;
496     xmlSchemaAnnotPtr annot;
497 };
498 
499 /**
500  * xmlSchemaTreeItem:
501  *
502  * The abstract base type for tree-like structured schema components.
503  * (Extends xmlSchemaAnnotItem)
504  */
505 typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
506 typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
507 struct _xmlSchemaTreeItem {
508     xmlSchemaTypeType type;
509     xmlSchemaAnnotPtr annot;
510     xmlSchemaTreeItemPtr next;
511     xmlSchemaTreeItemPtr children;
512 };
513 
514 
515 #define XML_SCHEMA_ATTR_USE_FIXED 1<<0
516 /**
517  * xmlSchemaAttributeUsePtr:
518  *
519  * The abstract base type for tree-like structured schema components.
520  * (Extends xmlSchemaTreeItem)
521  */
522 typedef struct _xmlSchemaAttributeUse xmlSchemaAttributeUse;
523 typedef xmlSchemaAttributeUse *xmlSchemaAttributeUsePtr;
524 struct _xmlSchemaAttributeUse {
525     xmlSchemaTypeType type;
526     xmlSchemaAnnotPtr annot;
527     xmlSchemaAttributeUsePtr next; /* The next attr. use. */
528     /*
529     * The attr. decl. OR a QName-ref. to an attr. decl. OR
530     * a QName-ref. to an attribute group definition.
531     */
532     xmlSchemaAttributePtr attrDecl;
533 
534     int flags;
535     xmlNodePtr node;
536     int occurs; /* required, optional */
537     const xmlChar * defValue;
538     xmlSchemaValPtr defVal;
539 };
540 
541 /**
542  * xmlSchemaAttributeUseProhibPtr:
543  *
544  * A helper component to reflect attribute prohibitions.
545  * (Extends xmlSchemaBasicItem)
546  */
547 typedef struct _xmlSchemaAttributeUseProhib xmlSchemaAttributeUseProhib;
548 typedef xmlSchemaAttributeUseProhib *xmlSchemaAttributeUseProhibPtr;
549 struct _xmlSchemaAttributeUseProhib {
550     xmlSchemaTypeType type; /* == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB */
551     xmlNodePtr node;
552     const xmlChar *name;
553     const xmlChar *targetNamespace;
554     int isRef;
555 };
556 
557 /**
558  * xmlSchemaRedef:
559  */
560 typedef struct _xmlSchemaRedef xmlSchemaRedef;
561 typedef xmlSchemaRedef *xmlSchemaRedefPtr;
562 struct _xmlSchemaRedef {
563     xmlSchemaRedefPtr next;
564     xmlSchemaBasicItemPtr item; /* The redefining component. */
565     xmlSchemaBasicItemPtr reference; /* The referencing component. */
566     xmlSchemaBasicItemPtr target; /* The to-be-redefined component. */
567     const xmlChar *refName; /* The name of the to-be-redefined component. */
568     const xmlChar *refTargetNs; /* The target namespace of the
569                                    to-be-redefined comp. */
570     xmlSchemaBucketPtr targetBucket; /* The redefined schema. */
571 };
572 
573 /**
574  * xmlSchemaConstructionCtxt:
575  */
576 typedef struct _xmlSchemaConstructionCtxt xmlSchemaConstructionCtxt;
577 typedef xmlSchemaConstructionCtxt *xmlSchemaConstructionCtxtPtr;
578 struct _xmlSchemaConstructionCtxt {
579     xmlSchemaPtr mainSchema; /* The main schema. */
580     xmlSchemaBucketPtr mainBucket; /* The main schema bucket */
581     xmlDictPtr dict;
582     xmlSchemaItemListPtr buckets; /* List of schema buckets. */
583     /* xmlSchemaItemListPtr relations; */ /* List of schema relations. */
584     xmlSchemaBucketPtr bucket; /* The current schema bucket */
585     xmlSchemaItemListPtr pending; /* All Components of all schemas that
586                                      need to be fixed. */
587     xmlHashTablePtr substGroups;
588     xmlSchemaRedefPtr redefs;
589     xmlSchemaRedefPtr lastRedef;
590 };
591 
592 #define XML_SCHEMAS_PARSE_ERROR		1
593 #define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
594 
595 struct _xmlSchemaParserCtxt {
596     int type;
597     void *errCtxt;             /* user specific error context */
598     xmlSchemaValidityErrorFunc error;   /* the callback in case of errors */
599     xmlSchemaValidityWarningFunc warning;       /* the callback in case of warning */
600     int err;
601     int nberrors;
602     xmlStructuredErrorFunc serror;
603 
604     xmlSchemaConstructionCtxtPtr constructor;
605     int ownsConstructor; /* TODO: Move this to parser *flags*. */
606 
607     /* xmlSchemaPtr topschema;	*/
608     /* xmlHashTablePtr namespaces;  */
609 
610     xmlSchemaPtr schema;        /* The main schema in use */
611     int counter;
612 
613     const xmlChar *URL;
614     xmlDocPtr doc;
615     int preserve;		/* Whether the doc should be freed  */
616 
617     const char *buffer;
618     int size;
619 
620     /*
621      * Used to build complex element content models
622      */
623     xmlAutomataPtr am;
624     xmlAutomataStatePtr start;
625     xmlAutomataStatePtr end;
626     xmlAutomataStatePtr state;
627 
628     xmlDictPtr dict;		/* dictionary for interned string names */
629     xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
630     int options;
631     xmlSchemaValidCtxtPtr vctxt;
632     int isS4S;
633     int isRedefine;
634     int xsiAssemble;
635     int stop; /* If the parser should stop; i.e. a critical error. */
636     const xmlChar *targetNamespace;
637     xmlSchemaBucketPtr redefined; /* The schema to be redefined. */
638 
639     xmlSchemaRedefPtr redef; /* Used for redefinitions. */
640     int redefCounter; /* Used for redefinitions. */
641     xmlSchemaItemListPtr attrProhibs;
642 };
643 
644 /**
645  * xmlSchemaQNameRef:
646  *
647  * A component reference item (not a schema component)
648  * (Extends xmlSchemaBasicItem)
649  */
650 typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef;
651 typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr;
652 struct _xmlSchemaQNameRef {
653     xmlSchemaTypeType type;
654     xmlSchemaBasicItemPtr item; /* The resolved referenced item. */
655     xmlSchemaTypeType itemType;
656     const xmlChar *name;
657     const xmlChar *targetNamespace;
658     xmlNodePtr node;
659 };
660 
661 /**
662  * xmlSchemaParticle:
663  *
664  * A particle component.
665  * (Extends xmlSchemaTreeItem)
666  */
667 typedef struct _xmlSchemaParticle xmlSchemaParticle;
668 typedef xmlSchemaParticle *xmlSchemaParticlePtr;
669 struct _xmlSchemaParticle {
670     xmlSchemaTypeType type;
671     xmlSchemaAnnotPtr annot;
672     xmlSchemaTreeItemPtr next; /* next particle */
673     xmlSchemaTreeItemPtr children; /* the "term" (e.g. a model group,
674 	a group definition, a XML_SCHEMA_EXTRA_QNAMEREF (if a reference),
675         etc.) */
676     int minOccurs;
677     int maxOccurs;
678     xmlNodePtr node;
679 };
680 
681 /**
682  * xmlSchemaModelGroup:
683  *
684  * A model group component.
685  * (Extends xmlSchemaTreeItem)
686  */
687 typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
688 typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
689 struct _xmlSchemaModelGroup {
690     xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_SEQUENCE, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL */
691     xmlSchemaAnnotPtr annot;
692     xmlSchemaTreeItemPtr next; /* not used */
693     xmlSchemaTreeItemPtr children; /* first particle (OR "element decl" OR "wildcard") */
694     xmlNodePtr node;
695 };
696 
697 #define XML_SCHEMA_MODEL_GROUP_DEF_MARKED 1<<0
698 #define XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED 1<<1
699 /**
700  * xmlSchemaModelGroupDef:
701  *
702  * A model group definition component.
703  * (Extends xmlSchemaTreeItem)
704  */
705 typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
706 typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
707 struct _xmlSchemaModelGroupDef {
708     xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_GROUP */
709     xmlSchemaAnnotPtr annot;
710     xmlSchemaTreeItemPtr next; /* not used */
711     xmlSchemaTreeItemPtr children; /* the "model group" */
712     const xmlChar *name;
713     const xmlChar *targetNamespace;
714     xmlNodePtr node;
715     int flags;
716 };
717 
718 typedef struct _xmlSchemaIDC xmlSchemaIDC;
719 typedef xmlSchemaIDC *xmlSchemaIDCPtr;
720 
721 /**
722  * xmlSchemaIDCSelect:
723  *
724  * The identity-constraint "field" and "selector" item, holding the
725  * XPath expression.
726  */
727 typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
728 typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
729 struct _xmlSchemaIDCSelect {
730     xmlSchemaIDCSelectPtr next;
731     xmlSchemaIDCPtr idc;
732     int index; /* an index position if significant for IDC key-sequences */
733     const xmlChar *xpath; /* the XPath expression */
734     void *xpathComp; /* the compiled XPath expression */
735 };
736 
737 /**
738  * xmlSchemaIDC:
739  *
740  * The identity-constraint definition component.
741  * (Extends xmlSchemaAnnotItem)
742  */
743 
744 struct _xmlSchemaIDC {
745     xmlSchemaTypeType type;
746     xmlSchemaAnnotPtr annot;
747     xmlSchemaIDCPtr next;
748     xmlNodePtr node;
749     const xmlChar *name;
750     const xmlChar *targetNamespace;
751     xmlSchemaIDCSelectPtr selector;
752     xmlSchemaIDCSelectPtr fields;
753     int nbFields;
754     xmlSchemaQNameRefPtr ref;
755 };
756 
757 /**
758  * xmlSchemaIDCAug:
759  *
760  * The augmented IDC information used for validation.
761  */
762 typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
763 typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
764 struct _xmlSchemaIDCAug {
765     xmlSchemaIDCAugPtr next; /* next in a list */
766     xmlSchemaIDCPtr def; /* the IDC definition */
767     int keyrefDepth; /* the lowest tree level to which IDC
768                         tables need to be bubbled upwards */
769 };
770 
771 /**
772  * xmlSchemaPSVIIDCKeySequence:
773  *
774  * The key sequence of a node table item.
775  */
776 typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
777 typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
778 struct _xmlSchemaPSVIIDCKey {
779     xmlSchemaTypePtr type;
780     xmlSchemaValPtr val;
781 };
782 
783 /**
784  * xmlSchemaPSVIIDCNode:
785  *
786  * The node table item of a node table.
787  */
788 typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
789 typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
790 struct _xmlSchemaPSVIIDCNode {
791     xmlNodePtr node;
792     xmlSchemaPSVIIDCKeyPtr *keys;
793     int nodeLine;
794     int nodeQNameID;
795 
796 };
797 
798 /**
799  * xmlSchemaPSVIIDCBinding:
800  *
801  * The identity-constraint binding item of the [identity-constraint table].
802  */
803 typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
804 typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
805 struct _xmlSchemaPSVIIDCBinding {
806     xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
807     xmlSchemaIDCPtr definition; /* the IDC definition */
808     xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
809     int nbNodes; /* number of entries in the node table */
810     int sizeNodes; /* size of the node table */
811     xmlSchemaItemListPtr dupls;
812 };
813 
814 
815 #define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
816 #define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
817 
818 #define XPATH_STATE_OBJ_MATCHES -2
819 #define XPATH_STATE_OBJ_BLOCKED -3
820 
821 typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
822 typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
823 
824 /**
825  * xmlSchemaIDCStateObj:
826  *
827  * The state object used to evaluate XPath expressions.
828  */
829 typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
830 typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
831 struct _xmlSchemaIDCStateObj {
832     int type;
833     xmlSchemaIDCStateObjPtr next; /* next if in a list */
834     int depth; /* depth of creation */
835     int *history; /* list of (depth, state-id) tuples */
836     int nbHistory;
837     int sizeHistory;
838     xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
839                                        matcher */
840     xmlSchemaIDCSelectPtr sel;
841     void *xpathCtxt;
842 };
843 
844 #define IDC_MATCHER 0
845 
846 /**
847  * xmlSchemaIDCMatcher:
848  *
849  * Used to evaluate IDC selectors (and fields).
850  */
851 struct _xmlSchemaIDCMatcher {
852     int type;
853     int depth; /* the tree depth at creation time */
854     xmlSchemaIDCMatcherPtr next; /* next in the list */
855     xmlSchemaIDCMatcherPtr nextCached; /* next in the cache list */
856     xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
857     int idcType;
858     xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
859                                          elements */
860     int sizeKeySeqs;
861     xmlSchemaItemListPtr targets; /* list of target-node
862                                      (xmlSchemaPSVIIDCNodePtr) entries */
863     xmlHashTablePtr htab;
864 };
865 
866 /*
867 * Element info flags.
868 */
869 #define XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES  1<<0
870 #define XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES 1<<1
871 #define XML_SCHEMA_ELEM_INFO_NILLED	       1<<2
872 #define XML_SCHEMA_ELEM_INFO_LOCAL_TYPE	       1<<3
873 
874 #define XML_SCHEMA_NODE_INFO_VALUE_NEEDED      1<<4
875 #define XML_SCHEMA_ELEM_INFO_EMPTY             1<<5
876 #define XML_SCHEMA_ELEM_INFO_HAS_CONTENT       1<<6
877 
878 #define XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT  1<<7
879 #define XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT  1<<8
880 #define XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED  1<<9
881 #define XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE  1<<10
882 
883 /**
884  * xmlSchemaNodeInfo:
885  *
886  * Holds information of an element node.
887  */
888 struct _xmlSchemaNodeInfo {
889     int nodeType;
890     xmlNodePtr node;
891     int nodeLine;
892     const xmlChar *localName;
893     const xmlChar *nsName;
894     const xmlChar *value;
895     xmlSchemaValPtr val; /* the pre-computed value if any */
896     xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
897 
898     int flags; /* combination of node info flags */
899 
900     int valNeeded;
901     int normVal;
902 
903     xmlSchemaElementPtr decl; /* the element/attribute declaration */
904     int depth;
905     xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
906                                             for the scope element*/
907     xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
908                                            element */
909     xmlRegExecCtxtPtr regexCtxt;
910 
911     const xmlChar **nsBindings; /* Namespace bindings on this element */
912     int nbNsBindings;
913     int sizeNsBindings;
914 
915     int hasKeyrefs;
916     int appliedXPath; /* Indicates that an XPath has been applied. */
917 };
918 
919 #define XML_SCHEMAS_ATTR_UNKNOWN 1
920 #define XML_SCHEMAS_ATTR_ASSESSED 2
921 #define XML_SCHEMAS_ATTR_PROHIBITED 3
922 #define XML_SCHEMAS_ATTR_ERR_MISSING 4
923 #define XML_SCHEMAS_ATTR_INVALID_VALUE 5
924 #define XML_SCHEMAS_ATTR_ERR_NO_TYPE 6
925 #define XML_SCHEMAS_ATTR_ERR_FIXED_VALUE 7
926 #define XML_SCHEMAS_ATTR_DEFAULT 8
927 #define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
928 #define XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL 10
929 #define XML_SCHEMAS_ATTR_HAS_ATTR_USE 11
930 #define XML_SCHEMAS_ATTR_HAS_ATTR_DECL 12
931 #define XML_SCHEMAS_ATTR_WILD_SKIP 13
932 #define XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL 14
933 #define XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID 15
934 #define XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID 16
935 #define XML_SCHEMAS_ATTR_META 17
936 /*
937 * @metaType values of xmlSchemaAttrInfo.
938 */
939 #define XML_SCHEMA_ATTR_INFO_META_XSI_TYPE 1
940 #define XML_SCHEMA_ATTR_INFO_META_XSI_NIL 2
941 #define XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC 3
942 #define XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC 4
943 #define XML_SCHEMA_ATTR_INFO_META_XMLNS 5
944 
945 typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo;
946 typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr;
947 struct _xmlSchemaAttrInfo {
948     int nodeType;
949     xmlNodePtr node;
950     int nodeLine;
951     const xmlChar *localName;
952     const xmlChar *nsName;
953     const xmlChar *value;
954     xmlSchemaValPtr val; /* the pre-computed value if any */
955     xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
956     int flags; /* combination of node info flags */
957 
958     xmlSchemaAttributePtr decl; /* the attribute declaration */
959     xmlSchemaAttributeUsePtr use;  /* the attribute use */
960     int state;
961     int metaType;
962     const xmlChar *vcValue; /* the value constraint value */
963     xmlSchemaNodeInfoPtr parent;
964 };
965 
966 
967 #define XML_SCHEMA_VALID_CTXT_FLAG_STREAM 1
968 /**
969  * xmlSchemaValidCtxt:
970  *
971  * A Schemas validation context
972  */
973 struct _xmlSchemaValidCtxt {
974     int type;
975     void *errCtxt;             /* user specific data block */
976     xmlSchemaValidityErrorFunc error;   /* the callback in case of errors */
977     xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
978     xmlStructuredErrorFunc serror;
979 
980     xmlSchemaPtr schema;        /* The schema in use */
981     xmlDocPtr doc;
982     xmlParserInputBufferPtr input;
983     xmlCharEncoding enc;
984     xmlSAXHandlerPtr sax;
985     xmlParserCtxtPtr parserCtxt;
986     void *user_data; /* TODO: What is this for? */
987     char *filename;
988 
989     int err;
990     int nberrors;
991 
992     xmlNodePtr node;
993     xmlNodePtr cur;
994     /* xmlSchemaTypePtr type; */
995 
996     xmlRegExecCtxtPtr regexp;
997     xmlSchemaValPtr value;
998 
999     int valueWS;
1000     int options;
1001     xmlNodePtr validationRoot;
1002     xmlSchemaParserCtxtPtr pctxt;
1003     int xsiAssemble;
1004 
1005     int depth;
1006     xmlSchemaNodeInfoPtr *elemInfos; /* array of element information */
1007     int sizeElemInfos;
1008     xmlSchemaNodeInfoPtr inode; /* the current element information */
1009 
1010     xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC information */
1011 
1012     xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
1013     xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
1014     xmlSchemaIDCMatcherPtr idcMatcherCache; /* Cache for IDC matcher objects. */
1015 
1016     xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
1017     int nbIdcNodes;
1018     int sizeIdcNodes;
1019 
1020     xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
1021     int nbIdcKeys;
1022     int sizeIdcKeys;
1023 
1024     int flags;
1025 
1026     xmlDictPtr dict;
1027 
1028 #ifdef LIBXML_READER_ENABLED
1029     xmlTextReaderPtr reader;
1030 #endif
1031 
1032     xmlSchemaAttrInfoPtr *attrInfos;
1033     int nbAttrInfos;
1034     int sizeAttrInfos;
1035 
1036     int skipDepth;
1037     xmlSchemaItemListPtr nodeQNames;
1038     int hasKeyrefs;
1039     int createIDCNodeTables;
1040     int psviExposeIDCNodeTables;
1041 
1042     /* Locator for error reporting in streaming mode */
1043     xmlSchemaValidityLocatorFunc locFunc;
1044     void *locCtxt;
1045 };
1046 
1047 /**
1048  * xmlSchemaSubstGroup:
1049  *
1050  *
1051  */
1052 typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup;
1053 typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr;
1054 struct _xmlSchemaSubstGroup {
1055     xmlSchemaElementPtr head;
1056     xmlSchemaItemListPtr members;
1057 };
1058 
1059 /**
1060  * xmlIDCHashEntry:
1061  *
1062  * an entry in hash tables to quickly look up keys/uniques
1063  */
1064 typedef struct _xmlIDCHashEntry xmlIDCHashEntry;
1065 typedef xmlIDCHashEntry *xmlIDCHashEntryPtr;
1066 struct _xmlIDCHashEntry {
1067     xmlIDCHashEntryPtr next; /* next item with same hash */
1068     int index;               /* index into associated item list */
1069 };
1070 
1071 /************************************************************************
1072  *									*
1073  *			Some predeclarations				*
1074  *									*
1075  ************************************************************************/
1076 
1077 static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
1078                                  xmlSchemaPtr schema,
1079                                  xmlNodePtr node);
1080 static int xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr ctxt,
1081                                  xmlSchemaPtr schema,
1082                                  xmlNodePtr node);
1083 static int
1084 xmlSchemaTypeFixup(xmlSchemaTypePtr type,
1085                    xmlSchemaAbstractCtxtPtr ctxt);
1086 static const xmlChar *
1087 xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
1088 static int
1089 xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1090                      xmlNodePtr node);
1091 static int
1092 xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
1093                        xmlSchemaParserCtxtPtr ctxt);
1094 static void
1095 xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
1096 static xmlSchemaWhitespaceValueType
1097 xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
1098 static xmlSchemaTreeItemPtr
1099 xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1100 			 xmlNodePtr node, xmlSchemaTypeType type,
1101 			 int withParticle);
1102 static const xmlChar *
1103 xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item);
1104 static xmlSchemaTypeLinkPtr
1105 xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
1106 static void
1107 xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
1108 		     const char *funcName,
1109 		     const char *message) LIBXML_ATTR_FORMAT(3,0);
1110 static int
1111 xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr ctxt,
1112 			     xmlSchemaTypePtr type,
1113 			     xmlSchemaTypePtr baseType,
1114 			     int subset);
1115 static void
1116 xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
1117 				   xmlSchemaParserCtxtPtr ctxt);
1118 static void
1119 xmlSchemaComponentListFree(xmlSchemaItemListPtr list);
1120 static xmlSchemaQNameRefPtr
1121 xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
1122 				xmlSchemaPtr schema,
1123 				xmlNodePtr node);
1124 
1125 /************************************************************************
1126  *									*
1127  *			Helper functions			        *
1128  *									*
1129  ************************************************************************/
1130 
1131 /**
1132  * xmlSchemaItemTypeToStr:
1133  * @type: the type of the schema item
1134  *
1135  * Returns the component name of a schema item.
1136  */
1137 static const xmlChar *
xmlSchemaItemTypeToStr(xmlSchemaTypeType type)1138 xmlSchemaItemTypeToStr(xmlSchemaTypeType type)
1139 {
1140     switch (type) {
1141 	case XML_SCHEMA_TYPE_BASIC:
1142 	    return(BAD_CAST "simple type definition");
1143 	case XML_SCHEMA_TYPE_SIMPLE:
1144 	    return(BAD_CAST "simple type definition");
1145 	case XML_SCHEMA_TYPE_COMPLEX:
1146 	    return(BAD_CAST "complex type definition");
1147 	case XML_SCHEMA_TYPE_ELEMENT:
1148 	    return(BAD_CAST "element declaration");
1149 	case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1150 	    return(BAD_CAST "attribute use");
1151 	case XML_SCHEMA_TYPE_ATTRIBUTE:
1152 	    return(BAD_CAST "attribute declaration");
1153 	case XML_SCHEMA_TYPE_GROUP:
1154 	    return(BAD_CAST "model group definition");
1155 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1156 	    return(BAD_CAST "attribute group definition");
1157 	case XML_SCHEMA_TYPE_NOTATION:
1158 	    return(BAD_CAST "notation declaration");
1159 	case XML_SCHEMA_TYPE_SEQUENCE:
1160 	    return(BAD_CAST "model group (sequence)");
1161 	case XML_SCHEMA_TYPE_CHOICE:
1162 	    return(BAD_CAST "model group (choice)");
1163 	case XML_SCHEMA_TYPE_ALL:
1164 	    return(BAD_CAST "model group (all)");
1165 	case XML_SCHEMA_TYPE_PARTICLE:
1166 	    return(BAD_CAST "particle");
1167 	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1168 	    return(BAD_CAST "unique identity-constraint");
1169 	    /* return(BAD_CAST "IDC (unique)"); */
1170 	case XML_SCHEMA_TYPE_IDC_KEY:
1171 	    return(BAD_CAST "key identity-constraint");
1172 	    /* return(BAD_CAST "IDC (key)"); */
1173 	case XML_SCHEMA_TYPE_IDC_KEYREF:
1174 	    return(BAD_CAST "keyref identity-constraint");
1175 	    /* return(BAD_CAST "IDC (keyref)"); */
1176 	case XML_SCHEMA_TYPE_ANY:
1177 	    return(BAD_CAST "wildcard (any)");
1178 	case XML_SCHEMA_EXTRA_QNAMEREF:
1179 	    return(BAD_CAST "[helper component] QName reference");
1180 	case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
1181 	    return(BAD_CAST "[helper component] attribute use prohibition");
1182 	default:
1183 	    return(BAD_CAST "Not a schema component");
1184     }
1185 }
1186 
1187 /**
1188  * xmlSchemaGetComponentTypeStr:
1189  * @type: the type of the schema item
1190  *
1191  * Returns the component name of a schema item.
1192  */
1193 static const xmlChar *
xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item)1194 xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item)
1195 {
1196     switch (item->type) {
1197 	case XML_SCHEMA_TYPE_BASIC:
1198 	    if (WXS_IS_COMPLEX(WXS_TYPE_CAST item))
1199 		return(BAD_CAST "complex type definition");
1200 	    else
1201 		return(BAD_CAST "simple type definition");
1202 	default:
1203 	    return(xmlSchemaItemTypeToStr(item->type));
1204     }
1205 }
1206 
1207 /**
1208  * xmlSchemaGetComponentNode:
1209  * @item: a schema component
1210  *
1211  * Returns node associated with the schema component.
1212  * NOTE that such a node need not be available; plus, a component's
1213  * node need not to reflect the component directly, since there is no
1214  * one-to-one relationship between the XML Schema representation and
1215  * the component representation.
1216  */
1217 static xmlNodePtr
xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)1218 xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
1219 {
1220     switch (item->type) {
1221 	case XML_SCHEMA_TYPE_ELEMENT:
1222 	    return (((xmlSchemaElementPtr) item)->node);
1223 	case XML_SCHEMA_TYPE_ATTRIBUTE:
1224 	    return (((xmlSchemaAttributePtr) item)->node);
1225 	case XML_SCHEMA_TYPE_COMPLEX:
1226 	case XML_SCHEMA_TYPE_SIMPLE:
1227 	    return (((xmlSchemaTypePtr) item)->node);
1228 	case XML_SCHEMA_TYPE_ANY:
1229 	case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1230 	    return (((xmlSchemaWildcardPtr) item)->node);
1231 	case XML_SCHEMA_TYPE_PARTICLE:
1232 	    return (((xmlSchemaParticlePtr) item)->node);
1233 	case XML_SCHEMA_TYPE_SEQUENCE:
1234 	case XML_SCHEMA_TYPE_CHOICE:
1235 	case XML_SCHEMA_TYPE_ALL:
1236 	    return (((xmlSchemaModelGroupPtr) item)->node);
1237 	case XML_SCHEMA_TYPE_GROUP:
1238 	    return (((xmlSchemaModelGroupDefPtr) item)->node);
1239 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1240 	    return (((xmlSchemaAttributeGroupPtr) item)->node);
1241 	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1242 	case XML_SCHEMA_TYPE_IDC_KEY:
1243 	case XML_SCHEMA_TYPE_IDC_KEYREF:
1244 	    return (((xmlSchemaIDCPtr) item)->node);
1245 	case XML_SCHEMA_EXTRA_QNAMEREF:
1246 	    return(((xmlSchemaQNameRefPtr) item)->node);
1247 	/* TODO: What to do with NOTATIONs?
1248 	case XML_SCHEMA_TYPE_NOTATION:
1249 	    return (((xmlSchemaNotationPtr) item)->node);
1250 	*/
1251 	case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1252 	    return (((xmlSchemaAttributeUsePtr) item)->node);
1253 	default:
1254 	    return (NULL);
1255     }
1256 }
1257 
1258 #if 0
1259 /**
1260  * xmlSchemaGetNextComponent:
1261  * @item: a schema component
1262  *
1263  * Returns the next sibling of the schema component.
1264  */
1265 static xmlSchemaBasicItemPtr
1266 xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
1267 {
1268     switch (item->type) {
1269 	case XML_SCHEMA_TYPE_ELEMENT:
1270 	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
1271 	case XML_SCHEMA_TYPE_ATTRIBUTE:
1272 	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
1273 	case XML_SCHEMA_TYPE_COMPLEX:
1274 	case XML_SCHEMA_TYPE_SIMPLE:
1275 	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
1276 	case XML_SCHEMA_TYPE_ANY:
1277 	case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1278 	    return (NULL);
1279 	case XML_SCHEMA_TYPE_PARTICLE:
1280 	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
1281 	case XML_SCHEMA_TYPE_SEQUENCE:
1282 	case XML_SCHEMA_TYPE_CHOICE:
1283 	case XML_SCHEMA_TYPE_ALL:
1284 	    return (NULL);
1285 	case XML_SCHEMA_TYPE_GROUP:
1286 	    return (NULL);
1287 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1288 	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
1289 	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1290 	case XML_SCHEMA_TYPE_IDC_KEY:
1291 	case XML_SCHEMA_TYPE_IDC_KEYREF:
1292 	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
1293 	default:
1294 	    return (NULL);
1295     }
1296 }
1297 #endif
1298 
1299 
1300 /**
1301  * xmlSchemaFormatQName:
1302  * @buf: the string buffer
1303  * @namespaceName:  the namespace name
1304  * @localName: the local name
1305  *
1306  * Returns the given QName in the format "{namespaceName}localName" or
1307  * just "localName" if @namespaceName is NULL.
1308  *
1309  * Returns the localName if @namespaceName is NULL, a formatted
1310  * string otherwise.
1311  */
1312 static const xmlChar*
xmlSchemaFormatQName(xmlChar ** buf,const xmlChar * namespaceName,const xmlChar * localName)1313 xmlSchemaFormatQName(xmlChar **buf,
1314 		     const xmlChar *namespaceName,
1315 		     const xmlChar *localName)
1316 {
1317     FREE_AND_NULL(*buf)
1318     if (namespaceName != NULL) {
1319 	*buf = xmlStrdup(BAD_CAST "{");
1320 	*buf = xmlStrcat(*buf, namespaceName);
1321 	*buf = xmlStrcat(*buf, BAD_CAST "}");
1322     }
1323     if (localName != NULL) {
1324 	if (namespaceName == NULL)
1325 	    return(localName);
1326 	*buf = xmlStrcat(*buf, localName);
1327     } else {
1328 	*buf = xmlStrcat(*buf, BAD_CAST "(NULL)");
1329     }
1330     return ((const xmlChar *) *buf);
1331 }
1332 
1333 static const xmlChar*
xmlSchemaFormatQNameNs(xmlChar ** buf,xmlNsPtr ns,const xmlChar * localName)1334 xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName)
1335 {
1336     if (ns != NULL)
1337 	return (xmlSchemaFormatQName(buf, ns->href, localName));
1338     else
1339 	return (xmlSchemaFormatQName(buf, NULL, localName));
1340 }
1341 
1342 static const xmlChar *
xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)1343 xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
1344 {
1345     switch (item->type) {
1346 	case XML_SCHEMA_TYPE_ELEMENT:
1347 	    return (((xmlSchemaElementPtr) item)->name);
1348 	case XML_SCHEMA_TYPE_ATTRIBUTE:
1349 	    return (((xmlSchemaAttributePtr) item)->name);
1350 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1351 	    return (((xmlSchemaAttributeGroupPtr) item)->name);
1352 	case XML_SCHEMA_TYPE_BASIC:
1353 	case XML_SCHEMA_TYPE_SIMPLE:
1354 	case XML_SCHEMA_TYPE_COMPLEX:
1355 	    return (((xmlSchemaTypePtr) item)->name);
1356 	case XML_SCHEMA_TYPE_GROUP:
1357 	    return (((xmlSchemaModelGroupDefPtr) item)->name);
1358 	case XML_SCHEMA_TYPE_IDC_KEY:
1359 	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1360 	case XML_SCHEMA_TYPE_IDC_KEYREF:
1361 	    return (((xmlSchemaIDCPtr) item)->name);
1362 	case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1363 	    if (WXS_ATTRUSE_DECL(item) != NULL) {
1364 		return(xmlSchemaGetComponentName(
1365 		    WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1366 	    } else
1367 		return(NULL);
1368 	case XML_SCHEMA_EXTRA_QNAMEREF:
1369 	    return (((xmlSchemaQNameRefPtr) item)->name);
1370 	case XML_SCHEMA_TYPE_NOTATION:
1371 	    return (((xmlSchemaNotationPtr) item)->name);
1372 	default:
1373 	    /*
1374 	    * Other components cannot have names.
1375 	    */
1376 	    break;
1377     }
1378     return (NULL);
1379 }
1380 
1381 #define xmlSchemaGetQNameRefName(r) (WXS_QNAME_CAST (r))->name
1382 #define xmlSchemaGetQNameRefTargetNs(r) (WXS_QNAME_CAST (r))->targetNamespace
1383 /*
1384 static const xmlChar *
1385 xmlSchemaGetQNameRefName(void *ref)
1386 {
1387     return(((xmlSchemaQNameRefPtr) ref)->name);
1388 }
1389 
1390 static const xmlChar *
1391 xmlSchemaGetQNameRefTargetNs(void *ref)
1392 {
1393     return(((xmlSchemaQNameRefPtr) ref)->targetNamespace);
1394 }
1395 */
1396 
1397 static const xmlChar *
xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)1398 xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
1399 {
1400     switch (item->type) {
1401 	case XML_SCHEMA_TYPE_ELEMENT:
1402 	    return (((xmlSchemaElementPtr) item)->targetNamespace);
1403 	case XML_SCHEMA_TYPE_ATTRIBUTE:
1404 	    return (((xmlSchemaAttributePtr) item)->targetNamespace);
1405 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1406 	    return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
1407 	case XML_SCHEMA_TYPE_BASIC:
1408 	    return (BAD_CAST "http://www.w3.org/2001/XMLSchema");
1409 	case XML_SCHEMA_TYPE_SIMPLE:
1410 	case XML_SCHEMA_TYPE_COMPLEX:
1411 	    return (((xmlSchemaTypePtr) item)->targetNamespace);
1412 	case XML_SCHEMA_TYPE_GROUP:
1413 	    return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1414 	case XML_SCHEMA_TYPE_IDC_KEY:
1415 	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1416 	case XML_SCHEMA_TYPE_IDC_KEYREF:
1417 	    return (((xmlSchemaIDCPtr) item)->targetNamespace);
1418 	case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1419 	    if (WXS_ATTRUSE_DECL(item) != NULL) {
1420 		return(xmlSchemaGetComponentTargetNs(
1421 		    WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1422 	    }
1423 	    /* TODO: Will returning NULL break something? */
1424 	    break;
1425 	case XML_SCHEMA_EXTRA_QNAMEREF:
1426 	    return (((xmlSchemaQNameRefPtr) item)->targetNamespace);
1427 	case XML_SCHEMA_TYPE_NOTATION:
1428 	    return (((xmlSchemaNotationPtr) item)->targetNamespace);
1429 	default:
1430 	    /*
1431 	    * Other components cannot have names.
1432 	    */
1433 	    break;
1434     }
1435     return (NULL);
1436 }
1437 
1438 static const xmlChar*
xmlSchemaGetComponentQName(xmlChar ** buf,void * item)1439 xmlSchemaGetComponentQName(xmlChar **buf,
1440 			   void *item)
1441 {
1442     return (xmlSchemaFormatQName(buf,
1443 	xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1444 	xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1445 }
1446 
1447 static const xmlChar*
xmlSchemaGetComponentDesignation(xmlChar ** buf,void * item)1448 xmlSchemaGetComponentDesignation(xmlChar **buf, void *item)
1449 {
1450     xmlChar *str = NULL;
1451 
1452     *buf = xmlStrcat(*buf, WXS_ITEM_TYPE_NAME(item));
1453     *buf = xmlStrcat(*buf, BAD_CAST " '");
1454     *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str,
1455 	(xmlSchemaBasicItemPtr) item));
1456     *buf = xmlStrcat(*buf, BAD_CAST "'");
1457     FREE_AND_NULL(str);
1458     return(*buf);
1459 }
1460 
1461 static const xmlChar*
xmlSchemaGetIDCDesignation(xmlChar ** buf,xmlSchemaIDCPtr idc)1462 xmlSchemaGetIDCDesignation(xmlChar **buf, xmlSchemaIDCPtr idc)
1463 {
1464     return(xmlSchemaGetComponentDesignation(buf, idc));
1465 }
1466 
1467 /**
1468  * xmlSchemaWildcardPCToString:
1469  * @pc: the type of processContents
1470  *
1471  * Returns a string representation of the type of
1472  * processContents.
1473  */
1474 static const xmlChar *
xmlSchemaWildcardPCToString(int pc)1475 xmlSchemaWildcardPCToString(int pc)
1476 {
1477     switch (pc) {
1478 	case XML_SCHEMAS_ANY_SKIP:
1479 	    return (BAD_CAST "skip");
1480 	case XML_SCHEMAS_ANY_LAX:
1481 	    return (BAD_CAST "lax");
1482 	case XML_SCHEMAS_ANY_STRICT:
1483 	    return (BAD_CAST "strict");
1484 	default:
1485 	    return (BAD_CAST "invalid process contents");
1486     }
1487 }
1488 
1489 /**
1490  * xmlSchemaGetCanonValueWhtspExt:
1491  * @val: the precomputed value
1492  * @retValue: the returned value
1493  * @ws: the whitespace type of the value
1494  * @for_hash: non-zero if this is supposed to generate a string for hashing
1495  *
1496  * Get a the canonical representation of the value.
1497  * The caller has to free the returned retValue.
1498  *
1499  * Returns 0 if the value could be built and -1 in case of
1500  *         API errors or if the value type is not supported yet.
1501  */
1502 static int
xmlSchemaGetCanonValueWhtspExt_1(xmlSchemaValPtr val,xmlSchemaWhitespaceValueType ws,xmlChar ** retValue,int for_hash)1503 xmlSchemaGetCanonValueWhtspExt_1(xmlSchemaValPtr val,
1504 			         xmlSchemaWhitespaceValueType ws,
1505 			         xmlChar **retValue,
1506 				 int for_hash)
1507 {
1508     int list;
1509     xmlSchemaValType valType;
1510     const xmlChar *value, *value2 = NULL;
1511 
1512 
1513     if ((retValue == NULL) || (val == NULL))
1514 	return (-1);
1515     list = xmlSchemaValueGetNext(val) ? 1 : 0;
1516     *retValue = NULL;
1517     do {
1518 	value = NULL;
1519 	valType = xmlSchemaGetValType(val);
1520 	switch (valType) {
1521 	    case XML_SCHEMAS_STRING:
1522 	    case XML_SCHEMAS_NORMSTRING:
1523 	    case XML_SCHEMAS_ANYSIMPLETYPE:
1524 		value = xmlSchemaValueGetAsString(val);
1525 		if (value != NULL) {
1526 		    if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1527 			value2 = xmlSchemaCollapseString(value);
1528 		    else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1529 			value2 = xmlSchemaWhiteSpaceReplace(value);
1530 		    if (value2 != NULL)
1531 			value = value2;
1532 		}
1533 		break;
1534 	    default:
1535 		if (xmlSchemaGetCanonValue(val, &value2) == -1) {
1536 		    if (value2 != NULL)
1537 			xmlFree((xmlChar *) value2);
1538 		    goto internal_error;
1539 		}
1540 		if (for_hash && valType == XML_SCHEMAS_DECIMAL) {
1541 		    /* We can mostly use the canonical value for hashing,
1542 		       except in the case of decimal.  There the canonical
1543 		       representation requires a trailing '.0' even for
1544 		       non-fractional numbers, but for the derived integer
1545 		       types it forbids any decimal point.  Nevertheless they
1546 		       compare equal if the value is equal.  We need to generate
1547 		       the same hash value for this to work, and it's easiest
1548 		       to just cut off the useless '.0' suffix for the
1549 		       decimal type.  */
1550 		    int len = xmlStrlen(value2);
1551 		    if (len > 2 && value2[len-1] == '0' && value2[len-2] == '.')
1552 		      ((xmlChar*)value2)[len-2] = 0;
1553 		}
1554 		value = value2;
1555 	}
1556 	if (*retValue == NULL)
1557 	    if (value == NULL) {
1558 		if (! list)
1559 		    *retValue = xmlStrdup(BAD_CAST "");
1560 	    } else
1561 		*retValue = xmlStrdup(value);
1562 	else if (value != NULL) {
1563 	    /* List. */
1564 	    *retValue = xmlStrcat((xmlChar *) *retValue, BAD_CAST " ");
1565 	    *retValue = xmlStrcat((xmlChar *) *retValue, value);
1566 	}
1567 	FREE_AND_NULL(value2)
1568 	val = xmlSchemaValueGetNext(val);
1569     } while (val != NULL);
1570 
1571     return (0);
1572 internal_error:
1573     if (*retValue != NULL)
1574 	xmlFree((xmlChar *) (*retValue));
1575     if (value2 != NULL)
1576 	xmlFree((xmlChar *) value2);
1577     return (-1);
1578 }
1579 
1580 static int
xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,xmlSchemaWhitespaceValueType ws,xmlChar ** retValue)1581 xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
1582 			       xmlSchemaWhitespaceValueType ws,
1583 			       xmlChar **retValue)
1584 {
1585     return xmlSchemaGetCanonValueWhtspExt_1(val, ws, retValue, 0);
1586 }
1587 
1588 static int
xmlSchemaGetCanonValueHash(xmlSchemaValPtr val,xmlChar ** retValue)1589 xmlSchemaGetCanonValueHash(xmlSchemaValPtr val,
1590 			   xmlChar **retValue)
1591 {
1592     return xmlSchemaGetCanonValueWhtspExt_1(val, XML_SCHEMA_WHITESPACE_COLLAPSE,
1593 					    retValue, 1);
1594 }
1595 
1596 /**
1597  * xmlSchemaFormatItemForReport:
1598  * @buf: the string buffer
1599  * @itemDes: the designation of the item
1600  * @itemName: the name of the item
1601  * @item: the item as an object
1602  * @itemNode: the node of the item
1603  * @local: the local name
1604  * @parsing: if the function is used during the parse
1605  *
1606  * Returns a representation of the given item used
1607  * for error reports.
1608  *
1609  * The following order is used to build the resulting
1610  * designation if the arguments are not NULL:
1611  * 1a. If itemDes not NULL -> itemDes
1612  * 1b. If (itemDes not NULL) and (itemName not NULL)
1613  *     -> itemDes + itemName
1614  * 2. If the preceding was NULL and (item not NULL) -> item
1615  * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
1616  *
1617  * If the itemNode is an attribute node, the name of the attribute
1618  * will be appended to the result.
1619  *
1620  * Returns the formatted string and sets @buf to the resulting value.
1621  */
1622 static xmlChar*
xmlSchemaFormatItemForReport(xmlChar ** buf,const xmlChar * itemDes,xmlSchemaBasicItemPtr item,xmlNodePtr itemNode)1623 xmlSchemaFormatItemForReport(xmlChar **buf,
1624 		     const xmlChar *itemDes,
1625 		     xmlSchemaBasicItemPtr item,
1626 		     xmlNodePtr itemNode)
1627 {
1628     xmlChar *str = NULL;
1629     int named = 1;
1630 
1631     if (*buf != NULL) {
1632 	xmlFree(*buf);
1633 	*buf = NULL;
1634     }
1635 
1636     if (itemDes != NULL) {
1637 	*buf = xmlStrdup(itemDes);
1638     } else if (item != NULL) {
1639 	switch (item->type) {
1640 	case XML_SCHEMA_TYPE_BASIC: {
1641 	    xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1642 
1643 	    if (WXS_IS_ATOMIC(type))
1644 		*buf = xmlStrdup(BAD_CAST "atomic type 'xs:");
1645 	    else if (WXS_IS_LIST(type))
1646 		*buf = xmlStrdup(BAD_CAST "list type 'xs:");
1647 	    else if (WXS_IS_UNION(type))
1648 		*buf = xmlStrdup(BAD_CAST "union type 'xs:");
1649 	    else
1650 		*buf = xmlStrdup(BAD_CAST "simple type 'xs:");
1651 	    *buf = xmlStrcat(*buf, type->name);
1652 	    *buf = xmlStrcat(*buf, BAD_CAST "'");
1653 	    }
1654 	    break;
1655 	case XML_SCHEMA_TYPE_SIMPLE: {
1656 	    xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1657 
1658 	    if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1659 		*buf = xmlStrdup(BAD_CAST"");
1660 	    } else {
1661 		*buf = xmlStrdup(BAD_CAST "local ");
1662 	    }
1663 	    if (WXS_IS_ATOMIC(type))
1664 		*buf = xmlStrcat(*buf, BAD_CAST "atomic type");
1665 	    else if (WXS_IS_LIST(type))
1666 		*buf = xmlStrcat(*buf, BAD_CAST "list type");
1667 	    else if (WXS_IS_UNION(type))
1668 		*buf = xmlStrcat(*buf, BAD_CAST "union type");
1669 	    else
1670 		*buf = xmlStrcat(*buf, BAD_CAST "simple type");
1671 	    if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1672 		*buf = xmlStrcat(*buf, BAD_CAST " '");
1673 		*buf = xmlStrcat(*buf, type->name);
1674 		*buf = xmlStrcat(*buf, BAD_CAST "'");
1675 	    }
1676 	    }
1677 	    break;
1678 	case XML_SCHEMA_TYPE_COMPLEX: {
1679 	    xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1680 
1681 	    if (type->flags & XML_SCHEMAS_TYPE_GLOBAL)
1682 		*buf = xmlStrdup(BAD_CAST "");
1683 	    else
1684 		*buf = xmlStrdup(BAD_CAST "local ");
1685 	    *buf = xmlStrcat(*buf, BAD_CAST "complex type");
1686 	    if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1687 		*buf = xmlStrcat(*buf, BAD_CAST " '");
1688 		*buf = xmlStrcat(*buf, type->name);
1689 		*buf = xmlStrcat(*buf, BAD_CAST "'");
1690 	    }
1691 	    }
1692 	    break;
1693 	case XML_SCHEMA_TYPE_ATTRIBUTE_USE: {
1694 		xmlSchemaAttributeUsePtr ause;
1695 
1696 		ause = WXS_ATTR_USE_CAST item;
1697 		*buf = xmlStrdup(BAD_CAST "attribute use ");
1698 		if (WXS_ATTRUSE_DECL(ause) != NULL) {
1699 		    *buf = xmlStrcat(*buf, BAD_CAST "'");
1700 		    *buf = xmlStrcat(*buf,
1701 			xmlSchemaGetComponentQName(&str, WXS_ATTRUSE_DECL(ause)));
1702 		    FREE_AND_NULL(str)
1703 			*buf = xmlStrcat(*buf, BAD_CAST "'");
1704 		} else {
1705 		    *buf = xmlStrcat(*buf, BAD_CAST "(unknown)");
1706 		}
1707 	    }
1708 	    break;
1709 	case XML_SCHEMA_TYPE_ATTRIBUTE: {
1710 		xmlSchemaAttributePtr attr;
1711 
1712 		attr = (xmlSchemaAttributePtr) item;
1713 		*buf = xmlStrdup(BAD_CAST "attribute decl.");
1714 		*buf = xmlStrcat(*buf, BAD_CAST " '");
1715 		*buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1716 		    attr->targetNamespace, attr->name));
1717 		FREE_AND_NULL(str)
1718 		    *buf = xmlStrcat(*buf, BAD_CAST "'");
1719 	    }
1720 	    break;
1721 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1722 	    xmlSchemaGetComponentDesignation(buf, item);
1723 	    break;
1724 	case XML_SCHEMA_TYPE_ELEMENT: {
1725 		xmlSchemaElementPtr elem;
1726 
1727 		elem = (xmlSchemaElementPtr) item;
1728 		*buf = xmlStrdup(BAD_CAST "element decl.");
1729 		*buf = xmlStrcat(*buf, BAD_CAST " '");
1730 		*buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1731 		    elem->targetNamespace, elem->name));
1732 		*buf = xmlStrcat(*buf, BAD_CAST "'");
1733 	    }
1734 	    break;
1735 	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1736 	case XML_SCHEMA_TYPE_IDC_KEY:
1737 	case XML_SCHEMA_TYPE_IDC_KEYREF:
1738 	    if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1739 		*buf = xmlStrdup(BAD_CAST "unique '");
1740 	    else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1741 		*buf = xmlStrdup(BAD_CAST "key '");
1742 	    else
1743 		*buf = xmlStrdup(BAD_CAST "keyRef '");
1744 	    *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1745 	    *buf = xmlStrcat(*buf, BAD_CAST "'");
1746 	    break;
1747 	case XML_SCHEMA_TYPE_ANY:
1748 	case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1749 	    *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1750 		    ((xmlSchemaWildcardPtr) item)->processContents));
1751 	    *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1752 	    break;
1753 	case XML_SCHEMA_FACET_MININCLUSIVE:
1754 	case XML_SCHEMA_FACET_MINEXCLUSIVE:
1755 	case XML_SCHEMA_FACET_MAXINCLUSIVE:
1756 	case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1757 	case XML_SCHEMA_FACET_TOTALDIGITS:
1758 	case XML_SCHEMA_FACET_FRACTIONDIGITS:
1759 	case XML_SCHEMA_FACET_PATTERN:
1760 	case XML_SCHEMA_FACET_ENUMERATION:
1761 	case XML_SCHEMA_FACET_WHITESPACE:
1762 	case XML_SCHEMA_FACET_LENGTH:
1763 	case XML_SCHEMA_FACET_MAXLENGTH:
1764 	case XML_SCHEMA_FACET_MINLENGTH:
1765 	    *buf = xmlStrdup(BAD_CAST "facet '");
1766 	    *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1767 	    *buf = xmlStrcat(*buf, BAD_CAST "'");
1768 	    break;
1769 	case XML_SCHEMA_TYPE_GROUP: {
1770 		*buf = xmlStrdup(BAD_CAST "model group def.");
1771 		*buf = xmlStrcat(*buf, BAD_CAST " '");
1772 		*buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1773 		*buf = xmlStrcat(*buf, BAD_CAST "'");
1774 		FREE_AND_NULL(str)
1775 	    }
1776 	    break;
1777 	case XML_SCHEMA_TYPE_SEQUENCE:
1778 	case XML_SCHEMA_TYPE_CHOICE:
1779 	case XML_SCHEMA_TYPE_ALL:
1780 	case XML_SCHEMA_TYPE_PARTICLE:
1781 	    *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1782 	    break;
1783 	case XML_SCHEMA_TYPE_NOTATION: {
1784 		*buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1785 		*buf = xmlStrcat(*buf, BAD_CAST " '");
1786 		*buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1787 		*buf = xmlStrcat(*buf, BAD_CAST "'");
1788 		FREE_AND_NULL(str);
1789 	    }
1790             /* Falls through. */
1791 	default:
1792 	    named = 0;
1793 	}
1794     } else
1795 	named = 0;
1796 
1797     if ((named == 0) && (itemNode != NULL)) {
1798 	xmlNodePtr elem;
1799 
1800 	if (itemNode->type == XML_ATTRIBUTE_NODE)
1801 	    elem = itemNode->parent;
1802 	else
1803 	    elem = itemNode;
1804 	*buf = xmlStrdup(BAD_CAST "Element '");
1805 	if (elem->ns != NULL) {
1806 	    *buf = xmlStrcat(*buf,
1807 		xmlSchemaFormatQName(&str, elem->ns->href, elem->name));
1808 	    FREE_AND_NULL(str)
1809 	} else
1810 	    *buf = xmlStrcat(*buf, elem->name);
1811 	*buf = xmlStrcat(*buf, BAD_CAST "'");
1812 
1813     }
1814     if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1815 	*buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1816 	if (itemNode->ns != NULL) {
1817 	    *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1818 		itemNode->ns->href, itemNode->name));
1819 	    FREE_AND_NULL(str)
1820 	} else
1821 	    *buf = xmlStrcat(*buf, itemNode->name);
1822 	*buf = xmlStrcat(*buf, BAD_CAST "'");
1823     }
1824     FREE_AND_NULL(str)
1825 
1826     return (xmlEscapeFormatString(buf));
1827 }
1828 
1829 /**
1830  * xmlSchemaFormatFacetEnumSet:
1831  * @buf: the string buffer
1832  * @type: the type holding the enumeration facets
1833  *
1834  * Builds a string consisting of all enumeration elements.
1835  *
1836  * Returns a string of all enumeration elements.
1837  */
1838 static const xmlChar *
xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,xmlChar ** buf,xmlSchemaTypePtr type)1839 xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,
1840 			    xmlChar **buf, xmlSchemaTypePtr type)
1841 {
1842     xmlSchemaFacetPtr facet;
1843     xmlSchemaWhitespaceValueType ws;
1844     xmlChar *value = NULL;
1845     int res, found = 0;
1846 
1847     if (*buf != NULL)
1848 	xmlFree(*buf);
1849     *buf = NULL;
1850 
1851     do {
1852 	/*
1853 	* Use the whitespace type of the base type.
1854 	*/
1855 	ws = xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
1856 	for (facet = type->facets; facet != NULL; facet = facet->next) {
1857 	    if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1858 		continue;
1859 	    found = 1;
1860 	    res = xmlSchemaGetCanonValueWhtspExt(facet->val,
1861 		ws, &value);
1862 	    if (res == -1) {
1863 		xmlSchemaInternalErr(actxt,
1864 		    "xmlSchemaFormatFacetEnumSet",
1865 		    "compute the canonical lexical representation");
1866 		if (*buf != NULL)
1867 		    xmlFree(*buf);
1868 		*buf = NULL;
1869 		return (NULL);
1870 	    }
1871 	    if (*buf == NULL)
1872 		*buf = xmlStrdup(BAD_CAST "'");
1873 	    else
1874 		*buf = xmlStrcat(*buf, BAD_CAST ", '");
1875 	    *buf = xmlStrcat(*buf, BAD_CAST value);
1876 	    *buf = xmlStrcat(*buf, BAD_CAST "'");
1877 	    if (value != NULL) {
1878 		xmlFree((xmlChar *)value);
1879 		value = NULL;
1880 	    }
1881 	}
1882 	/*
1883 	* The enumeration facet of a type restricts the enumeration
1884 	* facet of the ancestor type; i.e., such restricted enumerations
1885 	* do not belong to the set of the given type. Thus we break
1886 	* on the first found enumeration.
1887 	*/
1888 	if (found)
1889 	    break;
1890 	type = type->baseType;
1891     } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
1892 
1893     return ((const xmlChar *) *buf);
1894 }
1895 
1896 /************************************************************************
1897  *									*
1898  *			Error functions				        *
1899  *									*
1900  ************************************************************************/
1901 
1902 #if 0
1903 static void
1904 xmlSchemaErrMemory(const char *msg)
1905 {
1906     __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1907                      msg);
1908 }
1909 #endif
1910 
1911 static void
xmlSchemaPSimpleErr(const char * msg)1912 xmlSchemaPSimpleErr(const char *msg)
1913 {
1914     __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1915                      msg);
1916 }
1917 
1918 /**
1919  * xmlSchemaPErrMemory:
1920  * @node: a context node
1921  * @extra:  extra information
1922  *
1923  * Handle an out of memory condition
1924  */
1925 static void
xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,const char * extra,xmlNodePtr node)1926 xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
1927                     const char *extra, xmlNodePtr node)
1928 {
1929     if (ctxt != NULL)
1930         ctxt->nberrors++;
1931     __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
1932                      extra);
1933 }
1934 
1935 /**
1936  * xmlSchemaPErr:
1937  * @ctxt: the parsing context
1938  * @node: the context node
1939  * @error: the error code
1940  * @msg: the error message
1941  * @str1: extra data
1942  * @str2: extra data
1943  *
1944  * Handle a parser error
1945  */
1946 static void LIBXML_ATTR_FORMAT(4,0)
xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int error,const char * msg,const xmlChar * str1,const xmlChar * str2)1947 xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1948               const char *msg, const xmlChar * str1, const xmlChar * str2)
1949 {
1950     xmlGenericErrorFunc channel = NULL;
1951     xmlStructuredErrorFunc schannel = NULL;
1952     void *data = NULL;
1953 
1954     if (ctxt != NULL) {
1955         ctxt->nberrors++;
1956 	ctxt->err = error;
1957         channel = ctxt->error;
1958         data = ctxt->errCtxt;
1959 	schannel = ctxt->serror;
1960     }
1961     __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1962                     error, XML_ERR_ERROR, NULL, 0,
1963                     (const char *) str1, (const char *) str2, NULL, 0, 0,
1964                     msg, str1, str2);
1965 }
1966 
1967 /**
1968  * xmlSchemaPErr2:
1969  * @ctxt: the parsing context
1970  * @node: the context node
1971  * @node: the current child
1972  * @error: the error code
1973  * @msg: the error message
1974  * @str1: extra data
1975  * @str2: extra data
1976  *
1977  * Handle a parser error
1978  */
1979 static void LIBXML_ATTR_FORMAT(5,0)
xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,xmlNodePtr child,int error,const char * msg,const xmlChar * str1,const xmlChar * str2)1980 xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1981                xmlNodePtr child, int error,
1982                const char *msg, const xmlChar * str1, const xmlChar * str2)
1983 {
1984     if (child != NULL)
1985         xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
1986     else
1987         xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
1988 }
1989 
1990 
1991 /**
1992  * xmlSchemaPErrExt:
1993  * @ctxt: the parsing context
1994  * @node: the context node
1995  * @error: the error code
1996  * @strData1: extra data
1997  * @strData2: extra data
1998  * @strData3: extra data
1999  * @msg: the message
2000  * @str1:  extra parameter for the message display
2001  * @str2:  extra parameter for the message display
2002  * @str3:  extra parameter for the message display
2003  * @str4:  extra parameter for the message display
2004  * @str5:  extra parameter for the message display
2005  *
2006  * Handle a parser error
2007  */
2008 static void LIBXML_ATTR_FORMAT(7,0)
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)2009 xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
2010 		const xmlChar * strData1, const xmlChar * strData2,
2011 		const xmlChar * strData3, const char *msg, const xmlChar * str1,
2012 		const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
2013 		const xmlChar * str5)
2014 {
2015 
2016     xmlGenericErrorFunc channel = NULL;
2017     xmlStructuredErrorFunc schannel = NULL;
2018     void *data = NULL;
2019 
2020     if (ctxt != NULL) {
2021         ctxt->nberrors++;
2022 	ctxt->err = error;
2023         channel = ctxt->error;
2024         data = ctxt->errCtxt;
2025 	schannel = ctxt->serror;
2026     }
2027     __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
2028                     error, XML_ERR_ERROR, NULL, 0,
2029                     (const char *) strData1, (const char *) strData2,
2030 		    (const char *) strData3, 0, 0, msg, str1, str2,
2031 		    str3, str4, str5);
2032 }
2033 
2034 /************************************************************************
2035  *									*
2036  *			Allround error functions			*
2037  *									*
2038  ************************************************************************/
2039 
2040 /**
2041  * xmlSchemaVTypeErrMemory:
2042  * @node: a context node
2043  * @extra:  extra information
2044  *
2045  * Handle an out of memory condition
2046  */
2047 static void
xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,const char * extra,xmlNodePtr node)2048 xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
2049                     const char *extra, xmlNodePtr node)
2050 {
2051     if (ctxt != NULL) {
2052         ctxt->nberrors++;
2053         ctxt->err = XML_SCHEMAV_INTERNAL;
2054     }
2055     __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
2056                      extra);
2057 }
2058 
2059 static void LIBXML_ATTR_FORMAT(2,0)
xmlSchemaPSimpleInternalErr(xmlNodePtr node,const char * msg,const xmlChar * str)2060 xmlSchemaPSimpleInternalErr(xmlNodePtr node,
2061 			    const char *msg, const xmlChar *str)
2062 {
2063      __xmlSimpleError(XML_FROM_SCHEMASP, XML_SCHEMAP_INTERNAL, node,
2064 	 msg, (const char *) str);
2065 }
2066 
2067 #define WXS_ERROR_TYPE_ERROR 1
2068 #define WXS_ERROR_TYPE_WARNING 2
2069 /**
2070  * xmlSchemaErr4Line:
2071  * @ctxt: the validation context
2072  * @errorLevel: the error level
2073  * @error: the error code
2074  * @node: the context node
2075  * @line: the line number
2076  * @msg: the error message
2077  * @str1: extra data
2078  * @str2: extra data
2079  * @str3: extra data
2080  * @str4: extra data
2081  *
2082  * Handle a validation error
2083  */
2084 static void LIBXML_ATTR_FORMAT(6,0)
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)2085 xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt,
2086 		  xmlErrorLevel errorLevel,
2087 		  int error, xmlNodePtr node, int line, const char *msg,
2088 		  const xmlChar *str1, const xmlChar *str2,
2089 		  const xmlChar *str3, const xmlChar *str4)
2090 {
2091     xmlStructuredErrorFunc schannel = NULL;
2092     xmlGenericErrorFunc channel = NULL;
2093     void *data = NULL;
2094 
2095     if (ctxt != NULL) {
2096 	if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2097 	    xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
2098 	    const char *file = NULL;
2099 	    int col = 0;
2100 	    if (errorLevel != XML_ERR_WARNING) {
2101 		vctxt->nberrors++;
2102 		vctxt->err = error;
2103 		channel = vctxt->error;
2104 	    } else {
2105 		channel = vctxt->warning;
2106 	    }
2107 	    schannel = vctxt->serror;
2108 	    data = vctxt->errCtxt;
2109 
2110 	    /*
2111 	    * Error node. If we specify a line number, then
2112 	    * do not channel any node to the error function.
2113 	    */
2114 	    if (line == 0) {
2115 		if ((node == NULL) &&
2116 		    (vctxt->depth >= 0) &&
2117 		    (vctxt->inode != NULL)) {
2118 		    node = vctxt->inode->node;
2119 		}
2120 		/*
2121 		* Get filename and line if no node-tree.
2122 		*/
2123 		if ((node == NULL) &&
2124 		    (vctxt->parserCtxt != NULL) &&
2125 		    (vctxt->parserCtxt->input != NULL)) {
2126 		    file = vctxt->parserCtxt->input->filename;
2127 		    line = vctxt->parserCtxt->input->line;
2128 		    col = vctxt->parserCtxt->input->col;
2129 		}
2130 	    } else {
2131 		/*
2132 		* Override the given node's (if any) position
2133 		* and channel only the given line number.
2134 		*/
2135 		node = NULL;
2136 		/*
2137 		* Get filename.
2138 		*/
2139 		if (vctxt->doc != NULL)
2140 		    file = (const char *) vctxt->doc->URL;
2141 		else if ((vctxt->parserCtxt != NULL) &&
2142 		    (vctxt->parserCtxt->input != NULL))
2143 		    file = vctxt->parserCtxt->input->filename;
2144 	    }
2145 	    if (vctxt->locFunc != NULL) {
2146 	        if ((file == NULL) || (line == 0)) {
2147 		    unsigned long l;
2148 		    const char *f;
2149 		    vctxt->locFunc(vctxt->locCtxt, &f, &l);
2150 		    if (file == NULL)
2151 		        file = f;
2152 		    if (line == 0)
2153 		        line = (int) l;
2154 		}
2155 	    }
2156 	    if ((file == NULL) && (vctxt->filename != NULL))
2157 	        file = vctxt->filename;
2158 
2159 	    __xmlRaiseError(schannel, channel, data, ctxt,
2160 		node, XML_FROM_SCHEMASV,
2161 		error, errorLevel, file, line,
2162 		(const char *) str1, (const char *) str2,
2163 		(const char *) str3, 0, col, msg, str1, str2, str3, str4);
2164 
2165 	} else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
2166 	    xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
2167 	    if (errorLevel != XML_ERR_WARNING) {
2168 		pctxt->nberrors++;
2169 		pctxt->err = error;
2170 		channel = pctxt->error;
2171 	    } else {
2172 		channel = pctxt->warning;
2173 	    }
2174 	    schannel = pctxt->serror;
2175 	    data = pctxt->errCtxt;
2176 	    __xmlRaiseError(schannel, channel, data, ctxt,
2177 		node, XML_FROM_SCHEMASP, error,
2178 		errorLevel, NULL, 0,
2179 		(const char *) str1, (const char *) str2,
2180 		(const char *) str3, 0, 0, msg, str1, str2, str3, str4);
2181 	} else {
2182 	    TODO
2183 	}
2184     }
2185 }
2186 
2187 /**
2188  * xmlSchemaErr3:
2189  * @ctxt: the validation context
2190  * @node: the context node
2191  * @error: the error code
2192  * @msg: the error message
2193  * @str1: extra data
2194  * @str2: extra data
2195  * @str3: extra data
2196  *
2197  * Handle a validation error
2198  */
2199 static void LIBXML_ATTR_FORMAT(4,0)
xmlSchemaErr3(xmlSchemaAbstractCtxtPtr actxt,int error,xmlNodePtr node,const char * msg,const xmlChar * str1,const xmlChar * str2,const xmlChar * str3)2200 xmlSchemaErr3(xmlSchemaAbstractCtxtPtr actxt,
2201 	      int error, xmlNodePtr node, const char *msg,
2202 	      const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
2203 {
2204     xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2205 	msg, str1, str2, str3, NULL);
2206 }
2207 
2208 static void LIBXML_ATTR_FORMAT(4,0)
xmlSchemaErr4(xmlSchemaAbstractCtxtPtr actxt,int error,xmlNodePtr node,const char * msg,const xmlChar * str1,const xmlChar * str2,const xmlChar * str3,const xmlChar * str4)2209 xmlSchemaErr4(xmlSchemaAbstractCtxtPtr actxt,
2210 	      int error, xmlNodePtr node, const char *msg,
2211 	      const xmlChar *str1, const xmlChar *str2,
2212 	      const xmlChar *str3, const xmlChar *str4)
2213 {
2214     xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2215 	msg, str1, str2, str3, str4);
2216 }
2217 
2218 static void LIBXML_ATTR_FORMAT(4,0)
xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,int error,xmlNodePtr node,const char * msg,const xmlChar * str1,const xmlChar * str2)2219 xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
2220 	     int error, xmlNodePtr node, const char *msg,
2221 	     const xmlChar *str1, const xmlChar *str2)
2222 {
2223     xmlSchemaErr4(actxt, error, node, msg, str1, str2, NULL, NULL);
2224 }
2225 
2226 static xmlChar *
xmlSchemaFormatNodeForError(xmlChar ** msg,xmlSchemaAbstractCtxtPtr actxt,xmlNodePtr node)2227 xmlSchemaFormatNodeForError(xmlChar ** msg,
2228 			    xmlSchemaAbstractCtxtPtr actxt,
2229 			    xmlNodePtr node)
2230 {
2231     xmlChar *str = NULL;
2232 
2233     *msg = NULL;
2234     if ((node != NULL) &&
2235 	(node->type != XML_ELEMENT_NODE) &&
2236 	(node->type != XML_ATTRIBUTE_NODE))
2237     {
2238 	/*
2239 	* Don't try to format other nodes than element and
2240 	* attribute nodes.
2241 	* Play safe and return an empty string.
2242 	*/
2243 	*msg = xmlStrdup(BAD_CAST "");
2244 	return(*msg);
2245     }
2246     if (node != NULL) {
2247 	/*
2248 	* Work on tree nodes.
2249 	*/
2250 	if (node->type == XML_ATTRIBUTE_NODE) {
2251 	    xmlNodePtr elem = node->parent;
2252 
2253 	    *msg = xmlStrdup(BAD_CAST "Element '");
2254 	    if (elem->ns != NULL)
2255 		*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2256 		    elem->ns->href, elem->name));
2257 	    else
2258 		*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2259 		    NULL, elem->name));
2260 	    FREE_AND_NULL(str);
2261 	    *msg = xmlStrcat(*msg, BAD_CAST "', ");
2262 	    *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2263 	} else {
2264 	    *msg = xmlStrdup(BAD_CAST "Element '");
2265 	}
2266 	if (node->ns != NULL)
2267 	    *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2268 	    node->ns->href, node->name));
2269 	else
2270 	    *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2271 	    NULL, node->name));
2272 	FREE_AND_NULL(str);
2273 	*msg = xmlStrcat(*msg, BAD_CAST "': ");
2274     } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2275 	xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
2276 	/*
2277 	* Work on node infos.
2278 	*/
2279 	if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
2280 	    xmlSchemaNodeInfoPtr ielem =
2281 		vctxt->elemInfos[vctxt->depth];
2282 
2283 	    *msg = xmlStrdup(BAD_CAST "Element '");
2284 	    *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2285 		ielem->nsName, ielem->localName));
2286 	    FREE_AND_NULL(str);
2287 	    *msg = xmlStrcat(*msg, BAD_CAST "', ");
2288 	    *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2289 	} else {
2290 	    *msg = xmlStrdup(BAD_CAST "Element '");
2291 	}
2292 	*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2293 	    vctxt->inode->nsName, vctxt->inode->localName));
2294 	FREE_AND_NULL(str);
2295 	*msg = xmlStrcat(*msg, BAD_CAST "': ");
2296     } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
2297 	/*
2298 	* Hmm, no node while parsing?
2299 	* Return an empty string, in case NULL will break something.
2300 	*/
2301 	*msg = xmlStrdup(BAD_CAST "");
2302     } else {
2303 	TODO
2304 	return (NULL);
2305     }
2306 
2307     /*
2308      * xmlSchemaFormatItemForReport() also returns an escaped format
2309      * string, so do this before calling it below (in the future).
2310      */
2311     xmlEscapeFormatString(msg);
2312 
2313     /*
2314     * VAL TODO: The output of the given schema component is currently
2315     * disabled.
2316     */
2317 #if 0
2318     if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
2319 	*msg = xmlStrcat(*msg, BAD_CAST " [");
2320 	*msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
2321 	    NULL, type, NULL, 0));
2322 	FREE_AND_NULL(str)
2323 	*msg = xmlStrcat(*msg, BAD_CAST "]");
2324     }
2325 #endif
2326     return (*msg);
2327 }
2328 
2329 static void LIBXML_ATTR_FORMAT(3,0)
xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,const char * funcName,const char * message,const xmlChar * str1,const xmlChar * str2)2330 xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,
2331 		     const char *funcName,
2332 		     const char *message,
2333 		     const xmlChar *str1,
2334 		     const xmlChar *str2)
2335 {
2336     xmlChar *msg = NULL;
2337 
2338     if (actxt == NULL)
2339         return;
2340     msg = xmlStrdup(BAD_CAST "Internal error: %s, ");
2341     msg = xmlStrcat(msg, BAD_CAST message);
2342     msg = xmlStrcat(msg, BAD_CAST ".\n");
2343 
2344     if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
2345 	xmlSchemaErr3(actxt, XML_SCHEMAV_INTERNAL, NULL,
2346 	    (const char *) msg, (const xmlChar *) funcName, str1, str2);
2347     else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
2348 	xmlSchemaErr3(actxt, XML_SCHEMAP_INTERNAL, NULL,
2349 	    (const char *) msg, (const xmlChar *) funcName, str1, str2);
2350 
2351     FREE_AND_NULL(msg)
2352 }
2353 
2354 static void LIBXML_ATTR_FORMAT(3,0)
xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,const char * funcName,const char * message)2355 xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
2356 		     const char *funcName,
2357 		     const char *message)
2358 {
2359     xmlSchemaInternalErr2(actxt, funcName, message, NULL, NULL);
2360 }
2361 
2362 #if 0
2363 static void LIBXML_ATTR_FORMAT(3,0)
2364 xmlSchemaPInternalErr(xmlSchemaParserCtxtPtr pctxt,
2365 		     const char *funcName,
2366 		     const char *message,
2367 		     const xmlChar *str1,
2368 		     const xmlChar *str2)
2369 {
2370     xmlSchemaInternalErr2(ACTXT_CAST pctxt, funcName, message,
2371 	str1, str2);
2372 }
2373 #endif
2374 
2375 static void LIBXML_ATTR_FORMAT(5,0)
xmlSchemaCustomErr4(xmlSchemaAbstractCtxtPtr actxt,xmlParserErrors error,xmlNodePtr node,xmlSchemaBasicItemPtr item,const char * message,const xmlChar * str1,const xmlChar * str2,const xmlChar * str3,const xmlChar * str4)2376 xmlSchemaCustomErr4(xmlSchemaAbstractCtxtPtr actxt,
2377 		   xmlParserErrors error,
2378 		   xmlNodePtr node,
2379 		   xmlSchemaBasicItemPtr item,
2380 		   const char *message,
2381 		   const xmlChar *str1, const xmlChar *str2,
2382 		   const xmlChar *str3, const xmlChar *str4)
2383 {
2384     xmlChar *msg = NULL;
2385 
2386     if ((node == NULL) && (item != NULL) &&
2387 	(actxt->type == XML_SCHEMA_CTXT_PARSER)) {
2388 	node = WXS_ITEM_NODE(item);
2389 	xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2390 	msg = xmlStrcat(msg, BAD_CAST ": ");
2391     } else
2392 	xmlSchemaFormatNodeForError(&msg, actxt, node);
2393     msg = xmlStrcat(msg, (const xmlChar *) message);
2394     msg = xmlStrcat(msg, BAD_CAST ".\n");
2395     xmlSchemaErr4(actxt, error, node,
2396 	(const char *) msg, str1, str2, str3, str4);
2397     FREE_AND_NULL(msg)
2398 }
2399 
2400 static void LIBXML_ATTR_FORMAT(5,0)
xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,xmlParserErrors error,xmlNodePtr node,xmlSchemaBasicItemPtr item,const char * message,const xmlChar * str1,const xmlChar * str2)2401 xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
2402 		   xmlParserErrors error,
2403 		   xmlNodePtr node,
2404 		   xmlSchemaBasicItemPtr item,
2405 		   const char *message,
2406 		   const xmlChar *str1,
2407 		   const xmlChar *str2)
2408 {
2409     xmlSchemaCustomErr4(actxt, error, node, item,
2410 	message, str1, str2, NULL, NULL);
2411 }
2412 
2413 
2414 
2415 static void LIBXML_ATTR_FORMAT(5,0)
xmlSchemaCustomWarning(xmlSchemaAbstractCtxtPtr actxt,xmlParserErrors error,xmlNodePtr node,xmlSchemaTypePtr type ATTRIBUTE_UNUSED,const char * message,const xmlChar * str1,const xmlChar * str2,const xmlChar * str3)2416 xmlSchemaCustomWarning(xmlSchemaAbstractCtxtPtr actxt,
2417 		   xmlParserErrors error,
2418 		   xmlNodePtr node,
2419 		   xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2420 		   const char *message,
2421 		   const xmlChar *str1,
2422 		   const xmlChar *str2,
2423 		   const xmlChar *str3)
2424 {
2425     xmlChar *msg = NULL;
2426 
2427     xmlSchemaFormatNodeForError(&msg, actxt, node);
2428     msg = xmlStrcat(msg, (const xmlChar *) message);
2429     msg = xmlStrcat(msg, BAD_CAST ".\n");
2430 
2431     /* URGENT TODO: Set the error code to something sane. */
2432     xmlSchemaErr4Line(actxt, XML_ERR_WARNING, error, node, 0,
2433 	(const char *) msg, str1, str2, str3, NULL);
2434 
2435     FREE_AND_NULL(msg)
2436 }
2437 
2438 
2439 
2440 static void LIBXML_ATTR_FORMAT(5,0)
xmlSchemaKeyrefErr(xmlSchemaValidCtxtPtr vctxt,xmlParserErrors error,xmlSchemaPSVIIDCNodePtr idcNode,xmlSchemaTypePtr type ATTRIBUTE_UNUSED,const char * message,const xmlChar * str1,const xmlChar * str2)2441 xmlSchemaKeyrefErr(xmlSchemaValidCtxtPtr vctxt,
2442 		   xmlParserErrors error,
2443 		   xmlSchemaPSVIIDCNodePtr idcNode,
2444 		   xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2445 		   const char *message,
2446 		   const xmlChar *str1,
2447 		   const xmlChar *str2)
2448 {
2449     xmlChar *msg = NULL, *qname = NULL;
2450 
2451     msg = xmlStrdup(BAD_CAST "Element '%s': ");
2452     msg = xmlStrcat(msg, (const xmlChar *) message);
2453     msg = xmlStrcat(msg, BAD_CAST ".\n");
2454     xmlSchemaErr4Line(ACTXT_CAST vctxt, XML_ERR_ERROR,
2455 	error, NULL, idcNode->nodeLine, (const char *) msg,
2456 	xmlSchemaFormatQName(&qname,
2457 	    vctxt->nodeQNames->items[idcNode->nodeQNameID +1],
2458 	    vctxt->nodeQNames->items[idcNode->nodeQNameID]),
2459 	str1, str2, NULL);
2460     FREE_AND_NULL(qname);
2461     FREE_AND_NULL(msg);
2462 }
2463 
2464 static int
xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,xmlNodePtr node)2465 xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
2466 			   xmlNodePtr node)
2467 {
2468     if (node != NULL)
2469 	return (node->type);
2470     if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
2471 	(((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
2472 	return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
2473     return (-1);
2474 }
2475 
2476 static int
xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)2477 xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
2478 {
2479     switch (item->type) {
2480 	case XML_SCHEMA_TYPE_COMPLEX:
2481 	case XML_SCHEMA_TYPE_SIMPLE:
2482 	    if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2483 		return(1);
2484 	    break;
2485 	case XML_SCHEMA_TYPE_GROUP:
2486 	    return (1);
2487 	case XML_SCHEMA_TYPE_ELEMENT:
2488 	    if ( ((xmlSchemaElementPtr) item)->flags &
2489 		XML_SCHEMAS_ELEM_GLOBAL)
2490 		return(1);
2491 	    break;
2492 	case XML_SCHEMA_TYPE_ATTRIBUTE:
2493 	    if ( ((xmlSchemaAttributePtr) item)->flags &
2494 		XML_SCHEMAS_ATTR_GLOBAL)
2495 		return(1);
2496 	    break;
2497 	/* Note that attribute groups are always global. */
2498 	default:
2499 	    return(1);
2500     }
2501     return (0);
2502 }
2503 
2504 static void
xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,xmlParserErrors error,xmlNodePtr node,const xmlChar * value,xmlSchemaTypePtr type,int displayValue)2505 xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2506 		       xmlParserErrors error,
2507 		       xmlNodePtr node,
2508 		       const xmlChar *value,
2509 		       xmlSchemaTypePtr type,
2510 		       int displayValue)
2511 {
2512     xmlChar *msg = NULL;
2513 
2514     xmlSchemaFormatNodeForError(&msg, actxt, node);
2515 
2516     if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2517 	    XML_ATTRIBUTE_NODE))
2518 	msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2519     else
2520 	msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
2521 	    "value of ");
2522 
2523     if (! xmlSchemaIsGlobalItem(type))
2524 	msg = xmlStrcat(msg, BAD_CAST "the local ");
2525     else
2526 	msg = xmlStrcat(msg, BAD_CAST "the ");
2527 
2528     if (WXS_IS_ATOMIC(type))
2529 	msg = xmlStrcat(msg, BAD_CAST "atomic type");
2530     else if (WXS_IS_LIST(type))
2531 	msg = xmlStrcat(msg, BAD_CAST "list type");
2532     else if (WXS_IS_UNION(type))
2533 	msg = xmlStrcat(msg, BAD_CAST "union type");
2534 
2535     if (xmlSchemaIsGlobalItem(type)) {
2536 	xmlChar *str = NULL;
2537 	msg = xmlStrcat(msg, BAD_CAST " '");
2538 	if (type->builtInType != 0) {
2539 	    msg = xmlStrcat(msg, BAD_CAST "xs:");
2540 	    str = xmlStrdup(type->name);
2541 	} else {
2542 	    const xmlChar *qName = xmlSchemaFormatQName(&str, type->targetNamespace, type->name);
2543 	    if (!str)
2544 		str = xmlStrdup(qName);
2545 	}
2546 	msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
2547 	msg = xmlStrcat(msg, BAD_CAST "'");
2548 	FREE_AND_NULL(str);
2549     }
2550     msg = xmlStrcat(msg, BAD_CAST ".\n");
2551     if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2552 	    XML_ATTRIBUTE_NODE))
2553 	xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2554     else
2555 	xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2556     FREE_AND_NULL(msg)
2557 }
2558 
2559 static const xmlChar *
xmlSchemaFormatErrorNodeQName(xmlChar ** str,xmlSchemaNodeInfoPtr ni,xmlNodePtr node)2560 xmlSchemaFormatErrorNodeQName(xmlChar ** str,
2561 			      xmlSchemaNodeInfoPtr ni,
2562 			      xmlNodePtr node)
2563 {
2564     if (node != NULL) {
2565 	if (node->ns != NULL)
2566 	    return (xmlSchemaFormatQName(str, node->ns->href, node->name));
2567 	else
2568 	    return (xmlSchemaFormatQName(str, NULL, node->name));
2569     } else if (ni != NULL)
2570 	return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
2571     return (NULL);
2572 }
2573 
2574 static void
xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,xmlParserErrors error,xmlSchemaAttrInfoPtr ni,xmlNodePtr node)2575 xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
2576 			xmlParserErrors error,
2577 			xmlSchemaAttrInfoPtr ni,
2578 			xmlNodePtr node)
2579 {
2580     xmlChar *msg = NULL, *str = NULL;
2581 
2582     xmlSchemaFormatNodeForError(&msg, actxt, node);
2583     msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
2584     xmlSchemaErr(actxt, error, node, (const char *) msg,
2585 	xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
2586 	NULL);
2587     FREE_AND_NULL(str)
2588     FREE_AND_NULL(msg)
2589 }
2590 
2591 static void LIBXML_ATTR_FORMAT(5,0)
xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,xmlParserErrors error,xmlNodePtr node,xmlSchemaTypePtr type ATTRIBUTE_UNUSED,const char * message,int nbval,int nbneg,xmlChar ** values)2592 xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2593 		        xmlParserErrors error,
2594 		        xmlNodePtr node,
2595 			xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2596 			const char *message,
2597 			int nbval,
2598 			int nbneg,
2599 			xmlChar **values)
2600 {
2601     xmlChar *str = NULL, *msg = NULL;
2602     xmlChar *localName, *nsName;
2603     const xmlChar *cur, *end;
2604     int i;
2605 
2606     xmlSchemaFormatNodeForError(&msg, actxt, node);
2607     msg = xmlStrcat(msg, (const xmlChar *) message);
2608     msg = xmlStrcat(msg, BAD_CAST ".");
2609     /*
2610     * Note that is does not make sense to report that we have a
2611     * wildcard here, since the wildcard might be unfolded into
2612     * multiple transitions.
2613     */
2614     if (nbval + nbneg > 0) {
2615 	if (nbval + nbneg > 1) {
2616 	    str = xmlStrdup(BAD_CAST " Expected is one of ( ");
2617 	} else
2618 	    str = xmlStrdup(BAD_CAST " Expected is ( ");
2619 	nsName = NULL;
2620 
2621 	for (i = 0; i < nbval + nbneg; i++) {
2622 	    cur = values[i];
2623 	    if (cur == NULL)
2624 	        continue;
2625 	    if ((cur[0] == 'n') && (cur[1] == 'o') && (cur[2] == 't') &&
2626 	        (cur[3] == ' ')) {
2627 		cur += 4;
2628 		str = xmlStrcat(str, BAD_CAST "##other");
2629 	    }
2630 	    /*
2631 	    * Get the local name.
2632 	    */
2633 	    localName = NULL;
2634 
2635 	    end = cur;
2636 	    if (*end == '*') {
2637 		localName = xmlStrdup(BAD_CAST "*");
2638 		end++;
2639 	    } else {
2640 		while ((*end != 0) && (*end != '|'))
2641 		    end++;
2642 		localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
2643 	    }
2644 	    if (*end != 0) {
2645 		end++;
2646 		/*
2647 		* Skip "*|*" if they come with negated expressions, since
2648 		* they represent the same negated wildcard.
2649 		*/
2650 		if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
2651 		    /*
2652 		    * Get the namespace name.
2653 		    */
2654 		    cur = end;
2655 		    if (*end == '*') {
2656 			nsName = xmlStrdup(BAD_CAST "{*}");
2657 		    } else {
2658 			while (*end != 0)
2659 			    end++;
2660 
2661 			if (i >= nbval)
2662 			    nsName = xmlStrdup(BAD_CAST "{##other:");
2663 			else
2664 			    nsName = xmlStrdup(BAD_CAST "{");
2665 
2666 			nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
2667 			nsName = xmlStrcat(nsName, BAD_CAST "}");
2668 		    }
2669 		    str = xmlStrcat(str, BAD_CAST nsName);
2670 		    FREE_AND_NULL(nsName)
2671 		} else {
2672 		    FREE_AND_NULL(localName);
2673 		    continue;
2674 		}
2675 	    }
2676 	    str = xmlStrcat(str, BAD_CAST localName);
2677 	    FREE_AND_NULL(localName);
2678 
2679 	    if (i < nbval + nbneg -1)
2680 		str = xmlStrcat(str, BAD_CAST ", ");
2681 	}
2682 	str = xmlStrcat(str, BAD_CAST " ).\n");
2683 	msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
2684 	FREE_AND_NULL(str)
2685     } else
2686       msg = xmlStrcat(msg, BAD_CAST "\n");
2687     xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2688     xmlFree(msg);
2689 }
2690 
2691 static void LIBXML_ATTR_FORMAT(8,0)
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)2692 xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
2693 		  xmlParserErrors error,
2694 		  xmlNodePtr node,
2695 		  const xmlChar *value,
2696 		  unsigned long length,
2697 		  xmlSchemaTypePtr type,
2698 		  xmlSchemaFacetPtr facet,
2699 		  const char *message,
2700 		  const xmlChar *str1,
2701 		  const xmlChar *str2)
2702 {
2703     xmlChar *str = NULL, *msg = NULL;
2704     xmlSchemaTypeType facetType;
2705     int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
2706 
2707     xmlSchemaFormatNodeForError(&msg, actxt, node);
2708     if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
2709 	facetType = XML_SCHEMA_FACET_ENUMERATION;
2710 	/*
2711 	* If enumerations are validated, one must not expect the
2712 	* facet to be given.
2713 	*/
2714     } else
2715 	facetType = facet->type;
2716     msg = xmlStrcat(msg, BAD_CAST "[");
2717     msg = xmlStrcat(msg, BAD_CAST "facet '");
2718     msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
2719     msg = xmlStrcat(msg, BAD_CAST "'] ");
2720     if (message == NULL) {
2721 	/*
2722 	* Use a default message.
2723 	*/
2724 	if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
2725 	    (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
2726 	    (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
2727 
2728 	    char len[25], actLen[25];
2729 
2730 	    /* FIXME, TODO: What is the max expected string length of the
2731 	    * this value?
2732 	    */
2733 	    if (nodeType == XML_ATTRIBUTE_NODE)
2734 		msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
2735 	    else
2736 		msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
2737 
2738 	    snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
2739 	    snprintf(actLen, 24, "%lu", length);
2740 
2741 	    if (facetType == XML_SCHEMA_FACET_LENGTH)
2742 		msg = xmlStrcat(msg,
2743 		BAD_CAST "this differs from the allowed length of '%s'.\n");
2744 	    else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
2745 		msg = xmlStrcat(msg,
2746 		BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2747 	    else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
2748 		msg = xmlStrcat(msg,
2749 		BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
2750 
2751 	    if (nodeType == XML_ATTRIBUTE_NODE)
2752 		xmlSchemaErr3(actxt, error, node, (const char *) msg,
2753 		    value, (const xmlChar *) actLen, (const xmlChar *) len);
2754 	    else
2755 		xmlSchemaErr(actxt, error, node, (const char *) msg,
2756 		    (const xmlChar *) actLen, (const xmlChar *) len);
2757 
2758 	} else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2759 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2760 		"of the set {%s}.\n");
2761 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2762 		xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2763 	} else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2764 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2765 		"by the pattern '%s'.\n");
2766 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2767 		facet->value);
2768 	} else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2769 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2770 		"minimum value allowed ('%s').\n");
2771 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2772 		facet->value);
2773 	} else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2774 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2775 		"maximum value allowed ('%s').\n");
2776 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2777 		facet->value);
2778 	} else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
2779 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be greater than "
2780 		"'%s'.\n");
2781 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2782 		facet->value);
2783 	} else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
2784 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
2785 		"'%s'.\n");
2786 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2787 		facet->value);
2788 	} else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2789 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2790 		"digits than are allowed ('%s').\n");
2791 	    xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2792 		facet->value);
2793 	} else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2794 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2795 		"digits than are allowed ('%s').\n");
2796 	    xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2797 		facet->value);
2798 	} else if (nodeType == XML_ATTRIBUTE_NODE) {
2799 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
2800 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2801 	} else {
2802 	    msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2803 	    xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2804 	}
2805     } else {
2806 	msg = xmlStrcat(msg, (const xmlChar *) message);
2807 	msg = xmlStrcat(msg, BAD_CAST ".\n");
2808 	xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
2809     }
2810     FREE_AND_NULL(str)
2811     xmlFree(msg);
2812 }
2813 
2814 #define VERROR(err, type, msg) \
2815     xmlSchemaCustomErr(ACTXT_CAST vctxt, err, NULL, type, msg, NULL, NULL);
2816 
2817 #define VERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST vctxt, func, msg);
2818 
2819 #define PERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST pctxt, func, msg);
2820 #define PERROR_INT2(func, msg) xmlSchemaInternalErr(ACTXT_CAST ctxt, func, msg);
2821 
2822 #define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2823 
2824 
2825 /**
2826  * xmlSchemaPMissingAttrErr:
2827  * @ctxt: the schema validation context
2828  * @ownerItem: the owner as a schema object
2829  * @ownerElem: the owner as an element node
2830  * @node: the parent element node of the missing attribute node
2831  * @type: the corresponding type of the attribute node
2832  *
2833  * Reports an illegal attribute.
2834  */
2835 static void
xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr ownerItem,xmlNodePtr ownerElem,const char * name,const char * message)2836 xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
2837 			 xmlParserErrors error,
2838 			 xmlSchemaBasicItemPtr ownerItem,
2839 			 xmlNodePtr ownerElem,
2840 			 const char *name,
2841 			 const char *message)
2842 {
2843     xmlChar *des = NULL;
2844 
2845     xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2846 
2847     if (message != NULL)
2848 	xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
2849     else
2850 	xmlSchemaPErr(ctxt, ownerElem, error,
2851 	    "%s: The attribute '%s' is required but missing.\n",
2852 	    BAD_CAST des, BAD_CAST name);
2853     FREE_AND_NULL(des);
2854 }
2855 
2856 
2857 /**
2858  * xmlSchemaPResCompAttrErr:
2859  * @ctxt: the schema validation context
2860  * @error: the error code
2861  * @ownerItem: the owner as a schema object
2862  * @ownerElem: the owner as an element node
2863  * @name: the name of the attribute holding the QName
2864  * @refName: the referenced local name
2865  * @refURI: the referenced namespace URI
2866  * @message: optional message
2867  *
2868  * Used to report QName attribute values that failed to resolve
2869  * to schema components.
2870  */
2871 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)2872 xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
2873 			 xmlParserErrors error,
2874 			 xmlSchemaBasicItemPtr ownerItem,
2875 			 xmlNodePtr ownerElem,
2876 			 const char *name,
2877 			 const xmlChar *refName,
2878 			 const xmlChar *refURI,
2879 			 xmlSchemaTypeType refType,
2880 			 const char *refTypeStr)
2881 {
2882     xmlChar *des = NULL, *strA = NULL;
2883 
2884     xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2885     if (refTypeStr == NULL)
2886 	refTypeStr = (const char *) xmlSchemaItemTypeToStr(refType);
2887     xmlSchemaPErrExt(ctxt, ownerElem, error,
2888 	    NULL, NULL, NULL,
2889 	    "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2890 	    "%s.\n", BAD_CAST des, BAD_CAST name,
2891 	    xmlSchemaFormatQName(&strA, refURI, refName),
2892 	    BAD_CAST refTypeStr, NULL);
2893     FREE_AND_NULL(des)
2894     FREE_AND_NULL(strA)
2895 }
2896 
2897 /**
2898  * xmlSchemaPCustomAttrErr:
2899  * @ctxt: the schema parser context
2900  * @error: the error code
2901  * @ownerDes: the designation of the owner
2902  * @ownerItem: the owner as a schema object
2903  * @attr: the illegal attribute node
2904  *
2905  * Reports an illegal attribute during the parse.
2906  */
2907 static void
xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlChar ** ownerDes,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,const char * msg)2908 xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
2909 			xmlParserErrors error,
2910 			xmlChar **ownerDes,
2911 			xmlSchemaBasicItemPtr ownerItem,
2912 			xmlAttrPtr attr,
2913 			const char *msg)
2914 {
2915     xmlChar *des = NULL;
2916 
2917     if (ownerDes == NULL)
2918 	xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
2919     else if (*ownerDes == NULL) {
2920 	xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
2921 	des = *ownerDes;
2922     } else
2923 	des = *ownerDes;
2924     if (attr == NULL) {
2925 	xmlSchemaPErrExt(ctxt, NULL, error, NULL, NULL, NULL,
2926 	    "%s, attribute '%s': %s.\n",
2927 	    BAD_CAST des, (const xmlChar *) "Unknown",
2928 	    (const xmlChar *) msg, NULL, NULL);
2929     } else {
2930 	xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
2931 	    "%s, attribute '%s': %s.\n",
2932 	    BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2933     }
2934     if (ownerDes == NULL)
2935 	FREE_AND_NULL(des);
2936 }
2937 
2938 /**
2939  * xmlSchemaPIllegalAttrErr:
2940  * @ctxt: the schema parser context
2941  * @error: the error code
2942  * @ownerItem: the attribute's owner item
2943  * @attr: the illegal attribute node
2944  *
2945  * Reports an illegal attribute during the parse.
2946  */
2947 static void
xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr ownerComp ATTRIBUTE_UNUSED,xmlAttrPtr attr)2948 xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
2949 			 xmlParserErrors error,
2950 			 xmlSchemaBasicItemPtr ownerComp ATTRIBUTE_UNUSED,
2951 			 xmlAttrPtr attr)
2952 {
2953     xmlChar *strA = NULL, *strB = NULL;
2954 
2955     xmlSchemaFormatNodeForError(&strA, ACTXT_CAST ctxt, attr->parent);
2956     xmlSchemaErr4(ACTXT_CAST ctxt, error, (xmlNodePtr) attr,
2957 	"%sThe attribute '%s' is not allowed.\n", BAD_CAST strA,
2958 	xmlSchemaFormatQNameNs(&strB, attr->ns, attr->name),
2959 	NULL, NULL);
2960     FREE_AND_NULL(strA);
2961     FREE_AND_NULL(strB);
2962 }
2963 
2964 /**
2965  * xmlSchemaPCustomErr:
2966  * @ctxt: the schema parser context
2967  * @error: the error code
2968  * @itemDes: the designation of the schema item
2969  * @item: the schema item
2970  * @itemElem: the node of the schema item
2971  * @message: the error message
2972  * @str1: an optional param for the error message
2973  * @str2: an optional param for the error message
2974  * @str3: an optional param for the error message
2975  *
2976  * Reports an error during parsing.
2977  */
2978 static void LIBXML_ATTR_FORMAT(5,0)
xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr item,xmlNodePtr itemElem,const char * message,const xmlChar * str1,const xmlChar * str2,const xmlChar * str3)2979 xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
2980 		    xmlParserErrors error,
2981 		    xmlSchemaBasicItemPtr item,
2982 		    xmlNodePtr itemElem,
2983 		    const char *message,
2984 		    const xmlChar *str1,
2985 		    const xmlChar *str2,
2986 		    const xmlChar *str3)
2987 {
2988     xmlChar *des = NULL, *msg = NULL;
2989 
2990     xmlSchemaFormatItemForReport(&des, NULL, item, itemElem);
2991     msg = xmlStrdup(BAD_CAST "%s: ");
2992     msg = xmlStrcat(msg, (const xmlChar *) message);
2993     msg = xmlStrcat(msg, BAD_CAST ".\n");
2994     if ((itemElem == NULL) && (item != NULL))
2995 	itemElem = WXS_ITEM_NODE(item);
2996     xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
2997 	(const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
2998     FREE_AND_NULL(des);
2999     FREE_AND_NULL(msg);
3000 }
3001 
3002 /**
3003  * xmlSchemaPCustomErr:
3004  * @ctxt: the schema parser context
3005  * @error: the error code
3006  * @itemDes: the designation of the schema item
3007  * @item: the schema item
3008  * @itemElem: the node of the schema item
3009  * @message: the error message
3010  * @str1: the optional param for the error message
3011  *
3012  * Reports an error during parsing.
3013  */
3014 static void LIBXML_ATTR_FORMAT(5,0)
xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr item,xmlNodePtr itemElem,const char * message,const xmlChar * str1)3015 xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
3016 		    xmlParserErrors error,
3017 		    xmlSchemaBasicItemPtr item,
3018 		    xmlNodePtr itemElem,
3019 		    const char *message,
3020 		    const xmlChar *str1)
3021 {
3022     xmlSchemaPCustomErrExt(ctxt, error, item, itemElem, message,
3023 	str1, NULL, NULL);
3024 }
3025 
3026 /**
3027  * xmlSchemaPAttrUseErr:
3028  * @ctxt: the schema parser context
3029  * @error: the error code
3030  * @itemDes: the designation of the schema type
3031  * @item: the schema type
3032  * @itemElem: the node of the schema type
3033  * @attr: the invalid schema attribute
3034  * @message: the error message
3035  * @str1: the optional param for the error message
3036  *
3037  * Reports an attribute use error during parsing.
3038  */
3039 static void LIBXML_ATTR_FORMAT(6,0)
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)3040 xmlSchemaPAttrUseErr4(xmlSchemaParserCtxtPtr ctxt,
3041 		    xmlParserErrors error,
3042 		    xmlNodePtr node,
3043 		    xmlSchemaBasicItemPtr ownerItem,
3044 		    const xmlSchemaAttributeUsePtr attruse,
3045 		    const char *message,
3046 		    const xmlChar *str1, const xmlChar *str2,
3047 		    const xmlChar *str3,const xmlChar *str4)
3048 {
3049     xmlChar *str = NULL, *msg = NULL;
3050 
3051     xmlSchemaFormatItemForReport(&msg, NULL, ownerItem, NULL);
3052     msg = xmlStrcat(msg, BAD_CAST ", ");
3053     msg = xmlStrcat(msg,
3054 	BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
3055 	WXS_BASIC_CAST attruse, NULL));
3056     FREE_AND_NULL(str);
3057     msg = xmlStrcat(msg, BAD_CAST ": ");
3058     msg = xmlStrcat(msg, (const xmlChar *) message);
3059     msg = xmlStrcat(msg, BAD_CAST ".\n");
3060     xmlSchemaErr4(ACTXT_CAST ctxt, error, node,
3061 	(const char *) msg, str1, str2, str3, str4);
3062     xmlFree(msg);
3063 }
3064 
3065 /**
3066  * xmlSchemaPIllegalFacetAtomicErr:
3067  * @ctxt: the schema parser context
3068  * @error: the error code
3069  * @type: the schema type
3070  * @baseType: the base type of type
3071  * @facet: the illegal facet
3072  *
3073  * Reports an illegal facet for atomic simple types.
3074  */
3075 static void
xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaTypePtr type,xmlSchemaTypePtr baseType,xmlSchemaFacetPtr facet)3076 xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
3077 			  xmlParserErrors error,
3078 			  xmlSchemaTypePtr type,
3079 			  xmlSchemaTypePtr baseType,
3080 			  xmlSchemaFacetPtr facet)
3081 {
3082     xmlChar *des = NULL, *strT = NULL;
3083 
3084     xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type, type->node);
3085     xmlSchemaPErrExt(ctxt, type->node, error, NULL, NULL, NULL,
3086 	"%s: The facet '%s' is not allowed on types derived from the "
3087 	"type %s.\n",
3088 	BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
3089 	xmlSchemaFormatItemForReport(&strT, NULL, WXS_BASIC_CAST baseType, NULL),
3090 	NULL, NULL);
3091     FREE_AND_NULL(des);
3092     FREE_AND_NULL(strT);
3093 }
3094 
3095 /**
3096  * xmlSchemaPIllegalFacetListUnionErr:
3097  * @ctxt: the schema parser context
3098  * @error: the error code
3099  * @itemDes: the designation of the schema item involved
3100  * @item: the schema item involved
3101  * @facet: the illegal facet
3102  *
3103  * Reports an illegal facet for <list> and <union>.
3104  */
3105 static void
xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaTypePtr type,xmlSchemaFacetPtr facet)3106 xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
3107 			  xmlParserErrors error,
3108 			  xmlSchemaTypePtr type,
3109 			  xmlSchemaFacetPtr facet)
3110 {
3111     xmlChar *des = NULL;
3112 
3113     xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type,
3114 	type->node);
3115     xmlSchemaPErr(ctxt, type->node, error,
3116 	"%s: The facet '%s' is not allowed.\n",
3117 	BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
3118     FREE_AND_NULL(des);
3119 }
3120 
3121 /**
3122  * xmlSchemaPMutualExclAttrErr:
3123  * @ctxt: the schema validation context
3124  * @error: the error code
3125  * @elemDes: the designation of the parent element node
3126  * @attr: the bad attribute node
3127  * @type: the corresponding type of the attribute node
3128  *
3129  * Reports an illegal attribute.
3130  */
3131 static void
xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,const char * name1,const char * name2)3132 xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
3133 			 xmlParserErrors error,
3134 			 xmlSchemaBasicItemPtr ownerItem,
3135 			 xmlAttrPtr attr,
3136 			 const char *name1,
3137 			 const char *name2)
3138 {
3139     xmlChar *des = NULL;
3140 
3141     xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST ownerItem, attr->parent);
3142     xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
3143 	"%s: The attributes '%s' and '%s' are mutually exclusive.\n",
3144 	BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
3145     FREE_AND_NULL(des);
3146 }
3147 
3148 /**
3149  * xmlSchemaPSimpleTypeErr:
3150  * @ctxt:  the schema validation context
3151  * @error: the error code
3152  * @type: the type specifier
3153  * @ownerItem: the schema object if existent
3154  * @node: the validated node
3155  * @value: the validated value
3156  *
3157  * Reports a simple type validation error.
3158  * TODO: Should this report the value of an element as well?
3159  */
3160 static void LIBXML_ATTR_FORMAT(8,0)
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)3161 xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
3162 			xmlParserErrors error,
3163 			xmlSchemaBasicItemPtr ownerItem ATTRIBUTE_UNUSED,
3164 			xmlNodePtr node,
3165 			xmlSchemaTypePtr type,
3166 			const char *expected,
3167 			const xmlChar *value,
3168 			const char *message,
3169 			const xmlChar *str1,
3170 			const xmlChar *str2)
3171 {
3172     xmlChar *msg = NULL;
3173 
3174     xmlSchemaFormatNodeForError(&msg, ACTXT_CAST ctxt, node);
3175     if (message == NULL) {
3176 	/*
3177 	* Use default messages.
3178 	*/
3179 	if (type != NULL) {
3180 	    if (node->type == XML_ATTRIBUTE_NODE)
3181 		msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
3182 	    else
3183 		msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
3184 		"valid value of ");
3185 	    if (! xmlSchemaIsGlobalItem(type))
3186 		msg = xmlStrcat(msg, BAD_CAST "the local ");
3187 	    else
3188 		msg = xmlStrcat(msg, BAD_CAST "the ");
3189 
3190 	    if (WXS_IS_ATOMIC(type))
3191 		msg = xmlStrcat(msg, BAD_CAST "atomic type");
3192 	    else if (WXS_IS_LIST(type))
3193 		msg = xmlStrcat(msg, BAD_CAST "list type");
3194 	    else if (WXS_IS_UNION(type))
3195 		msg = xmlStrcat(msg, BAD_CAST "union type");
3196 
3197 	    if (xmlSchemaIsGlobalItem(type)) {
3198 		xmlChar *str = NULL;
3199 		msg = xmlStrcat(msg, BAD_CAST " '");
3200 		if (type->builtInType != 0) {
3201 		    msg = xmlStrcat(msg, BAD_CAST "xs:");
3202 		    str = xmlStrdup(type->name);
3203 		} else {
3204 		    const xmlChar *qName = xmlSchemaFormatQName(&str, type->targetNamespace, type->name);
3205 		    if (!str)
3206 			str = xmlStrdup(qName);
3207 		}
3208 		msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
3209 		msg = xmlStrcat(msg, BAD_CAST "'.");
3210 		FREE_AND_NULL(str);
3211 	    }
3212 	} else {
3213 	    if (node->type == XML_ATTRIBUTE_NODE)
3214 		msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
3215 	    else
3216 		msg = xmlStrcat(msg, BAD_CAST "The character content is not "
3217 		"valid.");
3218 	}
3219 	if (expected) {
3220 	    xmlChar *expectedEscaped = xmlCharStrdup(expected);
3221 	    msg = xmlStrcat(msg, BAD_CAST " Expected is '");
3222 	    msg = xmlStrcat(msg, xmlEscapeFormatString(&expectedEscaped));
3223 	    FREE_AND_NULL(expectedEscaped);
3224 	    msg = xmlStrcat(msg, BAD_CAST "'.\n");
3225 	} else
3226 	    msg = xmlStrcat(msg, BAD_CAST "\n");
3227 	if (node->type == XML_ATTRIBUTE_NODE)
3228 	    xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
3229 	else
3230 	    xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
3231     } else {
3232 	msg = xmlStrcat(msg, BAD_CAST message);
3233 	msg = xmlStrcat(msg, BAD_CAST ".\n");
3234 	xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
3235 	     (const char*) msg, str1, str2, NULL, NULL, NULL);
3236     }
3237     /* Cleanup. */
3238     FREE_AND_NULL(msg)
3239 }
3240 
3241 /**
3242  * xmlSchemaPContentErr:
3243  * @ctxt: the schema parser context
3244  * @error: the error code
3245  * @ownerItem: the owner item of the holder of the content
3246  * @ownerElem: the node of the holder of the content
3247  * @child: the invalid child node
3248  * @message: the optional error message
3249  * @content: the optional string describing the correct content
3250  *
3251  * Reports an error concerning the content of a schema element.
3252  */
3253 static void
xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr ownerItem,xmlNodePtr ownerElem,xmlNodePtr child,const char * message,const char * content)3254 xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
3255 		     xmlParserErrors error,
3256 		     xmlSchemaBasicItemPtr ownerItem,
3257 		     xmlNodePtr ownerElem,
3258 		     xmlNodePtr child,
3259 		     const char *message,
3260 		     const char *content)
3261 {
3262     xmlChar *des = NULL;
3263 
3264     xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
3265     if (message != NULL)
3266 	xmlSchemaPErr2(ctxt, ownerElem, child, error,
3267 	    "%s: %s.\n",
3268 	    BAD_CAST des, BAD_CAST message);
3269     else {
3270 	if (content != NULL) {
3271 	    xmlSchemaPErr2(ctxt, ownerElem, child, error,
3272 		"%s: The content is not valid. Expected is %s.\n",
3273 		BAD_CAST des, BAD_CAST content);
3274 	} else {
3275 	    xmlSchemaPErr2(ctxt, ownerElem, child, error,
3276 		"%s: The content is not valid.\n",
3277 		BAD_CAST des, NULL);
3278 	}
3279     }
3280     FREE_AND_NULL(des)
3281 }
3282 
3283 /************************************************************************
3284  *									*
3285  *			Streamable error functions                      *
3286  *									*
3287  ************************************************************************/
3288 
3289 
3290 
3291 
3292 /************************************************************************
3293  *									*
3294  *			Validation helper functions			*
3295  *									*
3296  ************************************************************************/
3297 
3298 
3299 /************************************************************************
3300  *									*
3301  *			Allocation functions				*
3302  *									*
3303  ************************************************************************/
3304 
3305 /**
3306  * xmlSchemaNewSchemaForParserCtxt:
3307  * @ctxt:  a schema validation context
3308  *
3309  * Allocate a new Schema structure.
3310  *
3311  * Returns the newly allocated structure or NULL in case or error
3312  */
3313 static xmlSchemaPtr
xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)3314 xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
3315 {
3316     xmlSchemaPtr ret;
3317 
3318     ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
3319     if (ret == NULL) {
3320         xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
3321         return (NULL);
3322     }
3323     memset(ret, 0, sizeof(xmlSchema));
3324     ret->dict = ctxt->dict;
3325     xmlDictReference(ret->dict);
3326 
3327     return (ret);
3328 }
3329 
3330 /**
3331  * xmlSchemaNewFacet:
3332  *
3333  * Allocate a new Facet structure.
3334  *
3335  * Returns the newly allocated structure or NULL in case or error
3336  */
3337 xmlSchemaFacetPtr
xmlSchemaNewFacet(void)3338 xmlSchemaNewFacet(void)
3339 {
3340     xmlSchemaFacetPtr ret;
3341 
3342     ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
3343     if (ret == NULL) {
3344         return (NULL);
3345     }
3346     memset(ret, 0, sizeof(xmlSchemaFacet));
3347 
3348     return (ret);
3349 }
3350 
3351 /**
3352  * xmlSchemaNewAnnot:
3353  * @ctxt:  a schema validation context
3354  * @node:  a node
3355  *
3356  * Allocate a new annotation structure.
3357  *
3358  * Returns the newly allocated structure or NULL in case or error
3359  */
3360 static xmlSchemaAnnotPtr
xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node)3361 xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3362 {
3363     xmlSchemaAnnotPtr ret;
3364 
3365     ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
3366     if (ret == NULL) {
3367         xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
3368         return (NULL);
3369     }
3370     memset(ret, 0, sizeof(xmlSchemaAnnot));
3371     ret->content = node;
3372     return (ret);
3373 }
3374 
3375 static xmlSchemaItemListPtr
xmlSchemaItemListCreate(void)3376 xmlSchemaItemListCreate(void)
3377 {
3378     xmlSchemaItemListPtr ret;
3379 
3380     ret = xmlMalloc(sizeof(xmlSchemaItemList));
3381     if (ret == NULL) {
3382 	xmlSchemaPErrMemory(NULL,
3383 	    "allocating an item list structure", NULL);
3384 	return (NULL);
3385     }
3386     memset(ret, 0, sizeof(xmlSchemaItemList));
3387     return (ret);
3388 }
3389 
3390 static void
xmlSchemaItemListClear(xmlSchemaItemListPtr list)3391 xmlSchemaItemListClear(xmlSchemaItemListPtr list)
3392 {
3393     if (list->items != NULL) {
3394 	xmlFree(list->items);
3395 	list->items = NULL;
3396     }
3397     list->nbItems = 0;
3398     list->sizeItems = 0;
3399 }
3400 
3401 static int
xmlSchemaItemListAdd(xmlSchemaItemListPtr list,void * item)3402 xmlSchemaItemListAdd(xmlSchemaItemListPtr list, void *item)
3403 {
3404     if (list->items == NULL) {
3405 	list->items = (void **) xmlMalloc(
3406 	    20 * sizeof(void *));
3407 	if (list->items == NULL) {
3408 	    xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3409 	    return(-1);
3410 	}
3411 	list->sizeItems = 20;
3412     } else if (list->sizeItems <= list->nbItems) {
3413 	list->sizeItems *= 2;
3414 	list->items = (void **) xmlRealloc(list->items,
3415 	    list->sizeItems * sizeof(void *));
3416 	if (list->items == NULL) {
3417 	    xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3418 	    list->sizeItems = 0;
3419 	    return(-1);
3420 	}
3421     }
3422     list->items[list->nbItems++] = item;
3423     return(0);
3424 }
3425 
3426 static int
xmlSchemaItemListAddSize(xmlSchemaItemListPtr list,int initialSize,void * item)3427 xmlSchemaItemListAddSize(xmlSchemaItemListPtr list,
3428 			 int initialSize,
3429 			 void *item)
3430 {
3431     if (list->items == NULL) {
3432 	if (initialSize <= 0)
3433 	    initialSize = 1;
3434 	list->items = (void **) xmlMalloc(
3435 	    initialSize * sizeof(void *));
3436 	if (list->items == NULL) {
3437 	    xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3438 	    return(-1);
3439 	}
3440 	list->sizeItems = initialSize;
3441     } else if (list->sizeItems <= list->nbItems) {
3442 	list->sizeItems *= 2;
3443 	list->items = (void **) xmlRealloc(list->items,
3444 	    list->sizeItems * sizeof(void *));
3445 	if (list->items == NULL) {
3446 	    xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3447 	    list->sizeItems = 0;
3448 	    return(-1);
3449 	}
3450     }
3451     list->items[list->nbItems++] = item;
3452     return(0);
3453 }
3454 
3455 static int
xmlSchemaItemListInsert(xmlSchemaItemListPtr list,void * item,int idx)3456 xmlSchemaItemListInsert(xmlSchemaItemListPtr list, void *item, int idx)
3457 {
3458     if (list->items == NULL) {
3459 	list->items = (void **) xmlMalloc(
3460 	    20 * sizeof(void *));
3461 	if (list->items == NULL) {
3462 	    xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3463 	    return(-1);
3464 	}
3465 	list->sizeItems = 20;
3466     } else if (list->sizeItems <= list->nbItems) {
3467 	list->sizeItems *= 2;
3468 	list->items = (void **) xmlRealloc(list->items,
3469 	    list->sizeItems * sizeof(void *));
3470 	if (list->items == NULL) {
3471 	    xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3472 	    list->sizeItems = 0;
3473 	    return(-1);
3474 	}
3475     }
3476     /*
3477     * Just append if the index is greater/equal than the item count.
3478     */
3479     if (idx >= list->nbItems) {
3480 	list->items[list->nbItems++] = item;
3481     } else {
3482 	int i;
3483 	for (i = list->nbItems; i > idx; i--)
3484 	    list->items[i] = list->items[i-1];
3485 	list->items[idx] = item;
3486 	list->nbItems++;
3487     }
3488     return(0);
3489 }
3490 
3491 #if 0 /* enable if ever needed */
3492 static int
3493 xmlSchemaItemListInsertSize(xmlSchemaItemListPtr list,
3494 			    int initialSize,
3495 			    void *item,
3496 			    int idx)
3497 {
3498     if (list->items == NULL) {
3499 	if (initialSize <= 0)
3500 	    initialSize = 1;
3501 	list->items = (void **) xmlMalloc(
3502 	    initialSize * sizeof(void *));
3503 	if (list->items == NULL) {
3504 	    xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3505 	    return(-1);
3506 	}
3507 	list->sizeItems = initialSize;
3508     } else if (list->sizeItems <= list->nbItems) {
3509 	list->sizeItems *= 2;
3510 	list->items = (void **) xmlRealloc(list->items,
3511 	    list->sizeItems * sizeof(void *));
3512 	if (list->items == NULL) {
3513 	    xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3514 	    list->sizeItems = 0;
3515 	    return(-1);
3516 	}
3517     }
3518     /*
3519     * Just append if the index is greater/equal than the item count.
3520     */
3521     if (idx >= list->nbItems) {
3522 	list->items[list->nbItems++] = item;
3523     } else {
3524 	int i;
3525 	for (i = list->nbItems; i > idx; i--)
3526 	    list->items[i] = list->items[i-1];
3527 	list->items[idx] = item;
3528 	list->nbItems++;
3529     }
3530     return(0);
3531 }
3532 #endif
3533 
3534 static int
xmlSchemaItemListRemove(xmlSchemaItemListPtr list,int idx)3535 xmlSchemaItemListRemove(xmlSchemaItemListPtr list, int idx)
3536 {
3537     int i;
3538     if ((list->items == NULL) || (idx >= list->nbItems)) {
3539 	xmlSchemaPSimpleErr("Internal error: xmlSchemaItemListRemove, "
3540 	    "index error.\n");
3541 	return(-1);
3542     }
3543 
3544     if (list->nbItems == 1) {
3545 	/* TODO: Really free the list? */
3546 	xmlFree(list->items);
3547 	list->items = NULL;
3548 	list->nbItems = 0;
3549 	list->sizeItems = 0;
3550     } else if (list->nbItems -1 == idx) {
3551 	list->nbItems--;
3552     } else {
3553 	for (i = idx; i < list->nbItems -1; i++)
3554 	    list->items[i] = list->items[i+1];
3555 	list->nbItems--;
3556     }
3557     return(0);
3558 }
3559 
3560 /**
3561  * xmlSchemaItemListFree:
3562  * @annot:  a schema type structure
3563  *
3564  * Deallocate a annotation structure
3565  */
3566 static void
xmlSchemaItemListFree(xmlSchemaItemListPtr list)3567 xmlSchemaItemListFree(xmlSchemaItemListPtr list)
3568 {
3569     if (list == NULL)
3570 	return;
3571     if (list->items != NULL)
3572 	xmlFree(list->items);
3573     xmlFree(list);
3574 }
3575 
3576 static void
xmlSchemaBucketFree(xmlSchemaBucketPtr bucket)3577 xmlSchemaBucketFree(xmlSchemaBucketPtr bucket)
3578 {
3579     if (bucket == NULL)
3580 	return;
3581     if (bucket->globals != NULL) {
3582 	xmlSchemaComponentListFree(bucket->globals);
3583 	xmlSchemaItemListFree(bucket->globals);
3584     }
3585     if (bucket->locals != NULL) {
3586 	xmlSchemaComponentListFree(bucket->locals);
3587 	xmlSchemaItemListFree(bucket->locals);
3588     }
3589     if (bucket->relations != NULL) {
3590 	xmlSchemaSchemaRelationPtr prev, cur = bucket->relations;
3591 	do {
3592 	    prev = cur;
3593 	    cur = cur->next;
3594 	    xmlFree(prev);
3595 	} while (cur != NULL);
3596     }
3597     if ((! bucket->preserveDoc) && (bucket->doc != NULL)) {
3598 	xmlFreeDoc(bucket->doc);
3599     }
3600     if (bucket->type == XML_SCHEMA_SCHEMA_IMPORT) {
3601 	if (WXS_IMPBUCKET(bucket)->schema != NULL)
3602 	    xmlSchemaFree(WXS_IMPBUCKET(bucket)->schema);
3603     }
3604     xmlFree(bucket);
3605 }
3606 
3607 static void
xmlSchemaBucketFreeEntry(void * bucket,const xmlChar * name ATTRIBUTE_UNUSED)3608 xmlSchemaBucketFreeEntry(void *bucket, const xmlChar *name ATTRIBUTE_UNUSED)
3609 {
3610     xmlSchemaBucketFree((xmlSchemaBucketPtr) bucket);
3611 }
3612 
3613 static xmlSchemaBucketPtr
xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,int type,const xmlChar * targetNamespace)3614 xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,
3615 			 int type, const xmlChar *targetNamespace)
3616 {
3617     xmlSchemaBucketPtr ret;
3618     int size;
3619     xmlSchemaPtr mainSchema;
3620 
3621     if (WXS_CONSTRUCTOR(pctxt)->mainSchema == NULL) {
3622 	PERROR_INT("xmlSchemaBucketCreate",
3623 	    "no main schema on constructor");
3624 	return(NULL);
3625     }
3626     mainSchema = WXS_CONSTRUCTOR(pctxt)->mainSchema;
3627     /* Create the schema bucket. */
3628     if (WXS_IS_BUCKET_INCREDEF(type))
3629 	size = sizeof(xmlSchemaInclude);
3630     else
3631 	size = sizeof(xmlSchemaImport);
3632     ret = (xmlSchemaBucketPtr) xmlMalloc(size);
3633     if (ret == NULL) {
3634 	xmlSchemaPErrMemory(NULL, "allocating schema bucket", NULL);
3635 	return(NULL);
3636     }
3637     memset(ret, 0, size);
3638     ret->targetNamespace = targetNamespace;
3639     ret->type = type;
3640     ret->globals = xmlSchemaItemListCreate();
3641     if (ret->globals == NULL) {
3642 	xmlFree(ret);
3643 	return(NULL);
3644     }
3645     ret->locals = xmlSchemaItemListCreate();
3646     if (ret->locals == NULL) {
3647 	xmlFree(ret);
3648 	return(NULL);
3649     }
3650     /*
3651     * The following will assure that only the first bucket is marked as
3652     * XML_SCHEMA_SCHEMA_MAIN and it points to the *main* schema.
3653     * For each following import buckets an xmlSchema will be created.
3654     * An xmlSchema will be created for every distinct targetNamespace.
3655     * We assign the targetNamespace to the schemata here.
3656     */
3657     if (! WXS_HAS_BUCKETS(pctxt)) {
3658 	if (WXS_IS_BUCKET_INCREDEF(type)) {
3659 	    PERROR_INT("xmlSchemaBucketCreate",
3660 		"first bucket but it's an include or redefine");
3661 	    xmlSchemaBucketFree(ret);
3662 	    return(NULL);
3663 	}
3664 	/* Force the type to be XML_SCHEMA_SCHEMA_MAIN. */
3665 	ret->type = XML_SCHEMA_SCHEMA_MAIN;
3666 	/* Point to the *main* schema. */
3667 	WXS_CONSTRUCTOR(pctxt)->mainBucket = ret;
3668 	WXS_IMPBUCKET(ret)->schema = mainSchema;
3669 	/*
3670 	* Ensure that the main schema gets a targetNamespace.
3671 	*/
3672 	mainSchema->targetNamespace = targetNamespace;
3673     } else {
3674 	if (type == XML_SCHEMA_SCHEMA_MAIN) {
3675 	    PERROR_INT("xmlSchemaBucketCreate",
3676 		"main bucket but it's not the first one");
3677 	    xmlSchemaBucketFree(ret);
3678 	    return(NULL);
3679 	} else if (type == XML_SCHEMA_SCHEMA_IMPORT) {
3680 	    /*
3681 	    * Create a schema for imports and assign the
3682 	    * targetNamespace.
3683 	    */
3684 	    WXS_IMPBUCKET(ret)->schema = xmlSchemaNewSchema(pctxt);
3685 	    if (WXS_IMPBUCKET(ret)->schema == NULL) {
3686 		xmlSchemaBucketFree(ret);
3687 		return(NULL);
3688 	    }
3689 	    WXS_IMPBUCKET(ret)->schema->targetNamespace = targetNamespace;
3690 	}
3691     }
3692     if (WXS_IS_BUCKET_IMPMAIN(type)) {
3693 	int res;
3694 	/*
3695 	* Imports go into the "schemasImports" slot of the main *schema*.
3696 	* Note that we create an import entry for the main schema as well; i.e.,
3697 	* even if there's only one schema, we'll get an import.
3698 	*/
3699 	if (mainSchema->schemasImports == NULL) {
3700 	    mainSchema->schemasImports = xmlHashCreateDict(5,
3701 		WXS_CONSTRUCTOR(pctxt)->dict);
3702 	    if (mainSchema->schemasImports == NULL) {
3703 		xmlSchemaBucketFree(ret);
3704 		return(NULL);
3705 	    }
3706 	}
3707 	if (targetNamespace == NULL)
3708 	    res = xmlHashAddEntry(mainSchema->schemasImports,
3709 		XML_SCHEMAS_NO_NAMESPACE, ret);
3710 	else
3711 	    res = xmlHashAddEntry(mainSchema->schemasImports,
3712 		targetNamespace, ret);
3713 	if (res != 0) {
3714 	    PERROR_INT("xmlSchemaBucketCreate",
3715 		"failed to add the schema bucket to the hash");
3716 	    xmlSchemaBucketFree(ret);
3717 	    return(NULL);
3718 	}
3719     } else {
3720 	/* Set the @ownerImport of an include bucket. */
3721 	if (WXS_IS_BUCKET_IMPMAIN(WXS_CONSTRUCTOR(pctxt)->bucket->type))
3722 	    WXS_INCBUCKET(ret)->ownerImport =
3723 		WXS_IMPBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket);
3724 	else
3725 	    WXS_INCBUCKET(ret)->ownerImport =
3726 		WXS_INCBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket)->ownerImport;
3727 
3728 	/* Includes got into the "includes" slot of the *main* schema. */
3729 	if (mainSchema->includes == NULL) {
3730 	    mainSchema->includes = xmlSchemaItemListCreate();
3731 	    if (mainSchema->includes == NULL) {
3732 		xmlSchemaBucketFree(ret);
3733 		return(NULL);
3734 	    }
3735 	}
3736 	xmlSchemaItemListAdd(mainSchema->includes, ret);
3737     }
3738     /*
3739     * Add to list of all buckets; this is used for lookup
3740     * during schema construction time only.
3741     */
3742     if (xmlSchemaItemListAdd(WXS_CONSTRUCTOR(pctxt)->buckets, ret) == -1)
3743 	return(NULL);
3744     return(ret);
3745 }
3746 
3747 static int
xmlSchemaAddItemSize(xmlSchemaItemListPtr * list,int initialSize,void * item)3748 xmlSchemaAddItemSize(xmlSchemaItemListPtr *list, int initialSize, void *item)
3749 {
3750     if (*list == NULL) {
3751 	*list = xmlSchemaItemListCreate();
3752 	if (*list == NULL)
3753 	    return(-1);
3754     }
3755     xmlSchemaItemListAddSize(*list, initialSize, item);
3756     return(0);
3757 }
3758 
3759 /**
3760  * xmlSchemaFreeAnnot:
3761  * @annot:  a schema type structure
3762  *
3763  * Deallocate a annotation structure
3764  */
3765 static void
xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)3766 xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
3767 {
3768     if (annot == NULL)
3769         return;
3770     if (annot->next == NULL) {
3771 	xmlFree(annot);
3772     } else {
3773 	xmlSchemaAnnotPtr prev;
3774 
3775 	do {
3776 	    prev = annot;
3777 	    annot = annot->next;
3778 	    xmlFree(prev);
3779 	} while (annot != NULL);
3780     }
3781 }
3782 
3783 /**
3784  * xmlSchemaFreeNotation:
3785  * @schema:  a schema notation structure
3786  *
3787  * Deallocate a Schema Notation structure.
3788  */
3789 static void
xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)3790 xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
3791 {
3792     if (nota == NULL)
3793         return;
3794     xmlFree(nota);
3795 }
3796 
3797 /**
3798  * xmlSchemaFreeAttribute:
3799  * @attr:  an attribute declaration
3800  *
3801  * Deallocates an attribute declaration structure.
3802  */
3803 static void
xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)3804 xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
3805 {
3806     if (attr == NULL)
3807         return;
3808     if (attr->annot != NULL)
3809 	xmlSchemaFreeAnnot(attr->annot);
3810     if (attr->defVal != NULL)
3811 	xmlSchemaFreeValue(attr->defVal);
3812     xmlFree(attr);
3813 }
3814 
3815 /**
3816  * xmlSchemaFreeAttributeUse:
3817  * @use:  an attribute use
3818  *
3819  * Deallocates an attribute use structure.
3820  */
3821 static void
xmlSchemaFreeAttributeUse(xmlSchemaAttributeUsePtr use)3822 xmlSchemaFreeAttributeUse(xmlSchemaAttributeUsePtr use)
3823 {
3824     if (use == NULL)
3825         return;
3826     if (use->annot != NULL)
3827 	xmlSchemaFreeAnnot(use->annot);
3828     if (use->defVal != NULL)
3829 	xmlSchemaFreeValue(use->defVal);
3830     xmlFree(use);
3831 }
3832 
3833 /**
3834  * xmlSchemaFreeAttributeUseProhib:
3835  * @prohib:  an attribute use prohibition
3836  *
3837  * Deallocates an attribute use structure.
3838  */
3839 static void
xmlSchemaFreeAttributeUseProhib(xmlSchemaAttributeUseProhibPtr prohib)3840 xmlSchemaFreeAttributeUseProhib(xmlSchemaAttributeUseProhibPtr prohib)
3841 {
3842     if (prohib == NULL)
3843         return;
3844     xmlFree(prohib);
3845 }
3846 
3847 /**
3848  * xmlSchemaFreeWildcardNsSet:
3849  * set:  a schema wildcard namespace
3850  *
3851  * Deallocates a list of wildcard constraint structures.
3852  */
3853 static void
xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)3854 xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
3855 {
3856     xmlSchemaWildcardNsPtr next;
3857 
3858     while (set != NULL) {
3859 	next = set->next;
3860 	xmlFree(set);
3861 	set = next;
3862     }
3863 }
3864 
3865 /**
3866  * xmlSchemaFreeWildcard:
3867  * @wildcard:  a wildcard structure
3868  *
3869  * Deallocates a wildcard structure.
3870  */
3871 void
xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)3872 xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
3873 {
3874     if (wildcard == NULL)
3875         return;
3876     if (wildcard->annot != NULL)
3877         xmlSchemaFreeAnnot(wildcard->annot);
3878     if (wildcard->nsSet != NULL)
3879 	xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
3880     if (wildcard->negNsSet != NULL)
3881 	xmlFree(wildcard->negNsSet);
3882     xmlFree(wildcard);
3883 }
3884 
3885 /**
3886  * xmlSchemaFreeAttributeGroup:
3887  * @schema:  a schema attribute group structure
3888  *
3889  * Deallocate a Schema Attribute Group structure.
3890  */
3891 static void
xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attrGr)3892 xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attrGr)
3893 {
3894     if (attrGr == NULL)
3895         return;
3896     if (attrGr->annot != NULL)
3897         xmlSchemaFreeAnnot(attrGr->annot);
3898     if (attrGr->attrUses != NULL)
3899 	xmlSchemaItemListFree(WXS_LIST_CAST attrGr->attrUses);
3900     xmlFree(attrGr);
3901 }
3902 
3903 /**
3904  * xmlSchemaFreeQNameRef:
3905  * @item: a QName reference structure
3906  *
3907  * Deallocatea a QName reference structure.
3908  */
3909 static void
xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)3910 xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3911 {
3912     xmlFree(item);
3913 }
3914 
3915 /**
3916  * xmlSchemaFreeTypeLinkList:
3917  * @alink: a type link
3918  *
3919  * Deallocate a list of types.
3920  */
3921 static void
xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)3922 xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3923 {
3924     xmlSchemaTypeLinkPtr next;
3925 
3926     while (link != NULL) {
3927 	next = link->next;
3928 	xmlFree(link);
3929 	link = next;
3930     }
3931 }
3932 
3933 static void
xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)3934 xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3935 {
3936     xmlSchemaIDCStateObjPtr next;
3937     while (sto != NULL) {
3938 	next = sto->next;
3939 	if (sto->history != NULL)
3940 	    xmlFree(sto->history);
3941 	if (sto->xpathCtxt != NULL)
3942 	    xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3943 	xmlFree(sto);
3944 	sto = next;
3945     }
3946 }
3947 
3948 /**
3949  * xmlSchemaFreeIDC:
3950  * @idc: a identity-constraint definition
3951  *
3952  * Deallocates an identity-constraint definition.
3953  */
3954 static void
xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)3955 xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3956 {
3957     xmlSchemaIDCSelectPtr cur, prev;
3958 
3959     if (idcDef == NULL)
3960 	return;
3961     if (idcDef->annot != NULL)
3962         xmlSchemaFreeAnnot(idcDef->annot);
3963     /* Selector */
3964     if (idcDef->selector != NULL) {
3965 	if (idcDef->selector->xpathComp != NULL)
3966 	    xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3967 	xmlFree(idcDef->selector);
3968     }
3969     /* Fields */
3970     if (idcDef->fields != NULL) {
3971 	cur = idcDef->fields;
3972 	do {
3973 	    prev = cur;
3974 	    cur = cur->next;
3975 	    if (prev->xpathComp != NULL)
3976 		xmlFreePattern((xmlPatternPtr) prev->xpathComp);
3977 	    xmlFree(prev);
3978 	} while (cur != NULL);
3979     }
3980     xmlFree(idcDef);
3981 }
3982 
3983 /**
3984  * xmlSchemaFreeElement:
3985  * @schema:  a schema element structure
3986  *
3987  * Deallocate a Schema Element structure.
3988  */
3989 static void
xmlSchemaFreeElement(xmlSchemaElementPtr elem)3990 xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3991 {
3992     if (elem == NULL)
3993         return;
3994     if (elem->annot != NULL)
3995         xmlSchemaFreeAnnot(elem->annot);
3996     if (elem->contModel != NULL)
3997         xmlRegFreeRegexp(elem->contModel);
3998     if (elem->defVal != NULL)
3999 	xmlSchemaFreeValue(elem->defVal);
4000     xmlFree(elem);
4001 }
4002 
4003 /**
4004  * xmlSchemaFreeFacet:
4005  * @facet:  a schema facet structure
4006  *
4007  * Deallocate a Schema Facet structure.
4008  */
4009 void
xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)4010 xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
4011 {
4012     if (facet == NULL)
4013         return;
4014     if (facet->val != NULL)
4015         xmlSchemaFreeValue(facet->val);
4016     if (facet->regexp != NULL)
4017         xmlRegFreeRegexp(facet->regexp);
4018     if (facet->annot != NULL)
4019         xmlSchemaFreeAnnot(facet->annot);
4020     xmlFree(facet);
4021 }
4022 
4023 /**
4024  * xmlSchemaFreeType:
4025  * @type:  a schema type structure
4026  *
4027  * Deallocate a Schema Type structure.
4028  */
4029 void
xmlSchemaFreeType(xmlSchemaTypePtr type)4030 xmlSchemaFreeType(xmlSchemaTypePtr type)
4031 {
4032     if (type == NULL)
4033         return;
4034     if (type->annot != NULL)
4035         xmlSchemaFreeAnnot(type->annot);
4036     if (type->facets != NULL) {
4037         xmlSchemaFacetPtr facet, next;
4038 
4039         facet = type->facets;
4040         while (facet != NULL) {
4041             next = facet->next;
4042             xmlSchemaFreeFacet(facet);
4043             facet = next;
4044         }
4045     }
4046     if (type->attrUses != NULL)
4047 	xmlSchemaItemListFree((xmlSchemaItemListPtr) type->attrUses);
4048     if (type->memberTypes != NULL)
4049 	xmlSchemaFreeTypeLinkList(type->memberTypes);
4050     if (type->facetSet != NULL) {
4051 	xmlSchemaFacetLinkPtr next, link;
4052 
4053 	link = type->facetSet;
4054 	do {
4055 	    next = link->next;
4056 	    xmlFree(link);
4057 	    link = next;
4058 	} while (link != NULL);
4059     }
4060     if (type->contModel != NULL)
4061         xmlRegFreeRegexp(type->contModel);
4062     xmlFree(type);
4063 }
4064 
4065 /**
4066  * xmlSchemaFreeModelGroupDef:
4067  * @item:  a schema model group definition
4068  *
4069  * Deallocates a schema model group definition.
4070  */
4071 static void
xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)4072 xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
4073 {
4074     if (item->annot != NULL)
4075 	xmlSchemaFreeAnnot(item->annot);
4076     xmlFree(item);
4077 }
4078 
4079 /**
4080  * xmlSchemaFreeModelGroup:
4081  * @item:  a schema model group
4082  *
4083  * Deallocates a schema model group structure.
4084  */
4085 static void
xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)4086 xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
4087 {
4088     if (item->annot != NULL)
4089 	xmlSchemaFreeAnnot(item->annot);
4090     xmlFree(item);
4091 }
4092 
4093 static void
xmlSchemaComponentListFree(xmlSchemaItemListPtr list)4094 xmlSchemaComponentListFree(xmlSchemaItemListPtr list)
4095 {
4096     if ((list == NULL) || (list->nbItems == 0))
4097 	return;
4098     {
4099 	xmlSchemaTreeItemPtr item;
4100 	xmlSchemaTreeItemPtr *items = (xmlSchemaTreeItemPtr *) list->items;
4101 	int i;
4102 
4103 	for (i = 0; i < list->nbItems; i++) {
4104 	    item = items[i];
4105 	    if (item == NULL)
4106 		continue;
4107 	    switch (item->type) {
4108 		case XML_SCHEMA_TYPE_SIMPLE:
4109 		case XML_SCHEMA_TYPE_COMPLEX:
4110 		    xmlSchemaFreeType((xmlSchemaTypePtr) item);
4111 		    break;
4112 		case XML_SCHEMA_TYPE_ATTRIBUTE:
4113 		    xmlSchemaFreeAttribute((xmlSchemaAttributePtr) item);
4114 		    break;
4115 		case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
4116 		    xmlSchemaFreeAttributeUse((xmlSchemaAttributeUsePtr) item);
4117 		    break;
4118 		case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
4119 		    xmlSchemaFreeAttributeUseProhib(
4120 			(xmlSchemaAttributeUseProhibPtr) item);
4121 		    break;
4122 		case XML_SCHEMA_TYPE_ELEMENT:
4123 		    xmlSchemaFreeElement((xmlSchemaElementPtr) item);
4124 		    break;
4125 		case XML_SCHEMA_TYPE_PARTICLE:
4126 		    if (item->annot != NULL)
4127 			xmlSchemaFreeAnnot(item->annot);
4128 		    xmlFree(item);
4129 		    break;
4130 		case XML_SCHEMA_TYPE_SEQUENCE:
4131 		case XML_SCHEMA_TYPE_CHOICE:
4132 		case XML_SCHEMA_TYPE_ALL:
4133 		    xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
4134 		    break;
4135 		case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
4136 		    xmlSchemaFreeAttributeGroup(
4137 			(xmlSchemaAttributeGroupPtr) item);
4138 		    break;
4139 		case XML_SCHEMA_TYPE_GROUP:
4140 		    xmlSchemaFreeModelGroupDef(
4141 			(xmlSchemaModelGroupDefPtr) item);
4142 		    break;
4143 		case XML_SCHEMA_TYPE_ANY:
4144 		case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
4145 		    xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
4146 		    break;
4147 		case XML_SCHEMA_TYPE_IDC_KEY:
4148 		case XML_SCHEMA_TYPE_IDC_UNIQUE:
4149 		case XML_SCHEMA_TYPE_IDC_KEYREF:
4150 		    xmlSchemaFreeIDC((xmlSchemaIDCPtr) item);
4151 		    break;
4152 		case XML_SCHEMA_TYPE_NOTATION:
4153 		    xmlSchemaFreeNotation((xmlSchemaNotationPtr) item);
4154 		    break;
4155 		case XML_SCHEMA_EXTRA_QNAMEREF:
4156 		    xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
4157 		    break;
4158 		default: {
4159 		    /* TODO: This should never be hit. */
4160 		    xmlSchemaPSimpleInternalErr(NULL,
4161 			"Internal error: xmlSchemaComponentListFree, "
4162 			"unexpected component type '%s'\n",
4163 			(const xmlChar *) WXS_ITEM_TYPE_NAME(item));
4164 			 }
4165 		    break;
4166 	    }
4167 	}
4168 	list->nbItems = 0;
4169     }
4170 }
4171 
4172 /**
4173  * xmlSchemaFree:
4174  * @schema:  a schema structure
4175  *
4176  * Deallocate a Schema structure.
4177  */
4178 void
xmlSchemaFree(xmlSchemaPtr schema)4179 xmlSchemaFree(xmlSchemaPtr schema)
4180 {
4181     if (schema == NULL)
4182         return;
4183     /* @volatiles is not used anymore :-/ */
4184     if (schema->volatiles != NULL)
4185 	TODO
4186     /*
4187     * Note that those slots are not responsible for freeing
4188     * schema components anymore; this will now be done by
4189     * the schema buckets.
4190     */
4191     if (schema->notaDecl != NULL)
4192         xmlHashFree(schema->notaDecl, NULL);
4193     if (schema->attrDecl != NULL)
4194         xmlHashFree(schema->attrDecl, NULL);
4195     if (schema->attrgrpDecl != NULL)
4196         xmlHashFree(schema->attrgrpDecl, NULL);
4197     if (schema->elemDecl != NULL)
4198         xmlHashFree(schema->elemDecl, NULL);
4199     if (schema->typeDecl != NULL)
4200         xmlHashFree(schema->typeDecl, NULL);
4201     if (schema->groupDecl != NULL)
4202         xmlHashFree(schema->groupDecl, NULL);
4203     if (schema->idcDef != NULL)
4204         xmlHashFree(schema->idcDef, NULL);
4205 
4206     if (schema->schemasImports != NULL)
4207 	xmlHashFree(schema->schemasImports, xmlSchemaBucketFreeEntry);
4208     if (schema->includes != NULL) {
4209 	xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->includes;
4210 	int i;
4211 	for (i = 0; i < list->nbItems; i++) {
4212 	    xmlSchemaBucketFree((xmlSchemaBucketPtr) list->items[i]);
4213 	}
4214 	xmlSchemaItemListFree(list);
4215     }
4216     if (schema->annot != NULL)
4217         xmlSchemaFreeAnnot(schema->annot);
4218     /* Never free the doc here, since this will be done by the buckets. */
4219 
4220     xmlDictFree(schema->dict);
4221     xmlFree(schema);
4222 }
4223 
4224 /************************************************************************
4225  *									*
4226  *			Debug functions					*
4227  *									*
4228  ************************************************************************/
4229 
4230 #ifdef LIBXML_OUTPUT_ENABLED
4231 
4232 static void
4233 xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output); /* forward */
4234 
4235 /**
4236  * xmlSchemaElementDump:
4237  * @elem:  an element
4238  * @output:  the file output
4239  *
4240  * Dump the element
4241  */
4242 static void
xmlSchemaElementDump(void * payload,void * data,const xmlChar * name ATTRIBUTE_UNUSED,const xmlChar * namespace ATTRIBUTE_UNUSED,const xmlChar * context ATTRIBUTE_UNUSED)4243 xmlSchemaElementDump(void *payload, void *data,
4244                      const xmlChar * name ATTRIBUTE_UNUSED,
4245 		     const xmlChar * namespace ATTRIBUTE_UNUSED,
4246                      const xmlChar * context ATTRIBUTE_UNUSED)
4247 {
4248     xmlSchemaElementPtr elem = (xmlSchemaElementPtr) payload;
4249     FILE *output = (FILE *) data;
4250     if (elem == NULL)
4251         return;
4252 
4253 
4254     fprintf(output, "Element");
4255     if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
4256 	fprintf(output, " (global)");
4257     fprintf(output, ": '%s' ", elem->name);
4258     if (namespace != NULL)
4259 	fprintf(output, "ns '%s'", namespace);
4260     fprintf(output, "\n");
4261 #if 0
4262     if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
4263 	fprintf(output, "  min %d ", elem->minOccurs);
4264         if (elem->maxOccurs >= UNBOUNDED)
4265             fprintf(output, "max: unbounded\n");
4266         else if (elem->maxOccurs != 1)
4267             fprintf(output, "max: %d\n", elem->maxOccurs);
4268         else
4269             fprintf(output, "\n");
4270     }
4271 #endif
4272     /*
4273     * Misc other properties.
4274     */
4275     if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
4276 	(elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
4277 	(elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
4278 	(elem->flags & XML_SCHEMAS_ELEM_DEFAULT)) {
4279 	fprintf(output, "  props: ");
4280 	if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
4281 	    fprintf(output, "[fixed] ");
4282 	if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
4283 	    fprintf(output, "[default] ");
4284 	if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
4285 	    fprintf(output, "[abstract] ");
4286 	if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
4287 	    fprintf(output, "[nillable] ");
4288 	fprintf(output, "\n");
4289     }
4290     /*
4291     * Default/fixed value.
4292     */
4293     if (elem->value != NULL)
4294 	fprintf(output, "  value: '%s'\n", elem->value);
4295     /*
4296     * Type.
4297     */
4298     if (elem->namedType != NULL) {
4299 	fprintf(output, "  type: '%s' ", elem->namedType);
4300 	if (elem->namedTypeNs != NULL)
4301 	    fprintf(output, "ns '%s'\n", elem->namedTypeNs);
4302 	else
4303 	    fprintf(output, "\n");
4304     } else if (elem->subtypes != NULL) {
4305 	/*
4306 	* Dump local types.
4307 	*/
4308 	xmlSchemaTypeDump(elem->subtypes, output);
4309     }
4310     /*
4311     * Substitution group.
4312     */
4313     if (elem->substGroup != NULL) {
4314 	fprintf(output, "  substitutionGroup: '%s' ", elem->substGroup);
4315 	if (elem->substGroupNs != NULL)
4316 	    fprintf(output, "ns '%s'\n", elem->substGroupNs);
4317 	else
4318 	    fprintf(output, "\n");
4319     }
4320 }
4321 
4322 /**
4323  * xmlSchemaAnnotDump:
4324  * @output:  the file output
4325  * @annot:  a annotation
4326  *
4327  * Dump the annotation
4328  */
4329 static void
xmlSchemaAnnotDump(FILE * output,xmlSchemaAnnotPtr annot)4330 xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
4331 {
4332     xmlChar *content;
4333 
4334     if (annot == NULL)
4335         return;
4336 
4337     content = xmlNodeGetContent(annot->content);
4338     if (content != NULL) {
4339         fprintf(output, "  Annot: %s\n", content);
4340         xmlFree(content);
4341     } else
4342         fprintf(output, "  Annot: empty\n");
4343 }
4344 
4345 /**
4346  * xmlSchemaContentModelDump:
4347  * @particle: the schema particle
4348  * @output: the file output
4349  * @depth: the depth used for indentation
4350  *
4351  * Dump a SchemaType structure
4352  */
4353 static void
xmlSchemaContentModelDump(xmlSchemaParticlePtr particle,FILE * output,int depth)4354 xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
4355 {
4356     xmlChar *str = NULL;
4357     xmlSchemaTreeItemPtr term;
4358     char shift[100];
4359     int i;
4360 
4361     if (particle == NULL)
4362 	return;
4363     for (i = 0;((i < depth) && (i < 25));i++)
4364         shift[2 * i] = shift[2 * i + 1] = ' ';
4365     shift[2 * i] = shift[2 * i + 1] = 0;
4366     fprintf(output, "%s", shift);
4367     if (particle->children == NULL) {
4368 	fprintf(output, "MISSING particle term\n");
4369 	return;
4370     }
4371     term = particle->children;
4372     if (term == NULL) {
4373 	fprintf(output, "(NULL)");
4374     } else {
4375 	switch (term->type) {
4376 	    case XML_SCHEMA_TYPE_ELEMENT:
4377 		fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
4378 		    ((xmlSchemaElementPtr)term)->targetNamespace,
4379 		    ((xmlSchemaElementPtr)term)->name));
4380 		FREE_AND_NULL(str);
4381 		break;
4382 	    case XML_SCHEMA_TYPE_SEQUENCE:
4383 		fprintf(output, "SEQUENCE");
4384 		break;
4385 	    case XML_SCHEMA_TYPE_CHOICE:
4386 		fprintf(output, "CHOICE");
4387 		break;
4388 	    case XML_SCHEMA_TYPE_ALL:
4389 		fprintf(output, "ALL");
4390 		break;
4391 	    case XML_SCHEMA_TYPE_ANY:
4392 		fprintf(output, "ANY");
4393 		break;
4394 	    default:
4395 		fprintf(output, "UNKNOWN\n");
4396 		return;
4397 	}
4398     }
4399     if (particle->minOccurs != 1)
4400 	fprintf(output, " min: %d", particle->minOccurs);
4401     if (particle->maxOccurs >= UNBOUNDED)
4402 	fprintf(output, " max: unbounded");
4403     else if (particle->maxOccurs != 1)
4404 	fprintf(output, " max: %d", particle->maxOccurs);
4405     fprintf(output, "\n");
4406     if (term &&
4407 	((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
4408 	 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
4409 	 (term->type == XML_SCHEMA_TYPE_ALL)) &&
4410 	 (term->children != NULL)) {
4411 	xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
4412 	    output, depth +1);
4413     }
4414     if (particle->next != NULL)
4415 	xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
4416 		output, depth);
4417 }
4418 
4419 /**
4420  * xmlSchemaAttrUsesDump:
4421  * @uses:  attribute uses list
4422  * @output:  the file output
4423  *
4424  * Dumps a list of attribute use components.
4425  */
4426 static void
xmlSchemaAttrUsesDump(xmlSchemaItemListPtr uses,FILE * output)4427 xmlSchemaAttrUsesDump(xmlSchemaItemListPtr uses, FILE * output)
4428 {
4429     xmlSchemaAttributeUsePtr use;
4430     xmlSchemaAttributeUseProhibPtr prohib;
4431     xmlSchemaQNameRefPtr ref;
4432     const xmlChar *name, *tns;
4433     xmlChar *str = NULL;
4434     int i;
4435 
4436     if ((uses == NULL) || (uses->nbItems == 0))
4437         return;
4438 
4439     fprintf(output, "  attributes:\n");
4440     for (i = 0; i < uses->nbItems; i++) {
4441 	use = uses->items[i];
4442 	if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
4443 	    fprintf(output, "  [prohibition] ");
4444 	    prohib = (xmlSchemaAttributeUseProhibPtr) use;
4445 	    name = prohib->name;
4446 	    tns = prohib->targetNamespace;
4447 	} else if (use->type == XML_SCHEMA_EXTRA_QNAMEREF) {
4448 	    fprintf(output, "  [reference] ");
4449 	    ref = (xmlSchemaQNameRefPtr) use;
4450 	    name = ref->name;
4451 	    tns = ref->targetNamespace;
4452 	} else {
4453 	    fprintf(output, "  [use] ");
4454 	    name = WXS_ATTRUSE_DECL_NAME(use);
4455 	    tns = WXS_ATTRUSE_DECL_TNS(use);
4456 	}
4457 	fprintf(output, "'%s'\n",
4458 	    (const char *) xmlSchemaFormatQName(&str, tns, name));
4459 	FREE_AND_NULL(str);
4460     }
4461 }
4462 
4463 /**
4464  * xmlSchemaTypeDump:
4465  * @output:  the file output
4466  * @type:  a type structure
4467  *
4468  * Dump a SchemaType structure
4469  */
4470 static void
xmlSchemaTypeDump(xmlSchemaTypePtr type,FILE * output)4471 xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
4472 {
4473     if (type == NULL) {
4474         fprintf(output, "Type: NULL\n");
4475         return;
4476     }
4477     fprintf(output, "Type: ");
4478     if (type->name != NULL)
4479         fprintf(output, "'%s' ", type->name);
4480     else
4481         fprintf(output, "(no name) ");
4482     if (type->targetNamespace != NULL)
4483 	fprintf(output, "ns '%s' ", type->targetNamespace);
4484     switch (type->type) {
4485         case XML_SCHEMA_TYPE_BASIC:
4486             fprintf(output, "[basic] ");
4487             break;
4488         case XML_SCHEMA_TYPE_SIMPLE:
4489             fprintf(output, "[simple] ");
4490             break;
4491         case XML_SCHEMA_TYPE_COMPLEX:
4492             fprintf(output, "[complex] ");
4493             break;
4494         case XML_SCHEMA_TYPE_SEQUENCE:
4495             fprintf(output, "[sequence] ");
4496             break;
4497         case XML_SCHEMA_TYPE_CHOICE:
4498             fprintf(output, "[choice] ");
4499             break;
4500         case XML_SCHEMA_TYPE_ALL:
4501             fprintf(output, "[all] ");
4502             break;
4503         case XML_SCHEMA_TYPE_UR:
4504             fprintf(output, "[ur] ");
4505             break;
4506         case XML_SCHEMA_TYPE_RESTRICTION:
4507             fprintf(output, "[restriction] ");
4508             break;
4509         case XML_SCHEMA_TYPE_EXTENSION:
4510             fprintf(output, "[extension] ");
4511             break;
4512         default:
4513             fprintf(output, "[unknown type %d] ", type->type);
4514             break;
4515     }
4516     fprintf(output, "content: ");
4517     switch (type->contentType) {
4518         case XML_SCHEMA_CONTENT_UNKNOWN:
4519             fprintf(output, "[unknown] ");
4520             break;
4521         case XML_SCHEMA_CONTENT_EMPTY:
4522             fprintf(output, "[empty] ");
4523             break;
4524         case XML_SCHEMA_CONTENT_ELEMENTS:
4525             fprintf(output, "[element] ");
4526             break;
4527         case XML_SCHEMA_CONTENT_MIXED:
4528             fprintf(output, "[mixed] ");
4529             break;
4530         case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
4531 	/* not used. */
4532             break;
4533         case XML_SCHEMA_CONTENT_BASIC:
4534             fprintf(output, "[basic] ");
4535             break;
4536         case XML_SCHEMA_CONTENT_SIMPLE:
4537             fprintf(output, "[simple] ");
4538             break;
4539         case XML_SCHEMA_CONTENT_ANY:
4540             fprintf(output, "[any] ");
4541             break;
4542     }
4543     fprintf(output, "\n");
4544     if (type->base != NULL) {
4545         fprintf(output, "  base type: '%s'", type->base);
4546 	if (type->baseNs != NULL)
4547 	    fprintf(output, " ns '%s'\n", type->baseNs);
4548 	else
4549 	    fprintf(output, "\n");
4550     }
4551     if (type->attrUses != NULL)
4552 	xmlSchemaAttrUsesDump(type->attrUses, output);
4553     if (type->annot != NULL)
4554         xmlSchemaAnnotDump(output, type->annot);
4555 #ifdef DUMP_CONTENT_MODEL
4556     if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
4557 	(type->subtypes != NULL)) {
4558 	xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
4559 	    output, 1);
4560     }
4561 #endif
4562 }
4563 
4564 static void
xmlSchemaTypeDumpEntry(void * type,void * output,const xmlChar * name ATTRIBUTE_UNUSED)4565 xmlSchemaTypeDumpEntry(void *type, void *output,
4566                        const xmlChar *name ATTRIBUTE_UNUSED)
4567 {
4568     xmlSchemaTypeDump((xmlSchemaTypePtr) type, (FILE *) output);
4569 }
4570 
4571 /**
4572  * xmlSchemaDump:
4573  * @output:  the file output
4574  * @schema:  a schema structure
4575  *
4576  * Dump a Schema structure.
4577  */
4578 void
xmlSchemaDump(FILE * output,xmlSchemaPtr schema)4579 xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
4580 {
4581     if (output == NULL)
4582         return;
4583     if (schema == NULL) {
4584         fprintf(output, "Schemas: NULL\n");
4585         return;
4586     }
4587     fprintf(output, "Schemas: ");
4588     if (schema->name != NULL)
4589         fprintf(output, "%s, ", schema->name);
4590     else
4591         fprintf(output, "no name, ");
4592     if (schema->targetNamespace != NULL)
4593         fprintf(output, "%s", (const char *) schema->targetNamespace);
4594     else
4595         fprintf(output, "no target namespace");
4596     fprintf(output, "\n");
4597     if (schema->annot != NULL)
4598         xmlSchemaAnnotDump(output, schema->annot);
4599     xmlHashScan(schema->typeDecl, xmlSchemaTypeDumpEntry, output);
4600     xmlHashScanFull(schema->elemDecl, xmlSchemaElementDump, output);
4601 }
4602 
4603 #ifdef DEBUG_IDC_NODE_TABLE
4604 /**
4605  * xmlSchemaDebugDumpIDCTable:
4606  * @vctxt: the WXS validation context
4607  *
4608  * Displays the current IDC table for debug purposes.
4609  */
4610 static void
xmlSchemaDebugDumpIDCTable(FILE * output,const xmlChar * namespaceName,const xmlChar * localName,xmlSchemaPSVIIDCBindingPtr bind)4611 xmlSchemaDebugDumpIDCTable(FILE * output,
4612 			   const xmlChar *namespaceName,
4613 			   const xmlChar *localName,
4614 			   xmlSchemaPSVIIDCBindingPtr bind)
4615 {
4616     xmlChar *str = NULL;
4617     const xmlChar *value;
4618     xmlSchemaPSVIIDCNodePtr tab;
4619     xmlSchemaPSVIIDCKeyPtr key;
4620     int i, j, res;
4621 
4622     fprintf(output, "IDC: TABLES on '%s'\n",
4623 	xmlSchemaFormatQName(&str, namespaceName, localName));
4624     FREE_AND_NULL(str)
4625 
4626     if (bind == NULL)
4627 	return;
4628     do {
4629 	fprintf(output, "IDC:   BINDING '%s' (%d)\n",
4630 	    xmlSchemaGetComponentQName(&str,
4631 		bind->definition), bind->nbNodes);
4632 	FREE_AND_NULL(str)
4633 	for (i = 0; i < bind->nbNodes; i++) {
4634 	    tab = bind->nodeTable[i];
4635 	    fprintf(output, "         ( ");
4636 	    for (j = 0; j < bind->definition->nbFields; j++) {
4637 		key = tab->keys[j];
4638 		if ((key != NULL) && (key->val != NULL)) {
4639 		    res = xmlSchemaGetCanonValue(key->val, &value);
4640 		    if (res >= 0)
4641 			fprintf(output, "'%s' ", value);
4642 		    else
4643 			fprintf(output, "CANON-VALUE-FAILED ");
4644 		    if (res == 0)
4645 			FREE_AND_NULL(value)
4646 		} else if (key != NULL)
4647 		    fprintf(output, "(no val), ");
4648 		else
4649 		    fprintf(output, "(key missing), ");
4650 	    }
4651 	    fprintf(output, ")\n");
4652 	}
4653 	if (bind->dupls && bind->dupls->nbItems) {
4654 	    fprintf(output, "IDC:     dupls (%d):\n", bind->dupls->nbItems);
4655 	    for (i = 0; i < bind->dupls->nbItems; i++) {
4656 		tab = bind->dupls->items[i];
4657 		fprintf(output, "         ( ");
4658 		for (j = 0; j < bind->definition->nbFields; j++) {
4659 		    key = tab->keys[j];
4660 		    if ((key != NULL) && (key->val != NULL)) {
4661 			res = xmlSchemaGetCanonValue(key->val, &value);
4662 			if (res >= 0)
4663 			    fprintf(output, "'%s' ", value);
4664 			else
4665 			    fprintf(output, "CANON-VALUE-FAILED ");
4666 			if (res == 0)
4667 			    FREE_AND_NULL(value)
4668 		    } else if (key != NULL)
4669 		    fprintf(output, "(no val), ");
4670 			else
4671 			    fprintf(output, "(key missing), ");
4672 		}
4673 		fprintf(output, ")\n");
4674 	    }
4675 	}
4676 	bind = bind->next;
4677     } while (bind != NULL);
4678 }
4679 #endif /* DEBUG_IDC */
4680 #endif /* LIBXML_OUTPUT_ENABLED */
4681 
4682 /************************************************************************
4683  *									*
4684  *			Utilities					*
4685  *									*
4686  ************************************************************************/
4687 
4688 /**
4689  * xmlSchemaGetPropNode:
4690  * @node: the element node
4691  * @name: the name of the attribute
4692  *
4693  * Seeks an attribute with a name of @name in
4694  * no namespace.
4695  *
4696  * Returns the attribute or NULL if not present.
4697  */
4698 static xmlAttrPtr
xmlSchemaGetPropNode(xmlNodePtr node,const char * name)4699 xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
4700 {
4701     xmlAttrPtr prop;
4702 
4703     if ((node == NULL) || (name == NULL))
4704 	return(NULL);
4705     prop = node->properties;
4706     while (prop != NULL) {
4707         if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
4708 	    return(prop);
4709 	prop = prop->next;
4710     }
4711     return (NULL);
4712 }
4713 
4714 /**
4715  * xmlSchemaGetPropNodeNs:
4716  * @node: the element node
4717  * @uri: the uri
4718  * @name: the name of the attribute
4719  *
4720  * Seeks an attribute with a local name of @name and
4721  * a namespace URI of @uri.
4722  *
4723  * Returns the attribute or NULL if not present.
4724  */
4725 static xmlAttrPtr
xmlSchemaGetPropNodeNs(xmlNodePtr node,const char * uri,const char * name)4726 xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
4727 {
4728     xmlAttrPtr prop;
4729 
4730     if ((node == NULL) || (name == NULL))
4731 	return(NULL);
4732     prop = node->properties;
4733     while (prop != NULL) {
4734 	if ((prop->ns != NULL) &&
4735 	    xmlStrEqual(prop->name, BAD_CAST name) &&
4736 	    xmlStrEqual(prop->ns->href, BAD_CAST uri))
4737 	    return(prop);
4738 	prop = prop->next;
4739     }
4740     return (NULL);
4741 }
4742 
4743 static const xmlChar *
xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node)4744 xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
4745 {
4746     xmlChar *val;
4747     const xmlChar *ret;
4748 
4749     val = xmlNodeGetContent(node);
4750     if (val == NULL)
4751 	val = xmlStrdup((xmlChar *)"");
4752     ret = xmlDictLookup(ctxt->dict, val, -1);
4753     xmlFree(val);
4754     return(ret);
4755 }
4756 
4757 static const xmlChar *
xmlSchemaGetNodeContentNoDict(xmlNodePtr node)4758 xmlSchemaGetNodeContentNoDict(xmlNodePtr node)
4759 {
4760     return((const xmlChar*) xmlNodeGetContent(node));
4761 }
4762 
4763 /**
4764  * xmlSchemaGetProp:
4765  * @ctxt: the parser context
4766  * @node: the node
4767  * @name: the property name
4768  *
4769  * Read a attribute value and internalize the string
4770  *
4771  * Returns the string or NULL if not present.
4772  */
4773 static const xmlChar *
xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,const char * name)4774 xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4775                  const char *name)
4776 {
4777     xmlChar *val;
4778     const xmlChar *ret;
4779 
4780     val = xmlGetNoNsProp(node, BAD_CAST name);
4781     if (val == NULL)
4782         return(NULL);
4783     ret = xmlDictLookup(ctxt->dict, val, -1);
4784     xmlFree(val);
4785     return(ret);
4786 }
4787 
4788 /************************************************************************
4789  *									*
4790  *			Parsing functions				*
4791  *									*
4792  ************************************************************************/
4793 
4794 #define WXS_FIND_GLOBAL_ITEM(slot)			\
4795     if (xmlStrEqual(nsName, schema->targetNamespace)) { \
4796 	ret = xmlHashLookup(schema->slot, name); \
4797 	if (ret != NULL) goto exit; \
4798     } \
4799     if (xmlHashSize(schema->schemasImports) > 1) { \
4800 	xmlSchemaImportPtr import; \
4801 	if (nsName == NULL) \
4802 	    import = xmlHashLookup(schema->schemasImports, \
4803 		XML_SCHEMAS_NO_NAMESPACE); \
4804 	else \
4805 	    import = xmlHashLookup(schema->schemasImports, nsName); \
4806 	if (import == NULL) \
4807 	    goto exit; \
4808 	ret = xmlHashLookup(import->schema->slot, name); \
4809     }
4810 
4811 /**
4812  * xmlSchemaGetElem:
4813  * @schema:  the schema context
4814  * @name:  the element name
4815  * @ns:  the element namespace
4816  *
4817  * Lookup a global element declaration in the schema.
4818  *
4819  * Returns the element declaration or NULL if not found.
4820  */
4821 static xmlSchemaElementPtr
xmlSchemaGetElem(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4822 xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
4823                  const xmlChar * nsName)
4824 {
4825     xmlSchemaElementPtr ret = NULL;
4826 
4827     if ((name == NULL) || (schema == NULL))
4828         return(NULL);
4829     if (schema != NULL) {
4830 	WXS_FIND_GLOBAL_ITEM(elemDecl)
4831     }
4832 exit:
4833 #ifdef DEBUG
4834     if (ret == NULL) {
4835         if (nsName == NULL)
4836             fprintf(stderr, "Unable to lookup element decl. %s", name);
4837         else
4838             fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
4839                     nsName);
4840     }
4841 #endif
4842     return (ret);
4843 }
4844 
4845 /**
4846  * xmlSchemaGetType:
4847  * @schema:  the main schema
4848  * @name:  the type's name
4849  * nsName:  the type's namespace
4850  *
4851  * Lookup a type in the schemas or the predefined types
4852  *
4853  * Returns the group definition or NULL if not found.
4854  */
4855 static xmlSchemaTypePtr
xmlSchemaGetType(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4856 xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
4857                  const xmlChar * nsName)
4858 {
4859     xmlSchemaTypePtr ret = NULL;
4860 
4861     if (name == NULL)
4862         return (NULL);
4863     /* First try the built-in types. */
4864     if ((nsName != NULL) && xmlStrEqual(nsName, xmlSchemaNs)) {
4865 	ret = xmlSchemaGetPredefinedType(name, nsName);
4866 	if (ret != NULL)
4867 	    goto exit;
4868 	/*
4869 	* Note that we try the parsed schemas as well here
4870 	* since one might have parsed the S4S, which contain more
4871 	* than the built-in types.
4872 	* TODO: Can we optimize this?
4873 	*/
4874     }
4875     if (schema != NULL) {
4876 	WXS_FIND_GLOBAL_ITEM(typeDecl)
4877     }
4878 exit:
4879 
4880 #ifdef DEBUG
4881     if (ret == NULL) {
4882         if (nsName == NULL)
4883             fprintf(stderr, "Unable to lookup type %s", name);
4884         else
4885             fprintf(stderr, "Unable to lookup type %s:%s", name,
4886                     nsName);
4887     }
4888 #endif
4889     return (ret);
4890 }
4891 
4892 /**
4893  * xmlSchemaGetAttributeDecl:
4894  * @schema:  the context of the schema
4895  * @name:  the name of the attribute
4896  * @ns:  the target namespace of the attribute
4897  *
4898  * Lookup a an attribute in the schema or imported schemas
4899  *
4900  * Returns the attribute declaration or NULL if not found.
4901  */
4902 static xmlSchemaAttributePtr
xmlSchemaGetAttributeDecl(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4903 xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
4904                  const xmlChar * nsName)
4905 {
4906     xmlSchemaAttributePtr ret = NULL;
4907 
4908     if ((name == NULL) || (schema == NULL))
4909         return (NULL);
4910     if (schema != NULL) {
4911 	WXS_FIND_GLOBAL_ITEM(attrDecl)
4912     }
4913 exit:
4914 #ifdef DEBUG
4915     if (ret == NULL) {
4916         if (nsName == NULL)
4917             fprintf(stderr, "Unable to lookup attribute %s", name);
4918         else
4919             fprintf(stderr, "Unable to lookup attribute %s:%s", name,
4920                     nsName);
4921     }
4922 #endif
4923     return (ret);
4924 }
4925 
4926 /**
4927  * xmlSchemaGetAttributeGroup:
4928  * @schema:  the context of the schema
4929  * @name:  the name of the attribute group
4930  * @ns:  the target namespace of the attribute group
4931  *
4932  * Lookup a an attribute group in the schema or imported schemas
4933  *
4934  * Returns the attribute group definition or NULL if not found.
4935  */
4936 static xmlSchemaAttributeGroupPtr
xmlSchemaGetAttributeGroup(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4937 xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
4938                  const xmlChar * nsName)
4939 {
4940     xmlSchemaAttributeGroupPtr ret = NULL;
4941 
4942     if ((name == NULL) || (schema == NULL))
4943         return (NULL);
4944     if (schema != NULL) {
4945 	WXS_FIND_GLOBAL_ITEM(attrgrpDecl)
4946     }
4947 exit:
4948     /* TODO:
4949     if ((ret != NULL) && (ret->redef != NULL)) {
4950 	* Return the last redefinition. *
4951 	ret = ret->redef;
4952     }
4953     */
4954 #ifdef DEBUG
4955     if (ret == NULL) {
4956         if (nsName == NULL)
4957             fprintf(stderr, "Unable to lookup attribute group %s", name);
4958         else
4959             fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
4960                     nsName);
4961     }
4962 #endif
4963     return (ret);
4964 }
4965 
4966 /**
4967  * xmlSchemaGetGroup:
4968  * @schema:  the context of the schema
4969  * @name:  the name of the group
4970  * @ns:  the target namespace of the group
4971  *
4972  * Lookup a group in the schema or imported schemas
4973  *
4974  * Returns the group definition or NULL if not found.
4975  */
4976 static xmlSchemaModelGroupDefPtr
xmlSchemaGetGroup(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4977 xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
4978                  const xmlChar * nsName)
4979 {
4980     xmlSchemaModelGroupDefPtr ret = NULL;
4981 
4982     if ((name == NULL) || (schema == NULL))
4983         return (NULL);
4984     if (schema != NULL) {
4985 	WXS_FIND_GLOBAL_ITEM(groupDecl)
4986     }
4987 exit:
4988 
4989 #ifdef DEBUG
4990     if (ret == NULL) {
4991         if (nsName == NULL)
4992             fprintf(stderr, "Unable to lookup group %s", name);
4993         else
4994             fprintf(stderr, "Unable to lookup group %s:%s", name,
4995                     nsName);
4996     }
4997 #endif
4998     return (ret);
4999 }
5000 
5001 static xmlSchemaNotationPtr
xmlSchemaGetNotation(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)5002 xmlSchemaGetNotation(xmlSchemaPtr schema,
5003 		     const xmlChar *name,
5004 		     const xmlChar *nsName)
5005 {
5006     xmlSchemaNotationPtr ret = NULL;
5007 
5008     if ((name == NULL) || (schema == NULL))
5009         return (NULL);
5010     if (schema != NULL) {
5011 	WXS_FIND_GLOBAL_ITEM(notaDecl)
5012     }
5013 exit:
5014     return (ret);
5015 }
5016 
5017 static xmlSchemaIDCPtr
xmlSchemaGetIDC(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)5018 xmlSchemaGetIDC(xmlSchemaPtr schema,
5019 		const xmlChar *name,
5020 		const xmlChar *nsName)
5021 {
5022     xmlSchemaIDCPtr ret = NULL;
5023 
5024     if ((name == NULL) || (schema == NULL))
5025         return (NULL);
5026     if (schema != NULL) {
5027 	WXS_FIND_GLOBAL_ITEM(idcDef)
5028     }
5029 exit:
5030     return (ret);
5031 }
5032 
5033 /**
5034  * xmlSchemaGetNamedComponent:
5035  * @schema:  the schema
5036  * @name:  the name of the group
5037  * @ns:  the target namespace of the group
5038  *
5039  * Lookup a group in the schema or imported schemas
5040  *
5041  * Returns the group definition or NULL if not found.
5042  */
5043 static xmlSchemaBasicItemPtr
xmlSchemaGetNamedComponent(xmlSchemaPtr schema,xmlSchemaTypeType itemType,const xmlChar * name,const xmlChar * targetNs)5044 xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
5045 			   xmlSchemaTypeType itemType,
5046 			   const xmlChar *name,
5047 			   const xmlChar *targetNs)
5048 {
5049     switch (itemType) {
5050 	case XML_SCHEMA_TYPE_GROUP:
5051 	    return ((xmlSchemaBasicItemPtr) xmlSchemaGetGroup(schema,
5052 		name, targetNs));
5053 	case XML_SCHEMA_TYPE_ELEMENT:
5054 	    return ((xmlSchemaBasicItemPtr) xmlSchemaGetElem(schema,
5055 		name, targetNs));
5056 	default:
5057 	    TODO
5058 	    return (NULL);
5059     }
5060 }
5061 
5062 /************************************************************************
5063  *									*
5064  *			Parsing functions				*
5065  *									*
5066  ************************************************************************/
5067 
5068 #define IS_BLANK_NODE(n)						\
5069     (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
5070 
5071 /**
5072  * xmlSchemaIsBlank:
5073  * @str:  a string
5074  * @len: the length of the string or -1
5075  *
5076  * Check if a string is ignorable
5077  *
5078  * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
5079  */
5080 static int
xmlSchemaIsBlank(xmlChar * str,int len)5081 xmlSchemaIsBlank(xmlChar * str, int len)
5082 {
5083     if (str == NULL)
5084         return (1);
5085     if (len < 0) {
5086 	while (*str != 0) {
5087 	    if (!(IS_BLANK_CH(*str)))
5088 		return (0);
5089 	    str++;
5090 	}
5091     } else while ((*str != 0) && (len != 0)) {
5092 	if (!(IS_BLANK_CH(*str)))
5093 	    return (0);
5094 	str++;
5095 	len--;
5096     }
5097 
5098     return (1);
5099 }
5100 
5101 #define WXS_COMP_NAME(c, t) ((t) (c))->name
5102 #define WXS_COMP_TNS(c, t) ((t) (c))->targetNamespace
5103 /*
5104 * xmlSchemaFindRedefCompInGraph:
5105 * ATTENTION TODO: This uses pointer comp. for strings.
5106 */
5107 static xmlSchemaBasicItemPtr
xmlSchemaFindRedefCompInGraph(xmlSchemaBucketPtr bucket,xmlSchemaTypeType type,const xmlChar * name,const xmlChar * nsName)5108 xmlSchemaFindRedefCompInGraph(xmlSchemaBucketPtr bucket,
5109 			      xmlSchemaTypeType type,
5110 			      const xmlChar *name,
5111 			      const xmlChar *nsName)
5112 {
5113     xmlSchemaBasicItemPtr ret;
5114     int i;
5115 
5116     if ((bucket == NULL) || (name == NULL))
5117 	return(NULL);
5118     if ((bucket->globals == NULL) ||
5119 	(bucket->globals->nbItems == 0))
5120 	goto subschemas;
5121     /*
5122     * Search in global components.
5123     */
5124     for (i = 0; i < bucket->globals->nbItems; i++) {
5125 	ret = bucket->globals->items[i];
5126 	if (ret->type == type) {
5127 	    switch (type) {
5128 		case XML_SCHEMA_TYPE_COMPLEX:
5129 		case XML_SCHEMA_TYPE_SIMPLE:
5130 		    if ((WXS_COMP_NAME(ret, xmlSchemaTypePtr) == name) &&
5131 			(WXS_COMP_TNS(ret, xmlSchemaTypePtr) ==
5132 			nsName))
5133 		    {
5134 			return(ret);
5135 		    }
5136 		    break;
5137 		case XML_SCHEMA_TYPE_GROUP:
5138 		    if ((WXS_COMP_NAME(ret,
5139 			    xmlSchemaModelGroupDefPtr) == name) &&
5140 			(WXS_COMP_TNS(ret,
5141 			    xmlSchemaModelGroupDefPtr) == nsName))
5142 		    {
5143 			return(ret);
5144 		    }
5145 		    break;
5146 		case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
5147 		    if ((WXS_COMP_NAME(ret,
5148 			    xmlSchemaAttributeGroupPtr) == name) &&
5149 			(WXS_COMP_TNS(ret,
5150 			    xmlSchemaAttributeGroupPtr) == nsName))
5151 		    {
5152 			return(ret);
5153 		    }
5154 		    break;
5155 		default:
5156 		    /* Should not be hit. */
5157 		    return(NULL);
5158 	    }
5159 	}
5160     }
5161 subschemas:
5162     /*
5163     * Process imported/included schemas.
5164     */
5165     if (bucket->relations != NULL) {
5166 	xmlSchemaSchemaRelationPtr rel = bucket->relations;
5167 
5168 	/*
5169 	* TODO: Marking the bucket will not avoid multiple searches
5170 	* in the same schema, but avoids at least circularity.
5171 	*/
5172 	bucket->flags |= XML_SCHEMA_BUCKET_MARKED;
5173 	do {
5174 	    if ((rel->bucket != NULL) &&
5175 		((rel->bucket->flags & XML_SCHEMA_BUCKET_MARKED) == 0)) {
5176 		ret = xmlSchemaFindRedefCompInGraph(rel->bucket,
5177 		    type, name, nsName);
5178 		if (ret != NULL)
5179 		    return(ret);
5180 	    }
5181 	    rel = rel->next;
5182 	} while (rel != NULL);
5183 	 bucket->flags ^= XML_SCHEMA_BUCKET_MARKED;
5184     }
5185     return(NULL);
5186 }
5187 
5188 /**
5189  * xmlSchemaAddNotation:
5190  * @ctxt:  a schema parser context
5191  * @schema:  the schema being built
5192  * @name:  the item name
5193  *
5194  * Add an XML schema annotation declaration
5195  * *WARNING* this interface is highly subject to change
5196  *
5197  * Returns the new structure or NULL in case of error
5198  */
5199 static xmlSchemaNotationPtr
xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node ATTRIBUTE_UNUSED)5200 xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5201                      const xmlChar *name, const xmlChar *nsName,
5202 		     xmlNodePtr node ATTRIBUTE_UNUSED)
5203 {
5204     xmlSchemaNotationPtr ret = NULL;
5205 
5206     if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5207         return (NULL);
5208 
5209     ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
5210     if (ret == NULL) {
5211         xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
5212         return (NULL);
5213     }
5214     memset(ret, 0, sizeof(xmlSchemaNotation));
5215     ret->type = XML_SCHEMA_TYPE_NOTATION;
5216     ret->name = name;
5217     ret->targetNamespace = nsName;
5218     /* TODO: do we need the node to be set?
5219     * ret->node = node;*/
5220     WXS_ADD_GLOBAL(ctxt, ret);
5221     return (ret);
5222 }
5223 
5224 /**
5225  * xmlSchemaAddAttribute:
5226  * @ctxt:  a schema parser context
5227  * @schema:  the schema being built
5228  * @name:  the item name
5229  * @namespace:  the namespace
5230  *
5231  * Add an XML schema Attribute declaration
5232  * *WARNING* this interface is highly subject to change
5233  *
5234  * Returns the new structure or NULL in case of error
5235  */
5236 static xmlSchemaAttributePtr
xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node,int topLevel)5237 xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5238                       const xmlChar * name, const xmlChar * nsName,
5239 		      xmlNodePtr node, int topLevel)
5240 {
5241     xmlSchemaAttributePtr ret = NULL;
5242 
5243     if ((ctxt == NULL) || (schema == NULL))
5244         return (NULL);
5245 
5246     ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
5247     if (ret == NULL) {
5248         xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
5249         return (NULL);
5250     }
5251     memset(ret, 0, sizeof(xmlSchemaAttribute));
5252     ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
5253     ret->node = node;
5254     ret->name = name;
5255     ret->targetNamespace = nsName;
5256 
5257     if (topLevel)
5258 	WXS_ADD_GLOBAL(ctxt, ret);
5259     else
5260 	WXS_ADD_LOCAL(ctxt, ret);
5261     WXS_ADD_PENDING(ctxt, ret);
5262     return (ret);
5263 }
5264 
5265 /**
5266  * xmlSchemaAddAttributeUse:
5267  * @ctxt:  a schema parser context
5268  * @schema:  the schema being built
5269  * @name:  the item name
5270  * @namespace:  the namespace
5271  *
5272  * Add an XML schema Attribute declaration
5273  * *WARNING* this interface is highly subject to change
5274  *
5275  * Returns the new structure or NULL in case of error
5276  */
5277 static xmlSchemaAttributeUsePtr
xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt,xmlNodePtr node)5278 xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt,
5279 			 xmlNodePtr node)
5280 {
5281     xmlSchemaAttributeUsePtr ret = NULL;
5282 
5283     if (pctxt == NULL)
5284         return (NULL);
5285 
5286     ret = (xmlSchemaAttributeUsePtr) xmlMalloc(sizeof(xmlSchemaAttributeUse));
5287     if (ret == NULL) {
5288         xmlSchemaPErrMemory(pctxt, "allocating attribute", NULL);
5289         return (NULL);
5290     }
5291     memset(ret, 0, sizeof(xmlSchemaAttributeUse));
5292     ret->type = XML_SCHEMA_TYPE_ATTRIBUTE_USE;
5293     ret->node = node;
5294 
5295     WXS_ADD_LOCAL(pctxt, ret);
5296     return (ret);
5297 }
5298 
5299 /*
5300 * xmlSchemaAddRedef:
5301 *
5302 * Adds a redefinition information. This is used at a later stage to:
5303 * resolve references to the redefined components and to check constraints.
5304 */
5305 static xmlSchemaRedefPtr
xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBucketPtr targetBucket,void * item,const xmlChar * refName,const xmlChar * refTargetNs)5306 xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt,
5307 		  xmlSchemaBucketPtr targetBucket,
5308 		  void *item,
5309 		  const xmlChar *refName,
5310 		  const xmlChar *refTargetNs)
5311 {
5312     xmlSchemaRedefPtr ret;
5313 
5314     ret = (xmlSchemaRedefPtr)
5315 	xmlMalloc(sizeof(xmlSchemaRedef));
5316     if (ret == NULL) {
5317 	xmlSchemaPErrMemory(pctxt,
5318 	    "allocating redefinition info", NULL);
5319 	return (NULL);
5320     }
5321     memset(ret, 0, sizeof(xmlSchemaRedef));
5322     ret->item = item;
5323     ret->targetBucket = targetBucket;
5324     ret->refName = refName;
5325     ret->refTargetNs = refTargetNs;
5326     if (WXS_CONSTRUCTOR(pctxt)->redefs == NULL)
5327 	WXS_CONSTRUCTOR(pctxt)->redefs = ret;
5328     else
5329 	WXS_CONSTRUCTOR(pctxt)->lastRedef->next = ret;
5330     WXS_CONSTRUCTOR(pctxt)->lastRedef = ret;
5331 
5332     return (ret);
5333 }
5334 
5335 /**
5336  * xmlSchemaAddAttributeGroupDefinition:
5337  * @ctxt:  a schema parser context
5338  * @schema:  the schema being built
5339  * @name:  the item name
5340  * @nsName:  the target namespace
5341  * @node: the corresponding node
5342  *
5343  * Add an XML schema Attribute Group definition.
5344  *
5345  * Returns the new structure or NULL in case of error
5346  */
5347 static xmlSchemaAttributeGroupPtr
xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema ATTRIBUTE_UNUSED,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node)5348 xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
5349                            xmlSchemaPtr schema ATTRIBUTE_UNUSED,
5350 			   const xmlChar *name,
5351 			   const xmlChar *nsName,
5352 			   xmlNodePtr node)
5353 {
5354     xmlSchemaAttributeGroupPtr ret = NULL;
5355 
5356     if ((pctxt == NULL) || (name == NULL))
5357         return (NULL);
5358 
5359     ret = (xmlSchemaAttributeGroupPtr)
5360         xmlMalloc(sizeof(xmlSchemaAttributeGroup));
5361     if (ret == NULL) {
5362 	xmlSchemaPErrMemory(pctxt, "allocating attribute group", NULL);
5363 	return (NULL);
5364     }
5365     memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
5366     ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5367     ret->name = name;
5368     ret->targetNamespace = nsName;
5369     ret->node = node;
5370 
5371     /* TODO: Remove the flag. */
5372     ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5373     if (pctxt->isRedefine) {
5374 	pctxt->redef = xmlSchemaAddRedef(pctxt, pctxt->redefined,
5375 	    ret, name, nsName);
5376 	if (pctxt->redef == NULL) {
5377 	    xmlFree(ret);
5378 	    return(NULL);
5379 	}
5380 	pctxt->redefCounter = 0;
5381     }
5382     WXS_ADD_GLOBAL(pctxt, ret);
5383     WXS_ADD_PENDING(pctxt, ret);
5384     return (ret);
5385 }
5386 
5387 /**
5388  * xmlSchemaAddElement:
5389  * @ctxt:  a schema parser context
5390  * @schema:  the schema being built
5391  * @name:  the type name
5392  * @namespace:  the type namespace
5393  *
5394  * Add an XML schema Element declaration
5395  * *WARNING* this interface is highly subject to change
5396  *
5397  * Returns the new structure or NULL in case of error
5398  */
5399 static xmlSchemaElementPtr
xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node,int topLevel)5400 xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt,
5401                     const xmlChar * name, const xmlChar * nsName,
5402 		    xmlNodePtr node, int topLevel)
5403 {
5404     xmlSchemaElementPtr ret = NULL;
5405 
5406     if ((ctxt == NULL) || (name == NULL))
5407         return (NULL);
5408 
5409     ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
5410     if (ret == NULL) {
5411         xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
5412         return (NULL);
5413     }
5414     memset(ret, 0, sizeof(xmlSchemaElement));
5415     ret->type = XML_SCHEMA_TYPE_ELEMENT;
5416     ret->name = name;
5417     ret->targetNamespace = nsName;
5418     ret->node = node;
5419 
5420     if (topLevel)
5421 	WXS_ADD_GLOBAL(ctxt, ret);
5422     else
5423 	WXS_ADD_LOCAL(ctxt, ret);
5424     WXS_ADD_PENDING(ctxt, ret);
5425     return (ret);
5426 }
5427 
5428 /**
5429  * xmlSchemaAddType:
5430  * @ctxt:  a schema parser context
5431  * @schema:  the schema being built
5432  * @name:  the item name
5433  * @namespace:  the namespace
5434  *
5435  * Add an XML schema item
5436  * *WARNING* this interface is highly subject to change
5437  *
5438  * Returns the new structure or NULL in case of error
5439  */
5440 static xmlSchemaTypePtr
xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaTypeType type,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node,int topLevel)5441 xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5442 		 xmlSchemaTypeType type,
5443                  const xmlChar * name, const xmlChar * nsName,
5444 		 xmlNodePtr node, int topLevel)
5445 {
5446     xmlSchemaTypePtr ret = NULL;
5447 
5448     if ((ctxt == NULL) || (schema == NULL))
5449         return (NULL);
5450 
5451     ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
5452     if (ret == NULL) {
5453         xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
5454         return (NULL);
5455     }
5456     memset(ret, 0, sizeof(xmlSchemaType));
5457     ret->type = type;
5458     ret->name = name;
5459     ret->targetNamespace = nsName;
5460     ret->node = node;
5461     if (topLevel) {
5462 	if (ctxt->isRedefine) {
5463 	    ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5464 		ret, name, nsName);
5465 	    if (ctxt->redef == NULL) {
5466 		xmlFree(ret);
5467 		return(NULL);
5468 	    }
5469 	    ctxt->redefCounter = 0;
5470 	}
5471 	WXS_ADD_GLOBAL(ctxt, ret);
5472     } else
5473 	WXS_ADD_LOCAL(ctxt, ret);
5474     WXS_ADD_PENDING(ctxt, ret);
5475     return (ret);
5476 }
5477 
5478 static xmlSchemaQNameRefPtr
xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypeType refType,const xmlChar * refName,const xmlChar * refNs)5479 xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt,
5480 		     xmlSchemaTypeType refType,
5481 		     const xmlChar *refName,
5482 		     const xmlChar *refNs)
5483 {
5484     xmlSchemaQNameRefPtr ret;
5485 
5486     ret = (xmlSchemaQNameRefPtr)
5487 	xmlMalloc(sizeof(xmlSchemaQNameRef));
5488     if (ret == NULL) {
5489 	xmlSchemaPErrMemory(pctxt,
5490 	    "allocating QName reference item", NULL);
5491 	return (NULL);
5492     }
5493     ret->node = NULL;
5494     ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
5495     ret->name = refName;
5496     ret->targetNamespace = refNs;
5497     ret->item = NULL;
5498     ret->itemType = refType;
5499     /*
5500     * Store the reference item in the schema.
5501     */
5502     WXS_ADD_LOCAL(pctxt, ret);
5503     return (ret);
5504 }
5505 
5506 static xmlSchemaAttributeUseProhibPtr
xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt)5507 xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt)
5508 {
5509     xmlSchemaAttributeUseProhibPtr ret;
5510 
5511     ret = (xmlSchemaAttributeUseProhibPtr)
5512 	xmlMalloc(sizeof(xmlSchemaAttributeUseProhib));
5513     if (ret == NULL) {
5514 	xmlSchemaPErrMemory(pctxt,
5515 	    "allocating attribute use prohibition", NULL);
5516 	return (NULL);
5517     }
5518     memset(ret, 0, sizeof(xmlSchemaAttributeUseProhib));
5519     ret->type = XML_SCHEMA_EXTRA_ATTR_USE_PROHIB;
5520     WXS_ADD_LOCAL(pctxt, ret);
5521     return (ret);
5522 }
5523 
5524 
5525 /**
5526  * xmlSchemaAddModelGroup:
5527  * @ctxt:  a schema parser context
5528  * @schema:  the schema being built
5529  * @type: the "compositor" type of the model group
5530  * @node: the node in the schema doc
5531  *
5532  * Adds a schema model group
5533  * *WARNING* this interface is highly subject to change
5534  *
5535  * Returns the new structure or NULL in case of error
5536  */
5537 static xmlSchemaModelGroupPtr
xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaTypeType type,xmlNodePtr node)5538 xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt,
5539 		       xmlSchemaPtr schema,
5540 		       xmlSchemaTypeType type,
5541 		       xmlNodePtr node)
5542 {
5543     xmlSchemaModelGroupPtr ret = NULL;
5544 
5545     if ((ctxt == NULL) || (schema == NULL))
5546         return (NULL);
5547 
5548     ret = (xmlSchemaModelGroupPtr)
5549 	xmlMalloc(sizeof(xmlSchemaModelGroup));
5550     if (ret == NULL) {
5551 	xmlSchemaPErrMemory(ctxt, "allocating model group component",
5552 	    NULL);
5553 	return (NULL);
5554     }
5555     memset(ret, 0, sizeof(xmlSchemaModelGroup));
5556     ret->type = type;
5557     ret->node = node;
5558     WXS_ADD_LOCAL(ctxt, ret);
5559     if ((type == XML_SCHEMA_TYPE_SEQUENCE) ||
5560 	(type == XML_SCHEMA_TYPE_CHOICE))
5561 	WXS_ADD_PENDING(ctxt, ret);
5562     return (ret);
5563 }
5564 
5565 
5566 /**
5567  * xmlSchemaAddParticle:
5568  * @ctxt:  a schema parser context
5569  * @schema:  the schema being built
5570  * @node: the corresponding node in the schema doc
5571  * @min: the minOccurs
5572  * @max: the maxOccurs
5573  *
5574  * Adds an XML schema particle component.
5575  * *WARNING* this interface is highly subject to change
5576  *
5577  * Returns the new structure or NULL in case of error
5578  */
5579 static xmlSchemaParticlePtr
xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int min,int max)5580 xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt,
5581 		     xmlNodePtr node, int min, int max)
5582 {
5583     xmlSchemaParticlePtr ret = NULL;
5584     if (ctxt == NULL)
5585         return (NULL);
5586 
5587 #ifdef DEBUG
5588     fprintf(stderr, "Adding particle component\n");
5589 #endif
5590     ret = (xmlSchemaParticlePtr)
5591 	xmlMalloc(sizeof(xmlSchemaParticle));
5592     if (ret == NULL) {
5593 	xmlSchemaPErrMemory(ctxt, "allocating particle component",
5594 	    NULL);
5595 	return (NULL);
5596     }
5597     ret->type = XML_SCHEMA_TYPE_PARTICLE;
5598     ret->annot = NULL;
5599     ret->node = node;
5600     ret->minOccurs = min;
5601     ret->maxOccurs = max;
5602     ret->next = NULL;
5603     ret->children = NULL;
5604 
5605     WXS_ADD_LOCAL(ctxt, ret);
5606     /*
5607     * Note that addition to pending components will be done locally
5608     * to the specific parsing function, since the most particles
5609     * need not to be fixed up (i.e. the reference to be resolved).
5610     * REMOVED: WXS_ADD_PENDING(ctxt, ret);
5611     */
5612     return (ret);
5613 }
5614 
5615 /**
5616  * xmlSchemaAddModelGroupDefinition:
5617  * @ctxt:  a schema validation context
5618  * @schema:  the schema being built
5619  * @name:  the group name
5620  *
5621  * Add an XML schema Group definition
5622  *
5623  * Returns the new structure or NULL in case of error
5624  */
5625 static xmlSchemaModelGroupDefPtr
xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node)5626 xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
5627 				 xmlSchemaPtr schema,
5628 				 const xmlChar *name,
5629 				 const xmlChar *nsName,
5630 				 xmlNodePtr node)
5631 {
5632     xmlSchemaModelGroupDefPtr ret = NULL;
5633 
5634     if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5635         return (NULL);
5636 
5637     ret = (xmlSchemaModelGroupDefPtr)
5638 	xmlMalloc(sizeof(xmlSchemaModelGroupDef));
5639     if (ret == NULL) {
5640         xmlSchemaPErrMemory(ctxt, "adding group", NULL);
5641         return (NULL);
5642     }
5643     memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
5644     ret->name = name;
5645     ret->type = XML_SCHEMA_TYPE_GROUP;
5646     ret->node = node;
5647     ret->targetNamespace = nsName;
5648 
5649     if (ctxt->isRedefine) {
5650 	ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5651 	    ret, name, nsName);
5652 	if (ctxt->redef == NULL) {
5653 	    xmlFree(ret);
5654 	    return(NULL);
5655 	}
5656 	ctxt->redefCounter = 0;
5657     }
5658     WXS_ADD_GLOBAL(ctxt, ret);
5659     WXS_ADD_PENDING(ctxt, ret);
5660     return (ret);
5661 }
5662 
5663 /**
5664  * xmlSchemaNewWildcardNs:
5665  * @ctxt:  a schema validation context
5666  *
5667  * Creates a new wildcard namespace constraint.
5668  *
5669  * Returns the new structure or NULL in case of error
5670  */
5671 static xmlSchemaWildcardNsPtr
xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)5672 xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
5673 {
5674     xmlSchemaWildcardNsPtr ret;
5675 
5676     ret = (xmlSchemaWildcardNsPtr)
5677 	xmlMalloc(sizeof(xmlSchemaWildcardNs));
5678     if (ret == NULL) {
5679 	xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
5680 	return (NULL);
5681     }
5682     ret->value = NULL;
5683     ret->next = NULL;
5684     return (ret);
5685 }
5686 
5687 static xmlSchemaIDCPtr
xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName,int category,xmlNodePtr node)5688 xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5689                   const xmlChar *name, const xmlChar *nsName,
5690 		  int category, xmlNodePtr node)
5691 {
5692     xmlSchemaIDCPtr ret = NULL;
5693 
5694     if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5695         return (NULL);
5696 
5697     ret = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
5698     if (ret == NULL) {
5699         xmlSchemaPErrMemory(ctxt,
5700 	    "allocating an identity-constraint definition", NULL);
5701         return (NULL);
5702     }
5703     memset(ret, 0, sizeof(xmlSchemaIDC));
5704     /* The target namespace of the parent element declaration. */
5705     ret->targetNamespace = nsName;
5706     ret->name = name;
5707     ret->type = category;
5708     ret->node = node;
5709 
5710     WXS_ADD_GLOBAL(ctxt, ret);
5711     /*
5712     * Only keyrefs need to be fixup up.
5713     */
5714     if (category == XML_SCHEMA_TYPE_IDC_KEYREF)
5715 	WXS_ADD_PENDING(ctxt, ret);
5716     return (ret);
5717 }
5718 
5719 /**
5720  * xmlSchemaAddWildcard:
5721  * @ctxt:  a schema validation context
5722  * @schema: a schema
5723  *
5724  * Adds a wildcard.
5725  * It corresponds to a xsd:anyAttribute and xsd:any.
5726  *
5727  * Returns the new structure or NULL in case of error
5728  */
5729 static xmlSchemaWildcardPtr
xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaTypeType type,xmlNodePtr node)5730 xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5731 		     xmlSchemaTypeType type, xmlNodePtr node)
5732 {
5733     xmlSchemaWildcardPtr ret = NULL;
5734 
5735     if ((ctxt == NULL) || (schema == NULL))
5736         return (NULL);
5737 
5738     ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
5739     if (ret == NULL) {
5740         xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
5741         return (NULL);
5742     }
5743     memset(ret, 0, sizeof(xmlSchemaWildcard));
5744     ret->type = type;
5745     ret->node = node;
5746     WXS_ADD_LOCAL(ctxt, ret);
5747     return (ret);
5748 }
5749 
5750 static void
xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group)5751 xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group)
5752 {
5753     if (group == NULL)
5754 	return;
5755     if (group->members != NULL)
5756 	xmlSchemaItemListFree(group->members);
5757     xmlFree(group);
5758 }
5759 
5760 static void
xmlSchemaSubstGroupFreeEntry(void * group,const xmlChar * name ATTRIBUTE_UNUSED)5761 xmlSchemaSubstGroupFreeEntry(void *group, const xmlChar *name ATTRIBUTE_UNUSED)
5762 {
5763     xmlSchemaSubstGroupFree((xmlSchemaSubstGroupPtr) group);
5764 }
5765 
5766 static xmlSchemaSubstGroupPtr
xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt,xmlSchemaElementPtr head)5767 xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt,
5768 		       xmlSchemaElementPtr head)
5769 {
5770     xmlSchemaSubstGroupPtr ret;
5771 
5772     /* Init subst group hash. */
5773     if (WXS_SUBST_GROUPS(pctxt) == NULL) {
5774 	WXS_SUBST_GROUPS(pctxt) = xmlHashCreateDict(10, pctxt->dict);
5775 	if (WXS_SUBST_GROUPS(pctxt) == NULL)
5776 	    return(NULL);
5777     }
5778     /* Create a new substitution group. */
5779     ret = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
5780     if (ret == NULL) {
5781 	xmlSchemaPErrMemory(NULL,
5782 	    "allocating a substitution group container", NULL);
5783 	return(NULL);
5784     }
5785     memset(ret, 0, sizeof(xmlSchemaSubstGroup));
5786     ret->head = head;
5787     /* Create list of members. */
5788     ret->members = xmlSchemaItemListCreate();
5789     if (ret->members == NULL) {
5790 	xmlSchemaSubstGroupFree(ret);
5791 	return(NULL);
5792     }
5793     /* Add subst group to hash. */
5794     if (xmlHashAddEntry2(WXS_SUBST_GROUPS(pctxt),
5795 	head->name, head->targetNamespace, ret) != 0) {
5796 	PERROR_INT("xmlSchemaSubstGroupAdd",
5797 	    "failed to add a new substitution container");
5798 	xmlSchemaSubstGroupFree(ret);
5799 	return(NULL);
5800     }
5801     return(ret);
5802 }
5803 
5804 static xmlSchemaSubstGroupPtr
xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt,xmlSchemaElementPtr head)5805 xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt,
5806 		       xmlSchemaElementPtr head)
5807 {
5808     if (WXS_SUBST_GROUPS(pctxt) == NULL)
5809 	return(NULL);
5810     return(xmlHashLookup2(WXS_SUBST_GROUPS(pctxt),
5811 	head->name, head->targetNamespace));
5812 
5813 }
5814 
5815 /**
5816  * xmlSchemaAddElementSubstitutionMember:
5817  * @pctxt:  a schema parser context
5818  * @head:  the head of the substitution group
5819  * @member: the new member of the substitution group
5820  *
5821  * Allocate a new annotation structure.
5822  *
5823  * Returns the newly allocated structure or NULL in case or error
5824  */
5825 static int
xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,xmlSchemaElementPtr head,xmlSchemaElementPtr member)5826 xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
5827 				      xmlSchemaElementPtr head,
5828 				      xmlSchemaElementPtr member)
5829 {
5830     xmlSchemaSubstGroupPtr substGroup = NULL;
5831 
5832     if ((pctxt == NULL) || (head == NULL) || (member == NULL))
5833 	return (-1);
5834 
5835     substGroup = xmlSchemaSubstGroupGet(pctxt, head);
5836     if (substGroup == NULL)
5837 	substGroup = xmlSchemaSubstGroupAdd(pctxt, head);
5838     if (substGroup == NULL)
5839 	return(-1);
5840     if (xmlSchemaItemListAdd(substGroup->members, member) == -1)
5841 	return(-1);
5842     return(0);
5843 }
5844 
5845 /************************************************************************
5846  *									*
5847  *		Utilities for parsing					*
5848  *									*
5849  ************************************************************************/
5850 
5851 /**
5852  * xmlSchemaPValAttrNodeQNameValue:
5853  * @ctxt:  a schema parser context
5854  * @schema: the schema context
5855  * @ownerItem: the parent as a schema object
5856  * @value:  the QName value
5857  * @uri:  the resulting namespace URI if found
5858  * @local: the resulting local part if found, the attribute value otherwise
5859  *
5860  * Extracts the local name and the URI of a QName value and validates it.
5861  * This one is intended to be used on attribute values that
5862  * should resolve to schema components.
5863  *
5864  * Returns 0, in case the QName is valid, a positive error code
5865  * if not valid and -1 if an internal error occurs.
5866  */
5867 static int
xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,const xmlChar * value,const xmlChar ** uri,const xmlChar ** local)5868 xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
5869 				       xmlSchemaPtr schema,
5870 				       xmlSchemaBasicItemPtr ownerItem,
5871 				       xmlAttrPtr attr,
5872 				       const xmlChar *value,
5873 				       const xmlChar **uri,
5874 				       const xmlChar **local)
5875 {
5876     const xmlChar *pref;
5877     xmlNsPtr ns;
5878     int len, ret;
5879 
5880     *uri = NULL;
5881     *local = NULL;
5882     ret = xmlValidateQName(value, 1);
5883     if (ret > 0) {
5884 	xmlSchemaPSimpleTypeErr(ctxt,
5885 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5886 	    ownerItem, (xmlNodePtr) attr,
5887 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
5888 	    NULL, value, NULL, NULL, NULL);
5889 	*local = value;
5890 	return (ctxt->err);
5891     } else if (ret < 0)
5892 	return (-1);
5893 
5894     if (!strchr((char *) value, ':')) {
5895 	ns = xmlSearchNs(attr->doc, attr->parent, NULL);
5896 	if (ns)
5897 	    *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5898 	else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
5899 	    /* TODO: move XML_SCHEMAS_INCLUDING_CONVERT_NS to the
5900 	    * parser context. */
5901 	    /*
5902 	    * This one takes care of included schemas with no
5903 	    * target namespace.
5904 	    */
5905 	    *uri = ctxt->targetNamespace;
5906 	}
5907 	*local = xmlDictLookup(ctxt->dict, value, -1);
5908 	return (0);
5909     }
5910     /*
5911     * At this point xmlSplitQName3 has to return a local name.
5912     */
5913     *local = xmlSplitQName3(value, &len);
5914     *local = xmlDictLookup(ctxt->dict, *local, -1);
5915     pref = xmlDictLookup(ctxt->dict, value, len);
5916     ns = xmlSearchNs(attr->doc, attr->parent, pref);
5917     if (ns == NULL) {
5918 	xmlSchemaPSimpleTypeErr(ctxt,
5919 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5920 	    ownerItem, (xmlNodePtr) attr,
5921 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
5922 	    "The value '%s' of simple type 'xs:QName' has no "
5923 	    "corresponding namespace declaration in scope", value, NULL);
5924 	return (ctxt->err);
5925     } else {
5926         *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5927     }
5928     return (0);
5929 }
5930 
5931 /**
5932  * xmlSchemaPValAttrNodeQName:
5933  * @ctxt:  a schema parser context
5934  * @schema: the schema context
5935  * @ownerItem: the owner as a schema object
5936  * @attr:  the attribute node
5937  * @uri:  the resulting namespace URI if found
5938  * @local: the resulting local part if found, the attribute value otherwise
5939  *
5940  * Extracts and validates the QName of an attribute value.
5941  * This one is intended to be used on attribute values that
5942  * should resolve to schema components.
5943  *
5944  * Returns 0, in case the QName is valid, a positive error code
5945  * if not valid and -1 if an internal error occurs.
5946  */
5947 static int
xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,const xmlChar ** uri,const xmlChar ** local)5948 xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
5949 				       xmlSchemaPtr schema,
5950 				       xmlSchemaBasicItemPtr ownerItem,
5951 				       xmlAttrPtr attr,
5952 				       const xmlChar **uri,
5953 				       const xmlChar **local)
5954 {
5955     const xmlChar *value;
5956 
5957     value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5958     return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
5959 	ownerItem, attr, value, uri, local));
5960 }
5961 
5962 /**
5963  * xmlSchemaPValAttrQName:
5964  * @ctxt:  a schema parser context
5965  * @schema: the schema context
5966  * @ownerItem: the owner as a schema object
5967  * @ownerElem:  the parent node of the attribute
5968  * @name:  the name of the attribute
5969  * @uri:  the resulting namespace URI if found
5970  * @local: the resulting local part if found, the attribute value otherwise
5971  *
5972  * Extracts and validates the QName of an attribute value.
5973  *
5974  * Returns 0, in case the QName is valid, a positive error code
5975  * if not valid and -1 if an internal error occurs.
5976  */
5977 static int
xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaBasicItemPtr ownerItem,xmlNodePtr ownerElem,const char * name,const xmlChar ** uri,const xmlChar ** local)5978 xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5979 				   xmlSchemaPtr schema,
5980 				   xmlSchemaBasicItemPtr ownerItem,
5981 				   xmlNodePtr ownerElem,
5982 				   const char *name,
5983 				   const xmlChar **uri,
5984 				   const xmlChar **local)
5985 {
5986     xmlAttrPtr attr;
5987 
5988     attr = xmlSchemaGetPropNode(ownerElem, name);
5989     if (attr == NULL) {
5990 	*local = NULL;
5991 	*uri = NULL;
5992 	return (0);
5993     }
5994     return (xmlSchemaPValAttrNodeQName(ctxt, schema,
5995 	ownerItem, attr, uri, local));
5996 }
5997 
5998 /**
5999  * xmlSchemaPValAttrID:
6000  * @ctxt:  a schema parser context
6001  *
6002  * Extracts and validates the ID of an attribute value.
6003  *
6004  * Returns 0, in case the ID is valid, a positive error code
6005  * if not valid and -1 if an internal error occurs.
6006  */
6007 static int
xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt,xmlAttrPtr attr)6008 xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr)
6009 {
6010     int ret;
6011     const xmlChar *value;
6012 
6013     if (attr == NULL)
6014 	return(0);
6015     value = xmlSchemaGetNodeContentNoDict((xmlNodePtr) attr);
6016     ret = xmlValidateNCName(value, 1);
6017     if (ret == 0) {
6018 	/*
6019 	* NOTE: the IDness might have already be declared in the DTD
6020 	*/
6021 	if (attr->atype != XML_ATTRIBUTE_ID) {
6022 	    xmlIDPtr res;
6023 	    xmlChar *strip;
6024 
6025 	    /*
6026 	    * TODO: Use xmlSchemaStrip here; it's not exported at this
6027 	    * moment.
6028 	    */
6029 	    strip = xmlSchemaCollapseString(value);
6030 	    if (strip != NULL) {
6031 		xmlFree((xmlChar *) value);
6032 		value = strip;
6033 	    }
6034 	    res = xmlAddID(NULL, attr->doc, value, attr);
6035 	    if (res == NULL) {
6036 		ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
6037 		xmlSchemaPSimpleTypeErr(ctxt,
6038 		    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6039 		    NULL, (xmlNodePtr) attr,
6040 		    xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
6041 		    NULL, NULL, "Duplicate value '%s' of simple "
6042 		    "type 'xs:ID'", value, NULL);
6043 	    } else
6044 		attr->atype = XML_ATTRIBUTE_ID;
6045 	}
6046     } else if (ret > 0) {
6047 	ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
6048 	xmlSchemaPSimpleTypeErr(ctxt,
6049 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6050 	    NULL, (xmlNodePtr) attr,
6051 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
6052 	    NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
6053 	    "not a valid 'xs:NCName'",
6054 	    value, NULL);
6055     }
6056     if (value != NULL)
6057 	xmlFree((xmlChar *)value);
6058 
6059     return (ret);
6060 }
6061 
6062 static int
xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr ownerElem,const xmlChar * name)6063 xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
6064 		    xmlNodePtr ownerElem,
6065 		    const xmlChar *name)
6066 {
6067     xmlAttrPtr attr;
6068 
6069     attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
6070     if (attr == NULL)
6071 	return(0);
6072     return(xmlSchemaPValAttrNodeID(ctxt, attr));
6073 
6074 }
6075 
6076 /**
6077  * xmlGetMaxOccurs:
6078  * @ctxt:  a schema validation context
6079  * @node:  a subtree containing XML Schema information
6080  *
6081  * Get the maxOccurs property
6082  *
6083  * Returns the default if not found, or the value
6084  */
6085 static int
xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int min,int max,int def,const char * expected)6086 xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
6087 		int min, int max, int def, const char *expected)
6088 {
6089     const xmlChar *val, *cur;
6090     int ret = 0;
6091     xmlAttrPtr attr;
6092 
6093     attr = xmlSchemaGetPropNode(node, "maxOccurs");
6094     if (attr == NULL)
6095 	return (def);
6096     val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6097 
6098     if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
6099 	if (max != UNBOUNDED) {
6100 	    xmlSchemaPSimpleTypeErr(ctxt,
6101 		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6102 		/* XML_SCHEMAP_INVALID_MINOCCURS, */
6103 		NULL, (xmlNodePtr) attr, NULL, expected,
6104 		val, NULL, NULL, NULL);
6105 	    return (def);
6106 	} else
6107 	    return (UNBOUNDED);  /* encoding it with -1 might be another option */
6108     }
6109 
6110     cur = val;
6111     while (IS_BLANK_CH(*cur))
6112         cur++;
6113     if (*cur == 0) {
6114         xmlSchemaPSimpleTypeErr(ctxt,
6115 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6116 	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
6117 	    NULL, (xmlNodePtr) attr, NULL, expected,
6118 	    val, NULL, NULL, NULL);
6119 	return (def);
6120     }
6121     while ((*cur >= '0') && (*cur <= '9')) {
6122         if (ret > INT_MAX / 10) {
6123             ret = INT_MAX;
6124         } else {
6125             int digit = *cur - '0';
6126             ret *= 10;
6127             if (ret > INT_MAX - digit)
6128                 ret = INT_MAX;
6129             else
6130                 ret += digit;
6131         }
6132         cur++;
6133     }
6134     while (IS_BLANK_CH(*cur))
6135         cur++;
6136     /*
6137     * TODO: Restrict the maximal value to Integer.
6138     */
6139     if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
6140 	xmlSchemaPSimpleTypeErr(ctxt,
6141 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6142 	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
6143 	    NULL, (xmlNodePtr) attr, NULL, expected,
6144 	    val, NULL, NULL, NULL);
6145         return (def);
6146     }
6147     return (ret);
6148 }
6149 
6150 /**
6151  * xmlGetMinOccurs:
6152  * @ctxt:  a schema validation context
6153  * @node:  a subtree containing XML Schema information
6154  *
6155  * Get the minOccurs property
6156  *
6157  * Returns the default if not found, or the value
6158  */
6159 static int
xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int min,int max,int def,const char * expected)6160 xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
6161 		int min, int max, int def, const char *expected)
6162 {
6163     const xmlChar *val, *cur;
6164     int ret = 0;
6165     xmlAttrPtr attr;
6166 
6167     attr = xmlSchemaGetPropNode(node, "minOccurs");
6168     if (attr == NULL)
6169 	return (def);
6170     val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6171     cur = val;
6172     while (IS_BLANK_CH(*cur))
6173         cur++;
6174     if (*cur == 0) {
6175         xmlSchemaPSimpleTypeErr(ctxt,
6176 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6177 	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
6178 	    NULL, (xmlNodePtr) attr, NULL, expected,
6179 	    val, NULL, NULL, NULL);
6180         return (def);
6181     }
6182     while ((*cur >= '0') && (*cur <= '9')) {
6183         if (ret > INT_MAX / 10) {
6184             ret = INT_MAX;
6185         } else {
6186             int digit = *cur - '0';
6187             ret *= 10;
6188             if (ret > INT_MAX - digit)
6189                 ret = INT_MAX;
6190             else
6191                 ret += digit;
6192         }
6193         cur++;
6194     }
6195     while (IS_BLANK_CH(*cur))
6196         cur++;
6197     /*
6198     * TODO: Restrict the maximal value to Integer.
6199     */
6200     if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
6201 	xmlSchemaPSimpleTypeErr(ctxt,
6202 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6203 	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
6204 	    NULL, (xmlNodePtr) attr, NULL, expected,
6205 	    val, NULL, NULL, NULL);
6206         return (def);
6207     }
6208     return (ret);
6209 }
6210 
6211 /**
6212  * xmlSchemaPGetBoolNodeValue:
6213  * @ctxt:  a schema validation context
6214  * @ownerItem:  the owner as a schema item
6215  * @node: the node holding the value
6216  *
6217  * Converts a boolean string value into 1 or 0.
6218  *
6219  * Returns 0 or 1.
6220  */
6221 static int
xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,xmlSchemaBasicItemPtr ownerItem,xmlNodePtr node)6222 xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
6223 			   xmlSchemaBasicItemPtr ownerItem,
6224 			   xmlNodePtr node)
6225 {
6226     xmlChar *value = NULL;
6227     int res = 0;
6228 
6229     value = xmlNodeGetContent(node);
6230     /*
6231     * 3.2.2.1 Lexical representation
6232     * An instance of a datatype that is defined as `boolean`
6233     * can have the following legal literals {true, false, 1, 0}.
6234     */
6235     if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
6236         res = 1;
6237     else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
6238         res = 0;
6239     else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
6240 	res = 1;
6241     else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
6242         res = 0;
6243     else {
6244         xmlSchemaPSimpleTypeErr(ctxt,
6245 	    XML_SCHEMAP_INVALID_BOOLEAN,
6246 	    ownerItem, node,
6247 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6248 	    NULL, BAD_CAST value,
6249 	    NULL, NULL, NULL);
6250     }
6251     if (value != NULL)
6252 	xmlFree(value);
6253     return (res);
6254 }
6255 
6256 /**
6257  * xmlGetBooleanProp:
6258  * @ctxt:  a schema validation context
6259  * @node:  a subtree containing XML Schema information
6260  * @name:  the attribute name
6261  * @def:  the default value
6262  *
6263  * Evaluate if a boolean property is set
6264  *
6265  * Returns the default if not found, 0 if found to be false,
6266  * 1 if found to be true
6267  */
6268 static int
xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,const char * name,int def)6269 xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
6270 		  xmlNodePtr node,
6271                   const char *name, int def)
6272 {
6273     const xmlChar *val;
6274 
6275     val = xmlSchemaGetProp(ctxt, node, name);
6276     if (val == NULL)
6277         return (def);
6278     /*
6279     * 3.2.2.1 Lexical representation
6280     * An instance of a datatype that is defined as `boolean`
6281     * can have the following legal literals {true, false, 1, 0}.
6282     */
6283     if (xmlStrEqual(val, BAD_CAST "true"))
6284         def = 1;
6285     else if (xmlStrEqual(val, BAD_CAST "false"))
6286         def = 0;
6287     else if (xmlStrEqual(val, BAD_CAST "1"))
6288 	def = 1;
6289     else if (xmlStrEqual(val, BAD_CAST "0"))
6290         def = 0;
6291     else {
6292         xmlSchemaPSimpleTypeErr(ctxt,
6293 	    XML_SCHEMAP_INVALID_BOOLEAN,
6294 	    NULL,
6295 	    (xmlNodePtr) xmlSchemaGetPropNode(node, name),
6296 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6297 	    NULL, val, NULL, NULL, NULL);
6298     }
6299     return (def);
6300 }
6301 
6302 /************************************************************************
6303  *									*
6304  *		Schema extraction from an Infoset			*
6305  *									*
6306  ************************************************************************/
6307 static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
6308                                                  ctxt, xmlSchemaPtr schema,
6309                                                  xmlNodePtr node,
6310 						 int topLevel);
6311 static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
6312                                                   ctxt,
6313                                                   xmlSchemaPtr schema,
6314                                                   xmlNodePtr node,
6315 						  int topLevel);
6316 static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
6317                                                   ctxt,
6318                                                   xmlSchemaPtr schema,
6319                                                   xmlNodePtr node,
6320 						  xmlSchemaTypeType parentType);
6321 static xmlSchemaBasicItemPtr
6322 xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
6323 			     xmlSchemaPtr schema,
6324 			     xmlNodePtr node,
6325 			     xmlSchemaItemListPtr uses,
6326 			     int parentType);
6327 static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
6328                                            xmlSchemaPtr schema,
6329                                            xmlNodePtr node);
6330 static xmlSchemaWildcardPtr
6331 xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6332                            xmlSchemaPtr schema, xmlNodePtr node);
6333 
6334 /**
6335  * xmlSchemaPValAttrNodeValue:
6336  *
6337  * @pctxt:  a schema parser context
6338  * @ownerItem: the schema object owner if existent
6339  * @attr:  the schema attribute node being validated
6340  * @value: the value
6341  * @type: the built-in type to be validated against
6342  *
6343  * Validates a value against the given built-in type.
6344  * This one is intended to be used internally for validation
6345  * of schema attribute values during parsing of the schema.
6346  *
6347  * Returns 0 if the value is valid, a positive error code
6348  * number otherwise and -1 in case of an internal or API error.
6349  */
6350 static int
xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,const xmlChar * value,xmlSchemaTypePtr type)6351 xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
6352 			   xmlSchemaBasicItemPtr ownerItem,
6353 			   xmlAttrPtr attr,
6354 			   const xmlChar *value,
6355 			   xmlSchemaTypePtr type)
6356 {
6357 
6358     int ret = 0;
6359 
6360     /*
6361     * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
6362     * one is really meant to be used internally, so better not.
6363     */
6364     if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
6365 	return (-1);
6366     if (type->type != XML_SCHEMA_TYPE_BASIC) {
6367 	PERROR_INT("xmlSchemaPValAttrNodeValue",
6368 	    "the given type is not a built-in type");
6369 	return (-1);
6370     }
6371     switch (type->builtInType) {
6372 	case XML_SCHEMAS_NCNAME:
6373 	case XML_SCHEMAS_QNAME:
6374 	case XML_SCHEMAS_ANYURI:
6375 	case XML_SCHEMAS_TOKEN:
6376 	case XML_SCHEMAS_LANGUAGE:
6377 	    ret = xmlSchemaValPredefTypeNode(type, value, NULL,
6378 		(xmlNodePtr) attr);
6379 	    break;
6380 	default: {
6381 	    PERROR_INT("xmlSchemaPValAttrNodeValue",
6382 		"validation using the given type is not supported while "
6383 		"parsing a schema");
6384 	    return (-1);
6385 	}
6386     }
6387     /*
6388     * TODO: Should we use the S4S error codes instead?
6389     */
6390     if (ret < 0) {
6391 	PERROR_INT("xmlSchemaPValAttrNodeValue",
6392 	    "failed to validate a schema attribute value");
6393 	return (-1);
6394     } else if (ret > 0) {
6395 	if (WXS_IS_LIST(type))
6396 	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
6397 	else
6398 	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
6399 	xmlSchemaPSimpleTypeErr(pctxt,
6400 	    ret, ownerItem, (xmlNodePtr) attr,
6401 	    type, NULL, value, NULL, NULL, NULL);
6402     }
6403     return (ret);
6404 }
6405 
6406 /**
6407  * xmlSchemaPValAttrNode:
6408  *
6409  * @ctxt:  a schema parser context
6410  * @ownerItem: the schema object owner if existent
6411  * @attr:  the schema attribute node being validated
6412  * @type: the built-in type to be validated against
6413  * @value: the resulting value if any
6414  *
6415  * Extracts and validates a value against the given built-in type.
6416  * This one is intended to be used internally for validation
6417  * of schema attribute values during parsing of the schema.
6418  *
6419  * Returns 0 if the value is valid, a positive error code
6420  * number otherwise and -1 in case of an internal or API error.
6421  */
6422 static int
xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,xmlSchemaTypePtr type,const xmlChar ** value)6423 xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
6424 			   xmlSchemaBasicItemPtr ownerItem,
6425 			   xmlAttrPtr attr,
6426 			   xmlSchemaTypePtr type,
6427 			   const xmlChar **value)
6428 {
6429     const xmlChar *val;
6430 
6431     if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
6432 	return (-1);
6433 
6434     val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6435     if (value != NULL)
6436 	*value = val;
6437 
6438     return (xmlSchemaPValAttrNodeValue(ctxt, ownerItem, attr,
6439 	val, type));
6440 }
6441 
6442 /**
6443  * xmlSchemaPValAttr:
6444  *
6445  * @ctxt:  a schema parser context
6446  * @node: the element node of the attribute
6447  * @ownerItem: the schema object owner if existent
6448  * @ownerElem: the owner element node
6449  * @name:  the name of the schema attribute node
6450  * @type: the built-in type to be validated against
6451  * @value: the resulting value if any
6452  *
6453  * Extracts and validates a value against the given built-in type.
6454  * This one is intended to be used internally for validation
6455  * of schema attribute values during parsing of the schema.
6456  *
6457  * Returns 0 if the value is valid, a positive error code
6458  * number otherwise and -1 in case of an internal or API error.
6459  */
6460 static int
xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,xmlSchemaBasicItemPtr ownerItem,xmlNodePtr ownerElem,const char * name,xmlSchemaTypePtr type,const xmlChar ** value)6461 xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
6462 		       xmlSchemaBasicItemPtr ownerItem,
6463 		       xmlNodePtr ownerElem,
6464 		       const char *name,
6465 		       xmlSchemaTypePtr type,
6466 		       const xmlChar **value)
6467 {
6468     xmlAttrPtr attr;
6469 
6470     if ((ctxt == NULL) || (type == NULL)) {
6471 	if (value != NULL)
6472 	    *value = NULL;
6473 	return (-1);
6474     }
6475     if (type->type != XML_SCHEMA_TYPE_BASIC) {
6476 	if (value != NULL)
6477 	    *value = NULL;
6478 	xmlSchemaPErr(ctxt, ownerElem,
6479 	    XML_SCHEMAP_INTERNAL,
6480 	    "Internal error: xmlSchemaPValAttr, the given "
6481 	    "type '%s' is not a built-in type.\n",
6482 	    type->name, NULL);
6483 	return (-1);
6484     }
6485     attr = xmlSchemaGetPropNode(ownerElem, name);
6486     if (attr == NULL) {
6487 	if (value != NULL)
6488 	    *value = NULL;
6489 	return (0);
6490     }
6491     return (xmlSchemaPValAttrNode(ctxt, ownerItem, attr,
6492 	type, value));
6493 }
6494 
6495 static int
xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema ATTRIBUTE_UNUSED,xmlNodePtr node,xmlAttrPtr attr,const xmlChar * namespaceName)6496 xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
6497 		  xmlSchemaPtr schema ATTRIBUTE_UNUSED,
6498 		  xmlNodePtr node,
6499 		  xmlAttrPtr attr,
6500 		  const xmlChar *namespaceName)
6501 {
6502     /* TODO: Pointer comparison instead? */
6503     if (xmlStrEqual(pctxt->targetNamespace, namespaceName))
6504 	return (0);
6505     if (xmlStrEqual(xmlSchemaNs, namespaceName))
6506 	return (0);
6507     /*
6508     * Check if the referenced namespace was <import>ed.
6509     */
6510     if (WXS_BUCKET(pctxt)->relations != NULL) {
6511 	xmlSchemaSchemaRelationPtr rel;
6512 
6513 	rel = WXS_BUCKET(pctxt)->relations;
6514 	do {
6515 	    if (WXS_IS_BUCKET_IMPMAIN(rel->type) &&
6516 		xmlStrEqual(namespaceName, rel->importNamespace))
6517 		return (0);
6518 	    rel = rel->next;
6519 	} while (rel != NULL);
6520     }
6521     /*
6522     * No matching <import>ed namespace found.
6523     */
6524     {
6525 	xmlNodePtr n = (attr != NULL) ? (xmlNodePtr) attr : node;
6526 
6527 	if (namespaceName == NULL)
6528 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
6529 		XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6530 		"References from this schema to components in no "
6531 		"namespace are not allowed, since not indicated by an "
6532 		"import statement", NULL, NULL);
6533 	else
6534 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
6535 		XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6536 		"References from this schema to components in the "
6537 		"namespace '%s' are not allowed, since not indicated by an "
6538 		"import statement", namespaceName, NULL);
6539     }
6540     return (XML_SCHEMAP_SRC_RESOLVE);
6541 }
6542 
6543 /**
6544  * xmlSchemaParseLocalAttributes:
6545  * @ctxt:  a schema validation context
6546  * @schema:  the schema being built
6547  * @node:  a subtree containing XML Schema information
6548  * @type:  the hosting type where the attributes will be anchored
6549  *
6550  * Parses attribute uses and attribute declarations and
6551  * attribute group references.
6552  */
6553 static int
xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr * child,xmlSchemaItemListPtr * list,int parentType,int * hasRefs)6554 xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6555                         xmlNodePtr *child, xmlSchemaItemListPtr *list,
6556 			int parentType, int *hasRefs)
6557 {
6558     void *item;
6559 
6560     while ((IS_SCHEMA((*child), "attribute")) ||
6561            (IS_SCHEMA((*child), "attributeGroup"))) {
6562         if (IS_SCHEMA((*child), "attribute")) {
6563 	    item = xmlSchemaParseLocalAttribute(ctxt, schema, *child,
6564 		*list, parentType);
6565         } else {
6566             item = xmlSchemaParseAttributeGroupRef(ctxt, schema, *child);
6567 	    if ((item != NULL) && (hasRefs != NULL))
6568 		*hasRefs = 1;
6569         }
6570 	if (item != NULL) {
6571 	    if (*list == NULL) {
6572 		/* TODO: Customize grow factor. */
6573 		*list = xmlSchemaItemListCreate();
6574 		if (*list == NULL)
6575 		    return(-1);
6576 	    }
6577 	    if (xmlSchemaItemListAddSize(*list, 2, item) == -1)
6578 		return(-1);
6579 	}
6580         *child = (*child)->next;
6581     }
6582     return (0);
6583 }
6584 
6585 /**
6586  * xmlSchemaParseAnnotation:
6587  * @ctxt:  a schema validation context
6588  * @schema:  the schema being built
6589  * @node:  a subtree containing XML Schema information
6590  *
6591  * parse a XML schema Attribute declaration
6592  * *WARNING* this interface is highly subject to change
6593  *
6594  * Returns -1 in case of error, 0 if the declaration is improper and
6595  *         1 in case of success.
6596  */
6597 static xmlSchemaAnnotPtr
xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int needed)6598 xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int needed)
6599 {
6600     xmlSchemaAnnotPtr ret;
6601     xmlNodePtr child = NULL;
6602     xmlAttrPtr attr;
6603     int barked = 0;
6604 
6605     /*
6606     * INFO: S4S completed.
6607     */
6608     /*
6609     * id = ID
6610     * {any attributes with non-schema namespace . . .}>
6611     * Content: (appinfo | documentation)*
6612     */
6613     if ((ctxt == NULL) || (node == NULL))
6614         return (NULL);
6615     if (needed)
6616 	ret = xmlSchemaNewAnnot(ctxt, node);
6617     else
6618 	ret = NULL;
6619     attr = node->properties;
6620     while (attr != NULL) {
6621 	if (((attr->ns == NULL) &&
6622 	    (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
6623 	    ((attr->ns != NULL) &&
6624 	    xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
6625 
6626 	    xmlSchemaPIllegalAttrErr(ctxt,
6627 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6628 	}
6629 	attr = attr->next;
6630     }
6631     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6632     /*
6633     * And now for the children...
6634     */
6635     child = node->children;
6636     while (child != NULL) {
6637 	if (IS_SCHEMA(child, "appinfo")) {
6638 	    /* TODO: make available the content of "appinfo". */
6639 	    /*
6640 	    * source = anyURI
6641 	    * {any attributes with non-schema namespace . . .}>
6642 	    * Content: ({any})*
6643 	    */
6644 	    attr = child->properties;
6645 	    while (attr != NULL) {
6646 		if (((attr->ns == NULL) &&
6647 		     (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
6648 		     ((attr->ns != NULL) &&
6649 		      xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
6650 
6651 		    xmlSchemaPIllegalAttrErr(ctxt,
6652 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6653 		}
6654 		attr = attr->next;
6655 	    }
6656 	    xmlSchemaPValAttr(ctxt, NULL, child, "source",
6657 		xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
6658 	    child = child->next;
6659 	} else if (IS_SCHEMA(child, "documentation")) {
6660 	    /* TODO: make available the content of "documentation". */
6661 	    /*
6662 	    * source = anyURI
6663 	    * {any attributes with non-schema namespace . . .}>
6664 	    * Content: ({any})*
6665 	    */
6666 	    attr = child->properties;
6667 	    while (attr != NULL) {
6668 		if (attr->ns == NULL) {
6669 		    if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
6670 			xmlSchemaPIllegalAttrErr(ctxt,
6671 			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6672 		    }
6673 		} else {
6674 		    if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
6675 			(xmlStrEqual(attr->name, BAD_CAST "lang") &&
6676 			(!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
6677 
6678 			xmlSchemaPIllegalAttrErr(ctxt,
6679 			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6680 		    }
6681 		}
6682 		attr = attr->next;
6683 	    }
6684 	    /*
6685 	    * Attribute "xml:lang".
6686 	    */
6687 	    attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
6688 	    if (attr != NULL)
6689 		xmlSchemaPValAttrNode(ctxt, NULL, attr,
6690 		xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
6691 	    child = child->next;
6692 	} else {
6693 	    if (!barked)
6694 		xmlSchemaPContentErr(ctxt,
6695 		    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6696 		    NULL, node, child, NULL, "(appinfo | documentation)*");
6697 	    barked = 1;
6698 	    child = child->next;
6699 	}
6700     }
6701 
6702     return (ret);
6703 }
6704 
6705 /**
6706  * xmlSchemaParseFacet:
6707  * @ctxt:  a schema validation context
6708  * @schema:  the schema being built
6709  * @node:  a subtree containing XML Schema information
6710  *
6711  * parse a XML schema Facet declaration
6712  * *WARNING* this interface is highly subject to change
6713  *
6714  * Returns the new type structure or NULL in case of error
6715  */
6716 static xmlSchemaFacetPtr
xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)6717 xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6718                     xmlNodePtr node)
6719 {
6720     xmlSchemaFacetPtr facet;
6721     xmlNodePtr child = NULL;
6722     const xmlChar *value;
6723 
6724     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6725         return (NULL);
6726 
6727     facet = xmlSchemaNewFacet();
6728     if (facet == NULL) {
6729         xmlSchemaPErrMemory(ctxt, "allocating facet", node);
6730         return (NULL);
6731     }
6732     facet->node = node;
6733     value = xmlSchemaGetProp(ctxt, node, "value");
6734     if (value == NULL) {
6735         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
6736                        "Facet %s has no value\n", node->name, NULL);
6737         xmlSchemaFreeFacet(facet);
6738         return (NULL);
6739     }
6740     if (IS_SCHEMA(node, "minInclusive")) {
6741         facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
6742     } else if (IS_SCHEMA(node, "minExclusive")) {
6743         facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
6744     } else if (IS_SCHEMA(node, "maxInclusive")) {
6745         facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
6746     } else if (IS_SCHEMA(node, "maxExclusive")) {
6747         facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
6748     } else if (IS_SCHEMA(node, "totalDigits")) {
6749         facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
6750     } else if (IS_SCHEMA(node, "fractionDigits")) {
6751         facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
6752     } else if (IS_SCHEMA(node, "pattern")) {
6753         facet->type = XML_SCHEMA_FACET_PATTERN;
6754     } else if (IS_SCHEMA(node, "enumeration")) {
6755         facet->type = XML_SCHEMA_FACET_ENUMERATION;
6756     } else if (IS_SCHEMA(node, "whiteSpace")) {
6757         facet->type = XML_SCHEMA_FACET_WHITESPACE;
6758     } else if (IS_SCHEMA(node, "length")) {
6759         facet->type = XML_SCHEMA_FACET_LENGTH;
6760     } else if (IS_SCHEMA(node, "maxLength")) {
6761         facet->type = XML_SCHEMA_FACET_MAXLENGTH;
6762     } else if (IS_SCHEMA(node, "minLength")) {
6763         facet->type = XML_SCHEMA_FACET_MINLENGTH;
6764     } else {
6765         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
6766                        "Unknown facet type %s\n", node->name, NULL);
6767         xmlSchemaFreeFacet(facet);
6768         return (NULL);
6769     }
6770     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6771     facet->value = value;
6772     if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
6773 	(facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
6774 	const xmlChar *fixed;
6775 
6776 	fixed = xmlSchemaGetProp(ctxt, node, "fixed");
6777 	if (fixed != NULL) {
6778 	    if (xmlStrEqual(fixed, BAD_CAST "true"))
6779 		facet->fixed = 1;
6780 	}
6781     }
6782     child = node->children;
6783 
6784     if (IS_SCHEMA(child, "annotation")) {
6785         facet->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6786         child = child->next;
6787     }
6788     if (child != NULL) {
6789         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
6790                        "Facet %s has unexpected child content\n",
6791                        node->name, NULL);
6792     }
6793     return (facet);
6794 }
6795 
6796 /**
6797  * xmlSchemaParseWildcardNs:
6798  * @ctxt:  a schema parser context
6799  * @wildc:  the wildcard, already created
6800  * @node:  a subtree containing XML Schema information
6801  *
6802  * Parses the attribute "processContents" and "namespace"
6803  * of a xsd:anyAttribute and xsd:any.
6804  * *WARNING* this interface is highly subject to change
6805  *
6806  * Returns 0 if everything goes fine, a positive error code
6807  * if something is not valid and -1 if an internal error occurs.
6808  */
6809 static int
xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema ATTRIBUTE_UNUSED,xmlSchemaWildcardPtr wildc,xmlNodePtr node)6810 xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
6811 			 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
6812 			 xmlSchemaWildcardPtr wildc,
6813 			 xmlNodePtr node)
6814 {
6815     const xmlChar *pc, *ns, *dictnsItem;
6816     int ret = 0;
6817     xmlChar *nsItem;
6818     xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
6819     xmlAttrPtr attr;
6820 
6821     pc = xmlSchemaGetProp(ctxt, node, "processContents");
6822     if ((pc == NULL)
6823         || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
6824         wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6825     } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
6826         wildc->processContents = XML_SCHEMAS_ANY_SKIP;
6827     } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
6828         wildc->processContents = XML_SCHEMAS_ANY_LAX;
6829     } else {
6830         xmlSchemaPSimpleTypeErr(ctxt,
6831 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6832 	    NULL, node,
6833 	    NULL, "(strict | skip | lax)", pc,
6834 	    NULL, NULL, NULL);
6835         wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6836 	ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
6837     }
6838     /*
6839      * Build the namespace constraints.
6840      */
6841     attr = xmlSchemaGetPropNode(node, "namespace");
6842     ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6843     if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
6844 	wildc->any = 1;
6845     else if (xmlStrEqual(ns, BAD_CAST "##other")) {
6846 	wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
6847 	if (wildc->negNsSet == NULL) {
6848 	    return (-1);
6849 	}
6850 	wildc->negNsSet->value = ctxt->targetNamespace;
6851     } else {
6852 	const xmlChar *end, *cur;
6853 
6854 	cur = ns;
6855 	do {
6856 	    while (IS_BLANK_CH(*cur))
6857 		cur++;
6858 	    end = cur;
6859 	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6860 		end++;
6861 	    if (end == cur)
6862 		break;
6863 	    nsItem = xmlStrndup(cur, end - cur);
6864 	    if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
6865 		    (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
6866 		xmlSchemaPSimpleTypeErr(ctxt,
6867 		    XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
6868 		    NULL, (xmlNodePtr) attr,
6869 		    NULL,
6870 		    "((##any | ##other) | List of (xs:anyURI | "
6871 		    "(##targetNamespace | ##local)))",
6872 		    nsItem, NULL, NULL, NULL);
6873 		ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
6874 	    } else {
6875 		if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
6876 		    dictnsItem = ctxt->targetNamespace;
6877 		} else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
6878 		    dictnsItem = NULL;
6879 		} else {
6880 		    /*
6881 		    * Validate the item (anyURI).
6882 		    */
6883 		    xmlSchemaPValAttrNodeValue(ctxt, NULL, attr,
6884 			nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
6885 		    dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
6886 		}
6887 		/*
6888 		* Avoid duplicate namespaces.
6889 		*/
6890 		tmp = wildc->nsSet;
6891 		while (tmp != NULL) {
6892 		    if (dictnsItem == tmp->value)
6893 			break;
6894 		    tmp = tmp->next;
6895 		}
6896 		if (tmp == NULL) {
6897 		    tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
6898 		    if (tmp == NULL) {
6899 			xmlFree(nsItem);
6900 			return (-1);
6901 		    }
6902 		    tmp->value = dictnsItem;
6903 		    tmp->next = NULL;
6904 		    if (wildc->nsSet == NULL)
6905 			wildc->nsSet = tmp;
6906 		    else if (lastNs != NULL)
6907 			lastNs->next = tmp;
6908 		    lastNs = tmp;
6909 		}
6910 
6911 	    }
6912 	    xmlFree(nsItem);
6913 	    cur = end;
6914 	} while (*cur != 0);
6915     }
6916     return (ret);
6917 }
6918 
6919 static int
xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,xmlNodePtr node,int minOccurs,int maxOccurs)6920 xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
6921 				 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
6922 				 xmlNodePtr node,
6923 				 int minOccurs,
6924 				 int maxOccurs) {
6925 
6926     if ((maxOccurs == 0) && ( minOccurs == 0))
6927 	return (0);
6928     if (maxOccurs != UNBOUNDED) {
6929 	/*
6930 	* TODO: Maybe we should better not create the particle,
6931 	* if min/max is invalid, since it could confuse the build of the
6932 	* content model.
6933 	*/
6934 	/*
6935 	* 3.9.6 Schema Component Constraint: Particle Correct
6936 	*
6937 	*/
6938 	if (maxOccurs < 1) {
6939 	    /*
6940 	    * 2.2 {max occurs} must be greater than or equal to 1.
6941 	    */
6942 	    xmlSchemaPCustomAttrErr(ctxt,
6943 		XML_SCHEMAP_P_PROPS_CORRECT_2_2,
6944 		NULL, NULL,
6945 		xmlSchemaGetPropNode(node, "maxOccurs"),
6946 		"The value must be greater than or equal to 1");
6947 	    return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6948 	} else if (minOccurs > maxOccurs) {
6949 	    /*
6950 	    * 2.1 {min occurs} must not be greater than {max occurs}.
6951 	    */
6952 	    xmlSchemaPCustomAttrErr(ctxt,
6953 		XML_SCHEMAP_P_PROPS_CORRECT_2_1,
6954 		NULL, NULL,
6955 		xmlSchemaGetPropNode(node, "minOccurs"),
6956 		"The value must not be greater than the value of 'maxOccurs'");
6957 	    return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6958 	}
6959     }
6960     return (0);
6961 }
6962 
6963 /**
6964  * xmlSchemaParseAny:
6965  * @ctxt:  a schema validation context
6966  * @schema:  the schema being built
6967  * @node:  a subtree containing XML Schema information
6968  *
6969  * Parsea a XML schema <any> element. A particle and wildcard
6970  * will be created (except if minOccurs==maxOccurs==0, in this case
6971  * nothing will be created).
6972  * *WARNING* this interface is highly subject to change
6973  *
6974  * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
6975  */
6976 static xmlSchemaParticlePtr
xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)6977 xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6978                   xmlNodePtr node)
6979 {
6980     xmlSchemaParticlePtr particle;
6981     xmlNodePtr child = NULL;
6982     xmlSchemaWildcardPtr wild;
6983     int min, max;
6984     xmlAttrPtr attr;
6985     xmlSchemaAnnotPtr annot = NULL;
6986 
6987     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6988         return (NULL);
6989     /*
6990     * Check for illegal attributes.
6991     */
6992     attr = node->properties;
6993     while (attr != NULL) {
6994 	if (attr->ns == NULL) {
6995 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6996 		(!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6997 		(!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6998 	        (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6999 		(!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
7000 		xmlSchemaPIllegalAttrErr(ctxt,
7001 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7002 	    }
7003 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7004 	    xmlSchemaPIllegalAttrErr(ctxt,
7005 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7006 	}
7007 	attr = attr->next;
7008     }
7009     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
7010     /*
7011     * minOccurs/maxOccurs.
7012     */
7013     max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
7014 	"(xs:nonNegativeInteger | unbounded)");
7015     min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
7016 	"xs:nonNegativeInteger");
7017     xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
7018     /*
7019     * Create & parse the wildcard.
7020     */
7021     wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
7022     if (wild == NULL)
7023 	return (NULL);
7024     xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
7025     /*
7026     * And now for the children...
7027     */
7028     child = node->children;
7029     if (IS_SCHEMA(child, "annotation")) {
7030         annot = xmlSchemaParseAnnotation(ctxt, child, 1);
7031         child = child->next;
7032     }
7033     if (child != NULL) {
7034 	xmlSchemaPContentErr(ctxt,
7035 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7036 	    NULL, node, child,
7037 	    NULL, "(annotation?)");
7038     }
7039     /*
7040     * No component if minOccurs==maxOccurs==0.
7041     */
7042     if ((min == 0) && (max == 0)) {
7043 	/* Don't free the wildcard, since it's already on the list. */
7044 	return (NULL);
7045     }
7046     /*
7047     * Create the particle.
7048     */
7049     particle = xmlSchemaAddParticle(ctxt, node, min, max);
7050     if (particle == NULL)
7051         return (NULL);
7052     particle->annot = annot;
7053     particle->children = (xmlSchemaTreeItemPtr) wild;
7054 
7055     return (particle);
7056 }
7057 
7058 /**
7059  * xmlSchemaParseNotation:
7060  * @ctxt:  a schema validation context
7061  * @schema:  the schema being built
7062  * @node:  a subtree containing XML Schema information
7063  *
7064  * parse a XML schema Notation declaration
7065  *
7066  * Returns the new structure or NULL in case of error
7067  */
7068 static xmlSchemaNotationPtr
xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)7069 xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
7070                        xmlNodePtr node)
7071 {
7072     const xmlChar *name;
7073     xmlSchemaNotationPtr ret;
7074     xmlNodePtr child = NULL;
7075 
7076     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7077         return (NULL);
7078     name = xmlSchemaGetProp(ctxt, node, "name");
7079     if (name == NULL) {
7080         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
7081                        "Notation has no name\n", NULL, NULL);
7082         return (NULL);
7083     }
7084     ret = xmlSchemaAddNotation(ctxt, schema, name,
7085 	ctxt->targetNamespace, node);
7086     if (ret == NULL)
7087         return (NULL);
7088     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
7089 
7090     child = node->children;
7091     if (IS_SCHEMA(child, "annotation")) {
7092         ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
7093         child = child->next;
7094     }
7095     if (child != NULL) {
7096 	xmlSchemaPContentErr(ctxt,
7097 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7098 	    NULL, node, child,
7099 	    NULL, "(annotation?)");
7100     }
7101 
7102     return (ret);
7103 }
7104 
7105 /**
7106  * xmlSchemaParseAnyAttribute:
7107  * @ctxt:  a schema validation context
7108  * @schema:  the schema being built
7109  * @node:  a subtree containing XML Schema information
7110  *
7111  * parse a XML schema AnyAttribute declaration
7112  * *WARNING* this interface is highly subject to change
7113  *
7114  * Returns a wildcard or NULL.
7115  */
7116 static xmlSchemaWildcardPtr
xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)7117 xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
7118                            xmlSchemaPtr schema, xmlNodePtr node)
7119 {
7120     xmlSchemaWildcardPtr ret;
7121     xmlNodePtr child = NULL;
7122     xmlAttrPtr attr;
7123 
7124     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7125         return (NULL);
7126 
7127     ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
7128 	node);
7129     if (ret == NULL) {
7130         return (NULL);
7131     }
7132     /*
7133     * Check for illegal attributes.
7134     */
7135     attr = node->properties;
7136     while (attr != NULL) {
7137 	if (attr->ns == NULL) {
7138 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7139 	        (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
7140 		(!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
7141 		xmlSchemaPIllegalAttrErr(ctxt,
7142 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7143 	    }
7144 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7145 	    xmlSchemaPIllegalAttrErr(ctxt,
7146 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7147 	}
7148 	attr = attr->next;
7149     }
7150     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
7151     /*
7152     * Parse the namespace list.
7153     */
7154     if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
7155 	return (NULL);
7156     /*
7157     * And now for the children...
7158     */
7159     child = node->children;
7160     if (IS_SCHEMA(child, "annotation")) {
7161         ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
7162         child = child->next;
7163     }
7164     if (child != NULL) {
7165 	xmlSchemaPContentErr(ctxt,
7166 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7167 	    NULL, node, child,
7168 	    NULL, "(annotation?)");
7169     }
7170 
7171     return (ret);
7172 }
7173 
7174 
7175 /**
7176  * xmlSchemaParseAttribute:
7177  * @ctxt:  a schema validation context
7178  * @schema:  the schema being built
7179  * @node:  a subtree containing XML Schema information
7180  *
7181  * parse a XML schema Attribute declaration
7182  * *WARNING* this interface is highly subject to change
7183  *
7184  * Returns the attribute declaration.
7185  */
7186 static xmlSchemaBasicItemPtr
xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlSchemaItemListPtr uses,int parentType)7187 xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
7188 			     xmlSchemaPtr schema,
7189 			     xmlNodePtr node,
7190 			     xmlSchemaItemListPtr uses,
7191 			     int parentType)
7192 {
7193     const xmlChar *attrValue, *name = NULL, *ns = NULL;
7194     xmlSchemaAttributeUsePtr use = NULL;
7195     xmlNodePtr child = NULL;
7196     xmlAttrPtr attr;
7197     const xmlChar *tmpNs = NULL, *tmpName = NULL, *defValue = NULL;
7198     int isRef = 0, occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7199     int	nberrors, hasForm = 0, defValueType = 0;
7200 
7201 #define WXS_ATTR_DEF_VAL_DEFAULT 1
7202 #define WXS_ATTR_DEF_VAL_FIXED 2
7203 
7204     /*
7205      * 3.2.3 Constraints on XML Representations of Attribute Declarations
7206      */
7207 
7208     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7209         return (NULL);
7210     attr = xmlSchemaGetPropNode(node, "ref");
7211     if (attr != NULL) {
7212 	if (xmlSchemaPValAttrNodeQName(pctxt, schema,
7213 	    NULL, attr, &tmpNs, &tmpName) != 0) {
7214 	    return (NULL);
7215 	}
7216 	if (xmlSchemaCheckReference(pctxt, schema, node, attr, tmpNs) != 0)
7217 	    return(NULL);
7218 	isRef = 1;
7219     }
7220     nberrors = pctxt->nberrors;
7221     /*
7222     * Check for illegal attributes.
7223     */
7224     attr = node->properties;
7225     while (attr != NULL) {
7226 	if (attr->ns == NULL) {
7227 	    if (isRef) {
7228 		if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7229 		    xmlSchemaPValAttrNodeID(pctxt, attr);
7230 		    goto attr_next;
7231 		} else if (xmlStrEqual(attr->name, BAD_CAST "ref")) {
7232 		    goto attr_next;
7233 		}
7234 	    } else {
7235 		if (xmlStrEqual(attr->name, BAD_CAST "name")) {
7236 		    goto attr_next;
7237 		} else if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7238 		    xmlSchemaPValAttrNodeID(pctxt, attr);
7239 		    goto attr_next;
7240 		} else if (xmlStrEqual(attr->name, BAD_CAST "type")) {
7241 		    xmlSchemaPValAttrNodeQName(pctxt, schema, NULL,
7242 			attr, &tmpNs, &tmpName);
7243 		    goto attr_next;
7244 		} else if (xmlStrEqual(attr->name, BAD_CAST "form")) {
7245 		    /*
7246 		    * Evaluate the target namespace
7247 		    */
7248 		    hasForm = 1;
7249 		    attrValue = xmlSchemaGetNodeContent(pctxt,
7250 			(xmlNodePtr) attr);
7251 		    if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
7252 			ns = pctxt->targetNamespace;
7253 		    } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified"))
7254 		    {
7255 			xmlSchemaPSimpleTypeErr(pctxt,
7256 			    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7257 			    NULL, (xmlNodePtr) attr,
7258 			    NULL, "(qualified | unqualified)",
7259 			    attrValue, NULL, NULL, NULL);
7260 		    }
7261 		    goto attr_next;
7262 		}
7263 	    }
7264 	    if (xmlStrEqual(attr->name, BAD_CAST "use")) {
7265 
7266 		attrValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7267 		/* TODO: Maybe we need to normalize the value beforehand. */
7268 		if (xmlStrEqual(attrValue, BAD_CAST "optional"))
7269 		    occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7270 		else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
7271 		    occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
7272 		else if (xmlStrEqual(attrValue, BAD_CAST "required"))
7273 		    occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
7274 		else {
7275 		    xmlSchemaPSimpleTypeErr(pctxt,
7276 			XML_SCHEMAP_INVALID_ATTR_USE,
7277 			NULL, (xmlNodePtr) attr,
7278 			NULL, "(optional | prohibited | required)",
7279 			attrValue, NULL, NULL, NULL);
7280 		}
7281 		goto attr_next;
7282 	    } else if (xmlStrEqual(attr->name, BAD_CAST "default")) {
7283 		/*
7284 		* 3.2.3 : 1
7285 		* default and fixed must not both be present.
7286 		*/
7287 		if (defValue) {
7288 		    xmlSchemaPMutualExclAttrErr(pctxt,
7289 			XML_SCHEMAP_SRC_ATTRIBUTE_1,
7290 			NULL, attr, "default", "fixed");
7291 		} else {
7292 		    defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7293 		    defValueType = WXS_ATTR_DEF_VAL_DEFAULT;
7294 		}
7295 		goto attr_next;
7296 	    } else if (xmlStrEqual(attr->name, BAD_CAST "fixed")) {
7297 		/*
7298 		* 3.2.3 : 1
7299 		* default and fixed must not both be present.
7300 		*/
7301 		if (defValue) {
7302 		    xmlSchemaPMutualExclAttrErr(pctxt,
7303 			XML_SCHEMAP_SRC_ATTRIBUTE_1,
7304 			NULL, attr, "default", "fixed");
7305 		} else {
7306 		    defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7307 		    defValueType = WXS_ATTR_DEF_VAL_FIXED;
7308 		}
7309 		goto attr_next;
7310 	    }
7311 	} else if (! xmlStrEqual(attr->ns->href, xmlSchemaNs))
7312 	    goto attr_next;
7313 
7314 	xmlSchemaPIllegalAttrErr(pctxt,
7315 	    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7316 
7317 attr_next:
7318 	attr = attr->next;
7319     }
7320     /*
7321     * 3.2.3 : 2
7322     * If default and use are both present, use must have
7323     * the actual value optional.
7324     */
7325     if ((defValueType == WXS_ATTR_DEF_VAL_DEFAULT) &&
7326 	(occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
7327 	xmlSchemaPSimpleTypeErr(pctxt,
7328 	    XML_SCHEMAP_SRC_ATTRIBUTE_2,
7329 	    NULL, node, NULL,
7330 	    "(optional | prohibited | required)", NULL,
7331 	    "The value of the attribute 'use' must be 'optional' "
7332 	    "if the attribute 'default' is present",
7333 	    NULL, NULL);
7334     }
7335     /*
7336     * We want correct attributes.
7337     */
7338     if (nberrors != pctxt->nberrors)
7339 	return(NULL);
7340     if (! isRef) {
7341 	xmlSchemaAttributePtr attrDecl;
7342 
7343 	/* TODO: move XML_SCHEMAS_QUALIF_ATTR to the parser. */
7344 	if ((! hasForm) && (schema->flags & XML_SCHEMAS_QUALIF_ATTR))
7345 	    ns = pctxt->targetNamespace;
7346 	/*
7347 	* 3.2.6 Schema Component Constraint: xsi: Not Allowed
7348 	* TODO: Move this to the component layer.
7349 	*/
7350 	if (xmlStrEqual(ns, xmlSchemaInstanceNs)) {
7351 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
7352 		XML_SCHEMAP_NO_XSI,
7353 		node, NULL,
7354 		"The target namespace must not match '%s'",
7355 		xmlSchemaInstanceNs, NULL);
7356 	}
7357 	attr = xmlSchemaGetPropNode(node, "name");
7358 	if (attr == NULL) {
7359 	    xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7360 		NULL, node, "name", NULL);
7361 	    return (NULL);
7362 	}
7363 	if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7364 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7365 	    return (NULL);
7366 	}
7367 	/*
7368 	* 3.2.6 Schema Component Constraint: xmlns Not Allowed
7369 	* TODO: Move this to the component layer.
7370 	*/
7371 	if (xmlStrEqual(name, BAD_CAST "xmlns")) {
7372 	    xmlSchemaPSimpleTypeErr(pctxt,
7373 		XML_SCHEMAP_NO_XMLNS,
7374 		NULL, (xmlNodePtr) attr,
7375 		xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7376 		"The value of the attribute must not match 'xmlns'",
7377 		NULL, NULL);
7378 	    return (NULL);
7379 	}
7380 	if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED)
7381 	    goto check_children;
7382 	/*
7383 	* Create the attribute use component.
7384 	*/
7385 	use = xmlSchemaAddAttributeUse(pctxt, node);
7386 	if (use == NULL)
7387 	    return(NULL);
7388 	use->occurs = occurs;
7389 	/*
7390 	* Create the attribute declaration.
7391 	*/
7392 	attrDecl = xmlSchemaAddAttribute(pctxt, schema, name, ns, node, 0);
7393 	if (attrDecl == NULL)
7394 	    return (NULL);
7395 	if (tmpName != NULL) {
7396 	    attrDecl->typeName = tmpName;
7397 	    attrDecl->typeNs = tmpNs;
7398 	}
7399 	use->attrDecl = attrDecl;
7400 	/*
7401 	* Value constraint.
7402 	*/
7403 	if (defValue != NULL) {
7404 	    attrDecl->defValue = defValue;
7405 	    if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7406 		attrDecl->flags |= XML_SCHEMAS_ATTR_FIXED;
7407 	}
7408     } else if (occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7409 	xmlSchemaQNameRefPtr ref;
7410 
7411 	/*
7412 	* Create the attribute use component.
7413 	*/
7414 	use = xmlSchemaAddAttributeUse(pctxt, node);
7415 	if (use == NULL)
7416 	    return(NULL);
7417 	/*
7418 	* We need to resolve the reference at later stage.
7419 	*/
7420 	WXS_ADD_PENDING(pctxt, use);
7421 	use->occurs = occurs;
7422 	/*
7423 	* Create a QName reference to the attribute declaration.
7424 	*/
7425 	ref = xmlSchemaNewQNameRef(pctxt, XML_SCHEMA_TYPE_ATTRIBUTE,
7426 	    tmpName, tmpNs);
7427 	if (ref == NULL)
7428 	    return(NULL);
7429 	/*
7430 	* Assign the reference. This will be substituted for the
7431 	* referenced attribute declaration when the QName is resolved.
7432 	*/
7433 	use->attrDecl = WXS_ATTR_CAST ref;
7434 	/*
7435 	* Value constraint.
7436 	*/
7437 	if (defValue != NULL)
7438 	    use->defValue = defValue;
7439 	if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7440 	    use->flags |= XML_SCHEMA_ATTR_USE_FIXED;
7441     }
7442 
7443 check_children:
7444     /*
7445     * And now for the children...
7446     */
7447     child = node->children;
7448     if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7449 	xmlSchemaAttributeUseProhibPtr prohib;
7450 
7451 	if (IS_SCHEMA(child, "annotation")) {
7452 	    xmlSchemaParseAnnotation(pctxt, child, 0);
7453 	    child = child->next;
7454 	}
7455 	if (child != NULL) {
7456 	    xmlSchemaPContentErr(pctxt,
7457 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7458 		NULL, node, child, NULL,
7459 		"(annotation?)");
7460 	}
7461 	/*
7462 	* Check for pointlessness of attribute prohibitions.
7463 	*/
7464 	if (parentType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
7465 	    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7466 		XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7467 		node, NULL,
7468 		"Skipping attribute use prohibition, since it is "
7469 		"pointless inside an <attributeGroup>",
7470 		NULL, NULL, NULL);
7471 	    return(NULL);
7472 	} else if (parentType == XML_SCHEMA_TYPE_EXTENSION) {
7473 	    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7474 		XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7475 		node, NULL,
7476 		"Skipping attribute use prohibition, since it is "
7477 		"pointless when extending a type",
7478 		NULL, NULL, NULL);
7479 	    return(NULL);
7480 	}
7481 	if (! isRef) {
7482 	    tmpName = name;
7483 	    tmpNs = ns;
7484 	}
7485 	/*
7486 	* Check for duplicate attribute prohibitions.
7487 	*/
7488 	if (uses) {
7489 	    int i;
7490 
7491 	    for (i = 0; i < uses->nbItems; i++) {
7492 		use = uses->items[i];
7493 		if ((use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) &&
7494 		    (tmpName == (WXS_ATTR_PROHIB_CAST use)->name) &&
7495 		    (tmpNs == (WXS_ATTR_PROHIB_CAST use)->targetNamespace))
7496 		{
7497 		    xmlChar *str = NULL;
7498 
7499 		    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7500 			XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7501 			node, NULL,
7502 			"Skipping duplicate attribute use prohibition '%s'",
7503 			xmlSchemaFormatQName(&str, tmpNs, tmpName),
7504 			NULL, NULL);
7505 		    FREE_AND_NULL(str)
7506 		    return(NULL);
7507 		}
7508 	    }
7509 	}
7510 	/*
7511 	* Create the attribute prohibition helper component.
7512 	*/
7513 	prohib = xmlSchemaAddAttributeUseProhib(pctxt);
7514 	if (prohib == NULL)
7515 	    return(NULL);
7516 	prohib->node = node;
7517 	prohib->name = tmpName;
7518 	prohib->targetNamespace = tmpNs;
7519 	if (isRef) {
7520 	    /*
7521 	    * We need at least to resolve to the attribute declaration.
7522 	    */
7523 	    WXS_ADD_PENDING(pctxt, prohib);
7524 	}
7525 	return(WXS_BASIC_CAST prohib);
7526     } else {
7527 	if (IS_SCHEMA(child, "annotation")) {
7528 	    /*
7529 	    * TODO: Should this go into the attr decl?
7530 	    */
7531 	    use->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7532 	    child = child->next;
7533 	}
7534 	if (isRef) {
7535 	    if (child != NULL) {
7536 		if (IS_SCHEMA(child, "simpleType"))
7537 		    /*
7538 		    * 3.2.3 : 3.2
7539 		    * If ref is present, then all of <simpleType>,
7540 		    * form and type must be absent.
7541 		    */
7542 		    xmlSchemaPContentErr(pctxt,
7543 			XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
7544 			NULL, node, child, NULL,
7545 			"(annotation?)");
7546 		else
7547 		    xmlSchemaPContentErr(pctxt,
7548 			XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7549 			NULL, node, child, NULL,
7550 			"(annotation?)");
7551 	    }
7552 	} else {
7553 	    if (IS_SCHEMA(child, "simpleType")) {
7554 		if (WXS_ATTRUSE_DECL(use)->typeName != NULL) {
7555 		    /*
7556 		    * 3.2.3 : 4
7557 		    * type and <simpleType> must not both be present.
7558 		    */
7559 		    xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7560 			NULL, node, child,
7561 			"The attribute 'type' and the <simpleType> child "
7562 			"are mutually exclusive", NULL);
7563 		} else
7564 		    WXS_ATTRUSE_TYPEDEF(use) =
7565 			xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7566 		child = child->next;
7567 	    }
7568 	    if (child != NULL)
7569 		xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7570 		NULL, node, child, NULL,
7571 		"(annotation?, simpleType?)");
7572 	}
7573     }
7574     return (WXS_BASIC_CAST use);
7575 }
7576 
7577 
7578 static xmlSchemaAttributePtr
xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)7579 xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt,
7580 			      xmlSchemaPtr schema,
7581 			      xmlNodePtr node)
7582 {
7583     const xmlChar *attrValue;
7584     xmlSchemaAttributePtr ret;
7585     xmlNodePtr child = NULL;
7586     xmlAttrPtr attr;
7587 
7588     /*
7589      * Note that the w3c spec assumes the schema to be validated with schema
7590      * for schemas beforehand.
7591      *
7592      * 3.2.3 Constraints on XML Representations of Attribute Declarations
7593      */
7594     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7595         return (NULL);
7596     /*
7597     * 3.2.3 : 3.1
7598     * One of ref or name must be present, but not both
7599     */
7600     attr = xmlSchemaGetPropNode(node, "name");
7601     if (attr == NULL) {
7602 	xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7603 	    NULL, node, "name", NULL);
7604 	return (NULL);
7605     }
7606     if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7607 	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
7608 	return (NULL);
7609     }
7610     /*
7611     * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7612     * TODO: Move this to the component layer.
7613     */
7614     if (xmlStrEqual(attrValue, BAD_CAST "xmlns")) {
7615 	xmlSchemaPSimpleTypeErr(pctxt,
7616 	    XML_SCHEMAP_NO_XMLNS,
7617 	    NULL, (xmlNodePtr) attr,
7618 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7619 	    "The value of the attribute must not match 'xmlns'",
7620 	    NULL, NULL);
7621 	return (NULL);
7622     }
7623     /*
7624     * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7625     * TODO: Move this to the component layer.
7626     *       Or better leave it here and add it to the component layer
7627     *       if we have a schema construction API.
7628     */
7629     if (xmlStrEqual(pctxt->targetNamespace, xmlSchemaInstanceNs)) {
7630 	xmlSchemaCustomErr(ACTXT_CAST pctxt,
7631 	    XML_SCHEMAP_NO_XSI, node, NULL,
7632 	    "The target namespace must not match '%s'",
7633 	    xmlSchemaInstanceNs, NULL);
7634     }
7635 
7636     ret = xmlSchemaAddAttribute(pctxt, schema, attrValue,
7637 	pctxt->targetNamespace, node, 1);
7638     if (ret == NULL)
7639 	return (NULL);
7640     ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
7641 
7642     /*
7643     * Check for illegal attributes.
7644     */
7645     attr = node->properties;
7646     while (attr != NULL) {
7647 	if (attr->ns == NULL) {
7648 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7649 		(!xmlStrEqual(attr->name, BAD_CAST "default")) &&
7650 		(!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
7651 		(!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7652 		(!xmlStrEqual(attr->name, BAD_CAST "type")))
7653 	    {
7654 		xmlSchemaPIllegalAttrErr(pctxt,
7655 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7656 	    }
7657 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7658 	    xmlSchemaPIllegalAttrErr(pctxt,
7659 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7660 	}
7661 	attr = attr->next;
7662     }
7663     xmlSchemaPValAttrQName(pctxt, schema, NULL,
7664 	node, "type", &ret->typeNs, &ret->typeName);
7665 
7666     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7667     /*
7668     * Attribute "fixed".
7669     */
7670     ret->defValue = xmlSchemaGetProp(pctxt, node, "fixed");
7671     if (ret->defValue != NULL)
7672 	ret->flags |= XML_SCHEMAS_ATTR_FIXED;
7673     /*
7674     * Attribute "default".
7675     */
7676     attr = xmlSchemaGetPropNode(node, "default");
7677     if (attr != NULL) {
7678 	/*
7679 	* 3.2.3 : 1
7680 	* default and fixed must not both be present.
7681 	*/
7682 	if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
7683 	    xmlSchemaPMutualExclAttrErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
7684 		WXS_BASIC_CAST ret, attr, "default", "fixed");
7685 	} else
7686 	    ret->defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7687     }
7688     /*
7689     * And now for the children...
7690     */
7691     child = node->children;
7692     if (IS_SCHEMA(child, "annotation")) {
7693         ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7694         child = child->next;
7695     }
7696     if (IS_SCHEMA(child, "simpleType")) {
7697 	if (ret->typeName != NULL) {
7698 	    /*
7699 	    * 3.2.3 : 4
7700 	    * type and <simpleType> must not both be present.
7701 	    */
7702 	    xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7703 		NULL, node, child,
7704 		"The attribute 'type' and the <simpleType> child "
7705 		"are mutually exclusive", NULL);
7706 	} else
7707 	    ret->subtypes = xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7708 	child = child->next;
7709     }
7710     if (child != NULL)
7711 	xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7712 	    NULL, node, child, NULL,
7713 	    "(annotation?, simpleType?)");
7714 
7715     return (ret);
7716 }
7717 
7718 /**
7719  * xmlSchemaParseAttributeGroupRef:
7720  * @ctxt:  a schema validation context
7721  * @schema:  the schema being built
7722  * @node:  a subtree containing XML Schema information
7723  *
7724  * Parse an attribute group definition reference.
7725  * Note that a reference to an attribute group does not
7726  * correspond to any component at all.
7727  * *WARNING* this interface is highly subject to change
7728  *
7729  * Returns the attribute group or NULL in case of error.
7730  */
7731 static xmlSchemaQNameRefPtr
xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)7732 xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
7733 				xmlSchemaPtr schema,
7734 				xmlNodePtr node)
7735 {
7736     xmlSchemaQNameRefPtr ret;
7737     xmlNodePtr child = NULL;
7738     xmlAttrPtr attr;
7739     const xmlChar *refNs = NULL, *ref = NULL;
7740 
7741     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7742         return (NULL);
7743 
7744     attr = xmlSchemaGetPropNode(node, "ref");
7745     if (attr == NULL) {
7746 	xmlSchemaPMissingAttrErr(pctxt,
7747 	    XML_SCHEMAP_S4S_ATTR_MISSING,
7748 	    NULL, node, "ref", NULL);
7749 	return (NULL);
7750     }
7751     xmlSchemaPValAttrNodeQName(pctxt, schema,
7752 	NULL, attr, &refNs, &ref);
7753     if (xmlSchemaCheckReference(pctxt, schema, node, attr, refNs) != 0)
7754 	return(NULL);
7755 
7756     /*
7757     * Check for illegal attributes.
7758     */
7759     attr = node->properties;
7760     while (attr != NULL) {
7761 	if (attr->ns == NULL) {
7762 	    if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
7763 		(!xmlStrEqual(attr->name, BAD_CAST "id")))
7764 	    {
7765 		xmlSchemaPIllegalAttrErr(pctxt,
7766 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7767 	    }
7768 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7769 	    xmlSchemaPIllegalAttrErr(pctxt,
7770 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7771 	}
7772 	attr = attr->next;
7773     }
7774     /* Attribute ID */
7775     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7776 
7777     /*
7778     * And now for the children...
7779     */
7780     child = node->children;
7781     if (IS_SCHEMA(child, "annotation")) {
7782 	/*
7783 	* TODO: We do not have a place to store the annotation, do we?
7784 	*/
7785         xmlSchemaParseAnnotation(pctxt, child, 0);
7786         child = child->next;
7787     }
7788     if (child != NULL) {
7789 	xmlSchemaPContentErr(pctxt,
7790 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7791 	    NULL, node, child, NULL,
7792 	    "(annotation?)");
7793     }
7794 
7795     /*
7796     * Handle attribute group redefinitions.
7797     */
7798     if (pctxt->isRedefine && pctxt->redef &&
7799 	(pctxt->redef->item->type ==
7800 	    XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
7801 	(ref == pctxt->redef->refName) &&
7802 	(refNs == pctxt->redef->refTargetNs))
7803     {
7804 	/*
7805 	* SPEC src-redefine:
7806 	* (7.1) "If it has an <attributeGroup> among its contents
7807 	* the `actual value` of whose ref [attribute] is the same
7808 	* as the `actual value` of its own name attribute plus
7809 	* target namespace, then it must have exactly one such group."
7810 	*/
7811 	if (pctxt->redefCounter != 0) {
7812 	    xmlChar *str = NULL;
7813 
7814 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
7815 		XML_SCHEMAP_SRC_REDEFINE, node, NULL,
7816 		"The redefining attribute group definition "
7817 		"'%s' must not contain more than one "
7818 		"reference to the redefined definition",
7819 		xmlSchemaFormatQName(&str, refNs, ref), NULL);
7820 	    FREE_AND_NULL(str);
7821 	    return(NULL);
7822 	}
7823 	pctxt->redefCounter++;
7824 	/*
7825 	* URGENT TODO: How to ensure that the reference will not be
7826 	* handled by the normal component resolution mechanism?
7827 	*/
7828 	ret = xmlSchemaNewQNameRef(pctxt,
7829 	    XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7830 	if (ret == NULL)
7831 	    return(NULL);
7832 	ret->node = node;
7833 	pctxt->redef->reference = WXS_BASIC_CAST ret;
7834     } else {
7835 	/*
7836 	* Create a QName-reference helper component. We will substitute this
7837 	* component for the attribute uses of the referenced attribute group
7838 	* definition.
7839 	*/
7840 	ret = xmlSchemaNewQNameRef(pctxt,
7841 	    XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7842 	if (ret == NULL)
7843 	    return(NULL);
7844 	ret->node = node;
7845 	/* Add to pending items, to be able to resolve the reference. */
7846 	WXS_ADD_PENDING(pctxt, ret);
7847     }
7848     return (ret);
7849 }
7850 
7851 /**
7852  * xmlSchemaParseAttributeGroupDefinition:
7853  * @pctxt:  a schema validation context
7854  * @schema:  the schema being built
7855  * @node:  a subtree containing XML Schema information
7856  *
7857  * parse a XML schema Attribute Group declaration
7858  * *WARNING* this interface is highly subject to change
7859  *
7860  * Returns the attribute group definition or NULL in case of error.
7861  */
7862 static xmlSchemaAttributeGroupPtr
xmlSchemaParseAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)7863 xmlSchemaParseAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
7864 				       xmlSchemaPtr schema,
7865 				       xmlNodePtr node)
7866 {
7867     const xmlChar *name;
7868     xmlSchemaAttributeGroupPtr ret;
7869     xmlNodePtr child = NULL;
7870     xmlAttrPtr attr;
7871     int hasRefs = 0;
7872 
7873     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7874         return (NULL);
7875 
7876     attr = xmlSchemaGetPropNode(node, "name");
7877     if (attr == NULL) {
7878 	xmlSchemaPMissingAttrErr(pctxt,
7879 	    XML_SCHEMAP_S4S_ATTR_MISSING,
7880 	    NULL, node, "name", NULL);
7881 	return (NULL);
7882     }
7883     /*
7884     * The name is crucial, exit if invalid.
7885     */
7886     if (xmlSchemaPValAttrNode(pctxt,
7887 	NULL, attr,
7888 	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7889 	return (NULL);
7890     }
7891     ret = xmlSchemaAddAttributeGroupDefinition(pctxt, schema,
7892 	name, pctxt->targetNamespace, node);
7893     if (ret == NULL)
7894 	return (NULL);
7895     /*
7896     * Check for illegal attributes.
7897     */
7898     attr = node->properties;
7899     while (attr != NULL) {
7900 	if (attr->ns == NULL) {
7901 	    if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7902 		(!xmlStrEqual(attr->name, BAD_CAST "id")))
7903 	    {
7904 		xmlSchemaPIllegalAttrErr(pctxt,
7905 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7906 	    }
7907 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7908 	    xmlSchemaPIllegalAttrErr(pctxt,
7909 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7910 	}
7911 	attr = attr->next;
7912     }
7913     /* Attribute ID */
7914     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7915     /*
7916     * And now for the children...
7917     */
7918     child = node->children;
7919     if (IS_SCHEMA(child, "annotation")) {
7920         ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7921         child = child->next;
7922     }
7923     /*
7924     * Parse contained attribute decls/refs.
7925     */
7926     if (xmlSchemaParseLocalAttributes(pctxt, schema, &child,
7927 	(xmlSchemaItemListPtr *) &(ret->attrUses),
7928 	XML_SCHEMA_TYPE_ATTRIBUTEGROUP, &hasRefs) == -1)
7929 	return(NULL);
7930     if (hasRefs)
7931 	ret->flags |= XML_SCHEMAS_ATTRGROUP_HAS_REFS;
7932     /*
7933     * Parse the attribute wildcard.
7934     */
7935     if (IS_SCHEMA(child, "anyAttribute")) {
7936 	ret->attributeWildcard = xmlSchemaParseAnyAttribute(pctxt,
7937 	    schema, child);
7938 	child = child->next;
7939     }
7940     if (child != NULL) {
7941 	xmlSchemaPContentErr(pctxt,
7942 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7943 	    NULL, node, child, NULL,
7944 	    "(annotation?, ((attribute | attributeGroup)*, anyAttribute?))");
7945     }
7946     return (ret);
7947 }
7948 
7949 /**
7950  * xmlSchemaPValAttrFormDefault:
7951  * @value:  the value
7952  * @flags: the flags to be modified
7953  * @flagQualified: the specific flag for "qualified"
7954  *
7955  * Returns 0 if the value is valid, 1 otherwise.
7956  */
7957 static int
xmlSchemaPValAttrFormDefault(const xmlChar * value,int * flags,int flagQualified)7958 xmlSchemaPValAttrFormDefault(const xmlChar *value,
7959 			     int *flags,
7960 			     int flagQualified)
7961 {
7962     if (xmlStrEqual(value, BAD_CAST "qualified")) {
7963 	if  ((*flags & flagQualified) == 0)
7964 	    *flags |= flagQualified;
7965     } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
7966 	return (1);
7967 
7968     return (0);
7969 }
7970 
7971 /**
7972  * xmlSchemaPValAttrBlockFinal:
7973  * @value:  the value
7974  * @flags: the flags to be modified
7975  * @flagAll: the specific flag for "#all"
7976  * @flagExtension: the specific flag for "extension"
7977  * @flagRestriction: the specific flag for "restriction"
7978  * @flagSubstitution: the specific flag for "substitution"
7979  * @flagList: the specific flag for "list"
7980  * @flagUnion: the specific flag for "union"
7981  *
7982  * Validates the value of the attribute "final" and "block". The value
7983  * is converted into the specified flag values and returned in @flags.
7984  *
7985  * Returns 0 if the value is valid, 1 otherwise.
7986  */
7987 
7988 static int
xmlSchemaPValAttrBlockFinal(const xmlChar * value,int * flags,int flagAll,int flagExtension,int flagRestriction,int flagSubstitution,int flagList,int flagUnion)7989 xmlSchemaPValAttrBlockFinal(const xmlChar *value,
7990 			    int *flags,
7991 			    int flagAll,
7992 			    int flagExtension,
7993 			    int flagRestriction,
7994 			    int flagSubstitution,
7995 			    int flagList,
7996 			    int flagUnion)
7997 {
7998     int ret = 0;
7999 
8000     /*
8001     * TODO: This does not check for duplicate entries.
8002     */
8003     if ((flags == NULL) || (value == NULL))
8004 	return (-1);
8005     if (value[0] == 0)
8006 	return (0);
8007     if (xmlStrEqual(value, BAD_CAST "#all")) {
8008 	if (flagAll != -1)
8009 	    *flags |= flagAll;
8010 	else {
8011 	    if (flagExtension != -1)
8012 		*flags |= flagExtension;
8013 	    if (flagRestriction != -1)
8014 		*flags |= flagRestriction;
8015 	    if (flagSubstitution != -1)
8016 		*flags |= flagSubstitution;
8017 	    if (flagList != -1)
8018 		*flags |= flagList;
8019 	    if (flagUnion != -1)
8020 		*flags |= flagUnion;
8021 	}
8022     } else {
8023 	const xmlChar *end, *cur = value;
8024 	xmlChar *item;
8025 
8026 	do {
8027 	    while (IS_BLANK_CH(*cur))
8028 		cur++;
8029 	    end = cur;
8030 	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
8031 		end++;
8032 	    if (end == cur)
8033 		break;
8034 	    item = xmlStrndup(cur, end - cur);
8035 	    if (xmlStrEqual(item, BAD_CAST "extension")) {
8036 		if (flagExtension != -1) {
8037 		    if ((*flags & flagExtension) == 0)
8038 			*flags |= flagExtension;
8039 		} else
8040 		    ret = 1;
8041 	    } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
8042 		if (flagRestriction != -1) {
8043 		    if ((*flags & flagRestriction) == 0)
8044 			*flags |= flagRestriction;
8045 		} else
8046 		    ret = 1;
8047 	    } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
8048 		if (flagSubstitution != -1) {
8049 		    if ((*flags & flagSubstitution) == 0)
8050 			*flags |= flagSubstitution;
8051 		} else
8052 		    ret = 1;
8053 	    } else if (xmlStrEqual(item, BAD_CAST "list")) {
8054 		if (flagList != -1) {
8055 		    if ((*flags & flagList) == 0)
8056 			*flags |= flagList;
8057 		} else
8058 		    ret = 1;
8059 	    } else if (xmlStrEqual(item, BAD_CAST "union")) {
8060 		if (flagUnion != -1) {
8061 		    if ((*flags & flagUnion) == 0)
8062 			*flags |= flagUnion;
8063 		} else
8064 		    ret = 1;
8065 	    } else
8066 		ret = 1;
8067 	    if (item != NULL)
8068 		xmlFree(item);
8069 	    cur = end;
8070 	} while ((ret == 0) && (*cur != 0));
8071     }
8072 
8073     return (ret);
8074 }
8075 
8076 static int
xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,xmlSchemaIDCPtr idc,xmlSchemaIDCSelectPtr selector,xmlAttrPtr attr,int isField)8077 xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
8078 			     xmlSchemaIDCPtr idc,
8079 			     xmlSchemaIDCSelectPtr selector,
8080 			     xmlAttrPtr attr,
8081 			     int isField)
8082 {
8083     xmlNodePtr node;
8084 
8085     /*
8086     * c-selector-xpath:
8087     * Schema Component Constraint: Selector Value OK
8088     *
8089     * TODO: 1 The {selector} must be a valid XPath expression, as defined
8090     * in [XPath].
8091     */
8092     if (selector == NULL) {
8093 	xmlSchemaPErr(ctxt, idc->node,
8094 	    XML_SCHEMAP_INTERNAL,
8095 	    "Internal error: xmlSchemaCheckCSelectorXPath, "
8096 	    "the selector is not specified.\n", NULL, NULL);
8097 	return (-1);
8098     }
8099     if (attr == NULL)
8100 	node = idc->node;
8101     else
8102 	node = (xmlNodePtr) attr;
8103     if (selector->xpath == NULL) {
8104 	xmlSchemaPCustomErr(ctxt,
8105 	    /* TODO: Adjust error code. */
8106 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8107 	    NULL, node,
8108 	    "The XPath expression of the selector is not valid", NULL);
8109 	return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
8110     } else {
8111 	const xmlChar **nsArray = NULL;
8112 	xmlNsPtr *nsList = NULL;
8113 	/*
8114 	* Compile the XPath expression.
8115 	*/
8116 	/*
8117 	* TODO: We need the array of in-scope namespaces for compilation.
8118 	* TODO: Call xmlPatterncompile with different options for selector/
8119 	* field.
8120 	*/
8121 	if (attr == NULL)
8122 	    nsList = NULL;
8123 	else
8124 	    nsList = xmlGetNsList(attr->doc, attr->parent);
8125 	/*
8126 	* Build an array of prefixes and namespaces.
8127 	*/
8128 	if (nsList != NULL) {
8129 	    int i, count = 0;
8130 
8131 	    for (i = 0; nsList[i] != NULL; i++)
8132 		count++;
8133 
8134 	    nsArray = (const xmlChar **) xmlMalloc(
8135 		(count * 2 + 1) * sizeof(const xmlChar *));
8136 	    if (nsArray == NULL) {
8137 		xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
8138 		    NULL);
8139 		xmlFree(nsList);
8140 		return (-1);
8141 	    }
8142 	    for (i = 0; i < count; i++) {
8143 		nsArray[2 * i] = nsList[i]->href;
8144 		nsArray[2 * i + 1] = nsList[i]->prefix;
8145 	    }
8146 	    nsArray[count * 2] = NULL;
8147 	    xmlFree(nsList);
8148 	}
8149 	/*
8150 	* TODO: Differentiate between "selector" and "field".
8151 	*/
8152 	if (isField)
8153 	    selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
8154 		NULL, XML_PATTERN_XSFIELD, nsArray);
8155 	else
8156 	    selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
8157 		NULL, XML_PATTERN_XSSEL, nsArray);
8158 	if (nsArray != NULL)
8159 	    xmlFree((xmlChar **) nsArray);
8160 
8161 	if (selector->xpathComp == NULL) {
8162 	    xmlSchemaPCustomErr(ctxt,
8163 		/* TODO: Adjust error code? */
8164 		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8165 		NULL, node,
8166 		"The XPath expression '%s' could not be "
8167 		"compiled", selector->xpath);
8168 	    return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
8169 	}
8170     }
8171     return (0);
8172 }
8173 
8174 #define ADD_ANNOTATION(annot)   \
8175     xmlSchemaAnnotPtr cur = item->annot; \
8176     if (item->annot == NULL) {  \
8177 	item->annot = annot;    \
8178 	return (annot);         \
8179     }                           \
8180     cur = item->annot;          \
8181     if (cur->next != NULL) {    \
8182 	cur = cur->next;	\
8183     }                           \
8184     cur->next = annot;
8185 
8186 /**
8187  * xmlSchemaAssignAnnotation:
8188  * @item: the schema component
8189  * @annot: the annotation
8190  *
8191  * Adds the annotation to the given schema component.
8192  *
8193  * Returns the given annotation.
8194  */
8195 static xmlSchemaAnnotPtr
xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,xmlSchemaAnnotPtr annot)8196 xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
8197 		       xmlSchemaAnnotPtr annot)
8198 {
8199     if ((annItem == NULL) || (annot == NULL))
8200 	return (NULL);
8201     switch (annItem->type) {
8202 	case XML_SCHEMA_TYPE_ELEMENT: {
8203 		xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
8204 		ADD_ANNOTATION(annot)
8205 	    }
8206 	    break;
8207 	case XML_SCHEMA_TYPE_ATTRIBUTE: {
8208 		xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
8209 		ADD_ANNOTATION(annot)
8210 	    }
8211 	    break;
8212 	case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
8213 	case XML_SCHEMA_TYPE_ANY: {
8214 		xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
8215 		ADD_ANNOTATION(annot)
8216 	    }
8217 	    break;
8218 	case XML_SCHEMA_TYPE_PARTICLE:
8219 	case XML_SCHEMA_TYPE_IDC_KEY:
8220 	case XML_SCHEMA_TYPE_IDC_KEYREF:
8221 	case XML_SCHEMA_TYPE_IDC_UNIQUE: {
8222 		xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
8223 		ADD_ANNOTATION(annot)
8224 	    }
8225 	    break;
8226 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
8227 		xmlSchemaAttributeGroupPtr item =
8228 		    (xmlSchemaAttributeGroupPtr) annItem;
8229 		ADD_ANNOTATION(annot)
8230 	    }
8231 	    break;
8232 	case XML_SCHEMA_TYPE_NOTATION: {
8233 		xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
8234 		ADD_ANNOTATION(annot)
8235 	    }
8236 	    break;
8237 	case XML_SCHEMA_FACET_MININCLUSIVE:
8238 	case XML_SCHEMA_FACET_MINEXCLUSIVE:
8239 	case XML_SCHEMA_FACET_MAXINCLUSIVE:
8240 	case XML_SCHEMA_FACET_MAXEXCLUSIVE:
8241 	case XML_SCHEMA_FACET_TOTALDIGITS:
8242 	case XML_SCHEMA_FACET_FRACTIONDIGITS:
8243 	case XML_SCHEMA_FACET_PATTERN:
8244 	case XML_SCHEMA_FACET_ENUMERATION:
8245 	case XML_SCHEMA_FACET_WHITESPACE:
8246 	case XML_SCHEMA_FACET_LENGTH:
8247 	case XML_SCHEMA_FACET_MAXLENGTH:
8248 	case XML_SCHEMA_FACET_MINLENGTH: {
8249 		xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
8250 		ADD_ANNOTATION(annot)
8251 	    }
8252 	    break;
8253 	case XML_SCHEMA_TYPE_SIMPLE:
8254 	case XML_SCHEMA_TYPE_COMPLEX: {
8255 		xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
8256 		ADD_ANNOTATION(annot)
8257 	    }
8258 	    break;
8259 	case XML_SCHEMA_TYPE_GROUP: {
8260 		xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
8261 		ADD_ANNOTATION(annot)
8262 	    }
8263 	    break;
8264 	case XML_SCHEMA_TYPE_SEQUENCE:
8265 	case XML_SCHEMA_TYPE_CHOICE:
8266 	case XML_SCHEMA_TYPE_ALL: {
8267 		xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
8268 		ADD_ANNOTATION(annot)
8269 	    }
8270 	    break;
8271 	default:
8272 	     xmlSchemaPCustomErr(NULL,
8273 		XML_SCHEMAP_INTERNAL,
8274 		NULL, NULL,
8275 		"Internal error: xmlSchemaAddAnnotation, "
8276 		"The item is not a annotated schema component", NULL);
8277 	     break;
8278     }
8279     return (annot);
8280 }
8281 
8282 /**
8283  * xmlSchemaParseIDCSelectorAndField:
8284  * @ctxt:  a schema validation context
8285  * @schema:  the schema being built
8286  * @node:  a subtree containing XML Schema information
8287  *
8288  * Parses a XML Schema identity-constraint definition's
8289  * <selector> and <field> elements.
8290  *
8291  * Returns the parsed identity-constraint definition.
8292  */
8293 static xmlSchemaIDCSelectPtr
xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,xmlSchemaIDCPtr idc,xmlNodePtr node,int isField)8294 xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
8295 			  xmlSchemaIDCPtr idc,
8296 			  xmlNodePtr node,
8297 			  int isField)
8298 {
8299     xmlSchemaIDCSelectPtr item;
8300     xmlNodePtr child = NULL;
8301     xmlAttrPtr attr;
8302 
8303     /*
8304     * Check for illegal attributes.
8305     */
8306     attr = node->properties;
8307     while (attr != NULL) {
8308 	if (attr->ns == NULL) {
8309 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8310 		(!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
8311 		xmlSchemaPIllegalAttrErr(ctxt,
8312 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8313 	    }
8314 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8315 	    xmlSchemaPIllegalAttrErr(ctxt,
8316 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8317 	}
8318 	attr = attr->next;
8319     }
8320     /*
8321     * Create the item.
8322     */
8323     item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
8324     if (item == NULL) {
8325         xmlSchemaPErrMemory(ctxt,
8326 	    "allocating a 'selector' of an identity-constraint definition",
8327 	    NULL);
8328         return (NULL);
8329     }
8330     memset(item, 0, sizeof(xmlSchemaIDCSelect));
8331     /*
8332     * Attribute "xpath" (mandatory).
8333     */
8334     attr = xmlSchemaGetPropNode(node, "xpath");
8335     if (attr == NULL) {
8336 	xmlSchemaPMissingAttrErr(ctxt,
8337 	    XML_SCHEMAP_S4S_ATTR_MISSING,
8338 	    NULL, node,
8339 	    "name", NULL);
8340     } else {
8341 	item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8342 	/*
8343 	* URGENT TODO: "field"s have an other syntax than "selector"s.
8344 	*/
8345 
8346 	if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
8347 	    isField) == -1) {
8348 	    xmlSchemaPErr(ctxt,
8349 		(xmlNodePtr) attr,
8350 		XML_SCHEMAP_INTERNAL,
8351 		"Internal error: xmlSchemaParseIDCSelectorAndField, "
8352 		"validating the XPath expression of a IDC selector.\n",
8353 		NULL, NULL);
8354 	}
8355 
8356     }
8357     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8358     /*
8359     * And now for the children...
8360     */
8361     child = node->children;
8362     if (IS_SCHEMA(child, "annotation")) {
8363 	/*
8364 	* Add the annotation to the parent IDC.
8365 	*/
8366 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
8367 	    xmlSchemaParseAnnotation(ctxt, child, 1));
8368 	child = child->next;
8369     }
8370     if (child != NULL) {
8371 	xmlSchemaPContentErr(ctxt,
8372 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8373 	    NULL, node, child,
8374 	    NULL, "(annotation?)");
8375     }
8376 
8377     return (item);
8378 }
8379 
8380 /**
8381  * xmlSchemaParseIDC:
8382  * @ctxt:  a schema validation context
8383  * @schema:  the schema being built
8384  * @node:  a subtree containing XML Schema information
8385  *
8386  * Parses a XML Schema identity-constraint definition.
8387  *
8388  * Returns the parsed identity-constraint definition.
8389  */
8390 static xmlSchemaIDCPtr
xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlSchemaTypeType idcCategory,const xmlChar * targetNamespace)8391 xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
8392 		  xmlSchemaPtr schema,
8393 		  xmlNodePtr node,
8394 		  xmlSchemaTypeType idcCategory,
8395 		  const xmlChar *targetNamespace)
8396 {
8397     xmlSchemaIDCPtr item = NULL;
8398     xmlNodePtr child = NULL;
8399     xmlAttrPtr attr;
8400     const xmlChar *name = NULL;
8401     xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
8402 
8403     /*
8404     * Check for illegal attributes.
8405     */
8406     attr = node->properties;
8407     while (attr != NULL) {
8408 	if (attr->ns == NULL) {
8409 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8410 		(!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8411 		((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
8412 		 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
8413 		xmlSchemaPIllegalAttrErr(ctxt,
8414 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8415 	    }
8416 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8417 	    xmlSchemaPIllegalAttrErr(ctxt,
8418 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8419 	}
8420 	attr = attr->next;
8421     }
8422     /*
8423     * Attribute "name" (mandatory).
8424     */
8425     attr = xmlSchemaGetPropNode(node, "name");
8426     if (attr == NULL) {
8427 	xmlSchemaPMissingAttrErr(ctxt,
8428 	    XML_SCHEMAP_S4S_ATTR_MISSING,
8429 	    NULL, node,
8430 	    "name", NULL);
8431 	return (NULL);
8432     } else if (xmlSchemaPValAttrNode(ctxt,
8433 	NULL, attr,
8434 	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8435 	return (NULL);
8436     }
8437     /* Create the component. */
8438     item = xmlSchemaAddIDC(ctxt, schema, name, targetNamespace,
8439 	idcCategory, node);
8440     if (item == NULL)
8441 	return(NULL);
8442 
8443     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8444     if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
8445 	/*
8446 	* Attribute "refer" (mandatory).
8447 	*/
8448 	attr = xmlSchemaGetPropNode(node, "refer");
8449 	if (attr == NULL) {
8450 	    xmlSchemaPMissingAttrErr(ctxt,
8451 		XML_SCHEMAP_S4S_ATTR_MISSING,
8452 		NULL, node,
8453 		"refer", NULL);
8454 	} else {
8455 	    /*
8456 	    * Create a reference item.
8457 	    */
8458 	    item->ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_IDC_KEY,
8459 		NULL, NULL);
8460 	    if (item->ref == NULL)
8461 		return (NULL);
8462 	    xmlSchemaPValAttrNodeQName(ctxt, schema,
8463 		NULL, attr,
8464 		&(item->ref->targetNamespace),
8465 		&(item->ref->name));
8466 	    xmlSchemaCheckReference(ctxt, schema, node, attr,
8467 		item->ref->targetNamespace);
8468 	}
8469     }
8470     /*
8471     * And now for the children...
8472     */
8473     child = node->children;
8474     if (IS_SCHEMA(child, "annotation")) {
8475 	item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
8476 	child = child->next;
8477     }
8478     if (child == NULL) {
8479 	xmlSchemaPContentErr(ctxt,
8480 		XML_SCHEMAP_S4S_ELEM_MISSING,
8481 		NULL, node, child,
8482 		"A child element is missing",
8483 		"(annotation?, (selector, field+))");
8484     }
8485     /*
8486     * Child element <selector>.
8487     */
8488     if (IS_SCHEMA(child, "selector")) {
8489 	item->selector = xmlSchemaParseIDCSelectorAndField(ctxt,
8490 	    item, child, 0);
8491 	child = child->next;
8492 	/*
8493 	* Child elements <field>.
8494 	*/
8495 	if (IS_SCHEMA(child, "field")) {
8496 	    do {
8497 		field = xmlSchemaParseIDCSelectorAndField(ctxt,
8498 		    item, child, 1);
8499 		if (field != NULL) {
8500 		    field->index = item->nbFields;
8501 		    item->nbFields++;
8502 		    if (lastField != NULL)
8503 			lastField->next = field;
8504 		    else
8505 			item->fields = field;
8506 		    lastField = field;
8507 		}
8508 		child = child->next;
8509 	    } while (IS_SCHEMA(child, "field"));
8510 	} else {
8511 	    xmlSchemaPContentErr(ctxt,
8512 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8513 		NULL, node, child,
8514 		NULL, "(annotation?, (selector, field+))");
8515 	}
8516     }
8517     if (child != NULL) {
8518 	xmlSchemaPContentErr(ctxt,
8519 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8520 	    NULL, node, child,
8521 	    NULL, "(annotation?, (selector, field+))");
8522     }
8523 
8524     return (item);
8525 }
8526 
8527 /**
8528  * xmlSchemaParseElement:
8529  * @ctxt:  a schema validation context
8530  * @schema:  the schema being built
8531  * @node:  a subtree containing XML Schema information
8532  * @topLevel: indicates if this is global declaration
8533  *
8534  * Parses a XML schema element declaration.
8535  * *WARNING* this interface is highly subject to change
8536  *
8537  * Returns the element declaration or a particle; NULL in case
8538  * of an error or if the particle has minOccurs==maxOccurs==0.
8539  */
8540 static xmlSchemaBasicItemPtr
xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int * isElemRef,int topLevel)8541 xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8542                       xmlNodePtr node, int *isElemRef, int topLevel)
8543 {
8544     xmlSchemaElementPtr decl = NULL;
8545     xmlSchemaParticlePtr particle = NULL;
8546     xmlSchemaAnnotPtr annot = NULL;
8547     xmlNodePtr child = NULL;
8548     xmlAttrPtr attr, nameAttr;
8549     int min, max, isRef = 0;
8550     xmlChar *des = NULL;
8551 
8552     /* 3.3.3 Constraints on XML Representations of Element Declarations */
8553     /* TODO: Complete implementation of 3.3.6 */
8554 
8555     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8556         return (NULL);
8557 
8558     if (isElemRef != NULL)
8559 	*isElemRef = 0;
8560     /*
8561     * If we get a "ref" attribute on a local <element> we will assume it's
8562     * a reference - even if there's a "name" attribute; this seems to be more
8563     * robust.
8564     */
8565     nameAttr = xmlSchemaGetPropNode(node, "name");
8566     attr = xmlSchemaGetPropNode(node, "ref");
8567     if ((topLevel) || (attr == NULL)) {
8568 	if (nameAttr == NULL) {
8569 	    xmlSchemaPMissingAttrErr(ctxt,
8570 		XML_SCHEMAP_S4S_ATTR_MISSING,
8571 		NULL, node, "name", NULL);
8572 	    return (NULL);
8573 	}
8574     } else
8575 	isRef = 1;
8576 
8577     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8578     child = node->children;
8579     if (IS_SCHEMA(child, "annotation")) {
8580 	annot = xmlSchemaParseAnnotation(ctxt, child, 1);
8581 	child = child->next;
8582     }
8583     /*
8584     * Skip particle part if a global declaration.
8585     */
8586     if (topLevel)
8587 	goto declaration_part;
8588     /*
8589     * The particle part ==================================================
8590     */
8591     min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
8592     max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
8593     xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
8594     particle = xmlSchemaAddParticle(ctxt, node, min, max);
8595     if (particle == NULL)
8596 	goto return_null;
8597 
8598     /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
8599 
8600     if (isRef) {
8601 	const xmlChar *refNs = NULL, *ref = NULL;
8602 	xmlSchemaQNameRefPtr refer = NULL;
8603 	/*
8604 	* The reference part =============================================
8605 	*/
8606 	if (isElemRef != NULL)
8607 	    *isElemRef = 1;
8608 
8609 	xmlSchemaPValAttrNodeQName(ctxt, schema,
8610 	    NULL, attr, &refNs, &ref);
8611 	xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
8612 	/*
8613 	* SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
8614 	*/
8615 	if (nameAttr != NULL) {
8616 	    xmlSchemaPMutualExclAttrErr(ctxt,
8617 		XML_SCHEMAP_SRC_ELEMENT_2_1, NULL, nameAttr, "ref", "name");
8618 	}
8619 	/*
8620 	* Check for illegal attributes.
8621 	*/
8622 	attr = node->properties;
8623 	while (attr != NULL) {
8624 	    if (attr->ns == NULL) {
8625 		if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
8626 		    xmlStrEqual(attr->name, BAD_CAST "name") ||
8627 		    xmlStrEqual(attr->name, BAD_CAST "id") ||
8628 		    xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
8629 		    xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
8630 		{
8631 		    attr = attr->next;
8632 		    continue;
8633 		} else {
8634 		    /* SPEC (3.3.3 : 2.2) */
8635 		    xmlSchemaPCustomAttrErr(ctxt,
8636 			XML_SCHEMAP_SRC_ELEMENT_2_2,
8637 			NULL, NULL, attr,
8638 			"Only the attributes 'minOccurs', 'maxOccurs' and "
8639 			"'id' are allowed in addition to 'ref'");
8640 		    break;
8641 		}
8642 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8643 		xmlSchemaPIllegalAttrErr(ctxt,
8644 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8645 	    }
8646 	    attr = attr->next;
8647 	}
8648 	/*
8649 	* No children except <annotation> expected.
8650 	*/
8651 	if (child != NULL) {
8652 	    xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8653 		NULL, node, child, NULL, "(annotation?)");
8654 	}
8655 	if ((min == 0) && (max == 0))
8656 	    goto return_null;
8657 	/*
8658 	* Create the reference item and attach it to the particle.
8659 	*/
8660 	refer = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_ELEMENT,
8661 	    ref, refNs);
8662 	if (refer == NULL)
8663 	    goto return_null;
8664 	particle->children = (xmlSchemaTreeItemPtr) refer;
8665 	particle->annot = annot;
8666 	/*
8667 	* Add the particle to pending components, since the reference
8668 	* need to be resolved.
8669 	*/
8670 	WXS_ADD_PENDING(ctxt, particle);
8671 	return ((xmlSchemaBasicItemPtr) particle);
8672     }
8673     /*
8674     * The declaration part ===============================================
8675     */
8676 declaration_part:
8677     {
8678 	const xmlChar *ns = NULL, *fixed, *name, *attrValue;
8679 	xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
8680 
8681 	if (xmlSchemaPValAttrNode(ctxt, NULL, nameAttr,
8682 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
8683 	    goto return_null;
8684 	/*
8685 	* Evaluate the target namespace.
8686 	*/
8687 	if (topLevel) {
8688 	    ns = ctxt->targetNamespace;
8689 	} else {
8690 	    attr = xmlSchemaGetPropNode(node, "form");
8691 	    if (attr != NULL) {
8692 		attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8693 		if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
8694 		    ns = ctxt->targetNamespace;
8695 		} else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
8696 		    xmlSchemaPSimpleTypeErr(ctxt,
8697 			XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8698 			NULL, (xmlNodePtr) attr,
8699 			NULL, "(qualified | unqualified)",
8700 			attrValue, NULL, NULL, NULL);
8701 		}
8702 	    } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
8703 		ns = ctxt->targetNamespace;
8704 	}
8705 	decl = xmlSchemaAddElement(ctxt, name, ns, node, topLevel);
8706 	if (decl == NULL) {
8707 	    goto return_null;
8708 	}
8709 	/*
8710 	* Check for illegal attributes.
8711 	*/
8712 	attr = node->properties;
8713 	while (attr != NULL) {
8714 	    if (attr->ns == NULL) {
8715 		if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8716 		    (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
8717 		    (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8718 		    (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
8719 		    (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
8720 		    (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
8721 		    (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
8722 		{
8723 		    if (topLevel == 0) {
8724 			if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8725 			    (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
8726 			    (!xmlStrEqual(attr->name, BAD_CAST "form")))
8727 			{
8728 			    xmlSchemaPIllegalAttrErr(ctxt,
8729 				XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8730 			}
8731 		    } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
8732 			(!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
8733 			(!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
8734 
8735 			xmlSchemaPIllegalAttrErr(ctxt,
8736 			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8737 		    }
8738 		}
8739 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8740 
8741 		xmlSchemaPIllegalAttrErr(ctxt,
8742 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8743 	    }
8744 	    attr = attr->next;
8745 	}
8746 	/*
8747 	* Extract/validate attributes.
8748 	*/
8749 	if (topLevel) {
8750 	    /*
8751 	    * Process top attributes of global element declarations here.
8752 	    */
8753 	    decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
8754 	    decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
8755 	    xmlSchemaPValAttrQName(ctxt, schema,
8756 		NULL, node, "substitutionGroup",
8757 		&(decl->substGroupNs), &(decl->substGroup));
8758 	    if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
8759 		decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
8760 	    /*
8761 	    * Attribute "final".
8762 	    */
8763 	    attr = xmlSchemaGetPropNode(node, "final");
8764 	    if (attr == NULL) {
8765 		if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8766 		    decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
8767 		if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8768 		    decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
8769 	    } else {
8770 		attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8771 		if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
8772 		    -1,
8773 		    XML_SCHEMAS_ELEM_FINAL_EXTENSION,
8774 		    XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
8775 		    xmlSchemaPSimpleTypeErr(ctxt,
8776 			XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8777 			NULL, (xmlNodePtr) attr,
8778 			NULL, "(#all | List of (extension | restriction))",
8779 			attrValue, NULL, NULL, NULL);
8780 		}
8781 	    }
8782 	}
8783 	/*
8784 	* Attribute "block".
8785 	*/
8786 	attr = xmlSchemaGetPropNode(node, "block");
8787 	if (attr == NULL) {
8788 	    /*
8789 	    * Apply default "block" values.
8790 	    */
8791 	    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8792 		decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
8793 	    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8794 		decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
8795 	    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8796 		decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
8797 	} else {
8798 	    attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8799 	    if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
8800 		-1,
8801 		XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
8802 		XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
8803 		XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
8804 		xmlSchemaPSimpleTypeErr(ctxt,
8805 		    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8806 		    NULL, (xmlNodePtr) attr,
8807 		    NULL, "(#all | List of (extension | "
8808 		    "restriction | substitution))", attrValue,
8809 		    NULL, NULL, NULL);
8810 	    }
8811 	}
8812 	if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
8813 	    decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
8814 
8815 	attr = xmlSchemaGetPropNode(node, "type");
8816 	if (attr != NULL) {
8817 	    xmlSchemaPValAttrNodeQName(ctxt, schema,
8818 		NULL, attr,
8819 		&(decl->namedTypeNs), &(decl->namedType));
8820 	    xmlSchemaCheckReference(ctxt, schema, node,
8821 		attr, decl->namedTypeNs);
8822 	}
8823 	decl->value = xmlSchemaGetProp(ctxt, node, "default");
8824 	attr = xmlSchemaGetPropNode(node, "fixed");
8825 	if (attr != NULL) {
8826 	    fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8827 	    if (decl->value != NULL) {
8828 		/*
8829 		* 3.3.3 : 1
8830 		* default and fixed must not both be present.
8831 		*/
8832 		xmlSchemaPMutualExclAttrErr(ctxt,
8833 		    XML_SCHEMAP_SRC_ELEMENT_1,
8834 		    NULL, attr, "default", "fixed");
8835 	    } else {
8836 		decl->flags |= XML_SCHEMAS_ELEM_FIXED;
8837 		decl->value = fixed;
8838 	    }
8839 	}
8840 	/*
8841 	* And now for the children...
8842 	*/
8843 	if (IS_SCHEMA(child, "complexType")) {
8844 	    /*
8845 	    * 3.3.3 : 3
8846 	    * "type" and either <simpleType> or <complexType> are mutually
8847 	    * exclusive
8848 	    */
8849 	    if (decl->namedType != NULL) {
8850 		xmlSchemaPContentErr(ctxt,
8851 		    XML_SCHEMAP_SRC_ELEMENT_3,
8852 		    NULL, node, child,
8853 		    "The attribute 'type' and the <complexType> child are "
8854 		    "mutually exclusive", NULL);
8855 	    } else
8856 		WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
8857 	    child = child->next;
8858 	} else if (IS_SCHEMA(child, "simpleType")) {
8859 	    /*
8860 	    * 3.3.3 : 3
8861 	    * "type" and either <simpleType> or <complexType> are
8862 	    * mutually exclusive
8863 	    */
8864 	    if (decl->namedType != NULL) {
8865 		xmlSchemaPContentErr(ctxt,
8866 		    XML_SCHEMAP_SRC_ELEMENT_3,
8867 		    NULL, node, child,
8868 		    "The attribute 'type' and the <simpleType> child are "
8869 		    "mutually exclusive", NULL);
8870 	    } else
8871 		WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8872 	    child = child->next;
8873 	}
8874 	while ((IS_SCHEMA(child, "unique")) ||
8875 	    (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
8876 	    if (IS_SCHEMA(child, "unique")) {
8877 		curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8878 		    XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
8879 	    } else if (IS_SCHEMA(child, "key")) {
8880 		curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8881 		    XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
8882 	    } else if (IS_SCHEMA(child, "keyref")) {
8883 		curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8884 		    XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
8885 	    }
8886 	    if (lastIDC != NULL)
8887 		lastIDC->next = curIDC;
8888 	    else
8889 		decl->idcs = (void *) curIDC;
8890 	    lastIDC = curIDC;
8891 	    child = child->next;
8892 	}
8893 	if (child != NULL) {
8894 	    xmlSchemaPContentErr(ctxt,
8895 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8896 		NULL, node, child,
8897 		NULL, "(annotation?, ((simpleType | complexType)?, "
8898 		"(unique | key | keyref)*))");
8899 	}
8900 	decl->annot = annot;
8901     }
8902     /*
8903     * NOTE: Element Declaration Representation OK 4. will be checked at a
8904     * different layer.
8905     */
8906     FREE_AND_NULL(des)
8907     if (topLevel)
8908 	return ((xmlSchemaBasicItemPtr) decl);
8909     else {
8910 	particle->children = (xmlSchemaTreeItemPtr) decl;
8911 	return ((xmlSchemaBasicItemPtr) particle);
8912     }
8913 
8914 return_null:
8915     FREE_AND_NULL(des);
8916     if (annot != NULL) {
8917 	if (particle != NULL)
8918 	    particle->annot = NULL;
8919 	if (decl != NULL)
8920 	    decl->annot = NULL;
8921 	xmlSchemaFreeAnnot(annot);
8922     }
8923     return (NULL);
8924 }
8925 
8926 /**
8927  * xmlSchemaParseUnion:
8928  * @ctxt:  a schema validation context
8929  * @schema:  the schema being built
8930  * @node:  a subtree containing XML Schema information
8931  *
8932  * parse a XML schema Union definition
8933  * *WARNING* this interface is highly subject to change
8934  *
8935  * Returns -1 in case of internal error, 0 in case of success and a positive
8936  * error code otherwise.
8937  */
8938 static int
xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)8939 xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8940                     xmlNodePtr node)
8941 {
8942     xmlSchemaTypePtr type;
8943     xmlNodePtr child = NULL;
8944     xmlAttrPtr attr;
8945     const xmlChar *cur = NULL;
8946 
8947     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8948         return (-1);
8949     /* Not a component, don't create it. */
8950     type = ctxt->ctxtType;
8951     /*
8952     * Mark the simple type as being of variety "union".
8953     */
8954     type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
8955     /*
8956     * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
8957     * then the `simple ur-type definition`."
8958     */
8959     type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
8960     /*
8961     * Check for illegal attributes.
8962     */
8963     attr = node->properties;
8964     while (attr != NULL) {
8965 	if (attr->ns == NULL) {
8966 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8967 		(!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
8968 		xmlSchemaPIllegalAttrErr(ctxt,
8969 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8970 	    }
8971 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8972 	    xmlSchemaPIllegalAttrErr(ctxt,
8973 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8974 	}
8975 	attr = attr->next;
8976     }
8977     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8978     /*
8979     * Attribute "memberTypes". This is a list of QNames.
8980     * TODO: Check the value to contain anything.
8981     */
8982     attr = xmlSchemaGetPropNode(node, "memberTypes");
8983     if (attr != NULL) {
8984 	const xmlChar *end;
8985 	xmlChar *tmp;
8986 	const xmlChar *localName, *nsName;
8987 	xmlSchemaTypeLinkPtr link, lastLink = NULL;
8988 	xmlSchemaQNameRefPtr ref;
8989 
8990 	cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8991 	type->base = cur;
8992 	do {
8993 	    while (IS_BLANK_CH(*cur))
8994 		cur++;
8995 	    end = cur;
8996 	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
8997 		end++;
8998 	    if (end == cur)
8999 		break;
9000 	    tmp = xmlStrndup(cur, end - cur);
9001 	    if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
9002 		NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
9003 		/*
9004 		* Create the member type link.
9005 		*/
9006 		link = (xmlSchemaTypeLinkPtr)
9007 		    xmlMalloc(sizeof(xmlSchemaTypeLink));
9008 		if (link == NULL) {
9009 		    xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
9010 			"allocating a type link", NULL);
9011 		    return (-1);
9012 		}
9013 		link->type = NULL;
9014 		link->next = NULL;
9015 		if (lastLink == NULL)
9016 		    type->memberTypes = link;
9017 		else
9018 		    lastLink->next = link;
9019 		lastLink = link;
9020 		/*
9021 		* Create a reference item.
9022 		*/
9023 		ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_SIMPLE,
9024 		    localName, nsName);
9025 		if (ref == NULL) {
9026 		    FREE_AND_NULL(tmp)
9027 		    return (-1);
9028 		}
9029 		/*
9030 		* Assign the reference to the link, it will be resolved
9031 		* later during fixup of the union simple type.
9032 		*/
9033 		link->type = (xmlSchemaTypePtr) ref;
9034 	    }
9035 	    FREE_AND_NULL(tmp)
9036 	    cur = end;
9037 	} while (*cur != 0);
9038 
9039     }
9040     /*
9041     * And now for the children...
9042     */
9043     child = node->children;
9044     if (IS_SCHEMA(child, "annotation")) {
9045 	/*
9046 	* Add the annotation to the simple type ancestor.
9047 	*/
9048 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9049 	    xmlSchemaParseAnnotation(ctxt, child, 1));
9050         child = child->next;
9051     }
9052     if (IS_SCHEMA(child, "simpleType")) {
9053 	xmlSchemaTypePtr subtype, last = NULL;
9054 
9055 	/*
9056 	* Anchor the member types in the "subtypes" field of the
9057 	* simple type.
9058 	*/
9059 	while (IS_SCHEMA(child, "simpleType")) {
9060 	    subtype = (xmlSchemaTypePtr)
9061 		xmlSchemaParseSimpleType(ctxt, schema, child, 0);
9062 	    if (subtype != NULL) {
9063 		if (last == NULL) {
9064 		    type->subtypes = subtype;
9065 		    last = subtype;
9066 		} else {
9067 		    last->next = subtype;
9068 		    last = subtype;
9069 		}
9070 		last->next = NULL;
9071 	    }
9072 	    child = child->next;
9073 	}
9074     }
9075     if (child != NULL) {
9076 	xmlSchemaPContentErr(ctxt,
9077 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9078 	    NULL, node, child, NULL, "(annotation?, simpleType*)");
9079     }
9080     if ((attr == NULL) && (type->subtypes == NULL)) {
9081 	 /*
9082 	* src-union-memberTypes-or-simpleTypes
9083 	* Either the memberTypes [attribute] of the <union> element must
9084 	* be non-empty or there must be at least one simpleType [child].
9085 	*/
9086 	xmlSchemaPCustomErr(ctxt,
9087 	    XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
9088 	    NULL, node,
9089 	    "Either the attribute 'memberTypes' or "
9090 	    "at least one <simpleType> child must be present", NULL);
9091     }
9092     return (0);
9093 }
9094 
9095 /**
9096  * xmlSchemaParseList:
9097  * @ctxt:  a schema validation context
9098  * @schema:  the schema being built
9099  * @node:  a subtree containing XML Schema information
9100  *
9101  * parse a XML schema List definition
9102  * *WARNING* this interface is highly subject to change
9103  *
9104  * Returns -1 in case of error, 0 if the declaration is improper and
9105  *         1 in case of success.
9106  */
9107 static xmlSchemaTypePtr
xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)9108 xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9109                    xmlNodePtr node)
9110 {
9111     xmlSchemaTypePtr type;
9112     xmlNodePtr child = NULL;
9113     xmlAttrPtr attr;
9114 
9115     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9116         return (NULL);
9117     /* Not a component, don't create it. */
9118     type = ctxt->ctxtType;
9119     /*
9120     * Mark the type as being of variety "list".
9121     */
9122     type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
9123     /*
9124     * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
9125     * then the `simple ur-type definition`."
9126     */
9127     type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
9128     /*
9129     * Check for illegal attributes.
9130     */
9131     attr = node->properties;
9132     while (attr != NULL) {
9133 	if (attr->ns == NULL) {
9134 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9135 		(!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
9136 		xmlSchemaPIllegalAttrErr(ctxt,
9137 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9138 	    }
9139 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9140 	    xmlSchemaPIllegalAttrErr(ctxt,
9141 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9142 	}
9143 	attr = attr->next;
9144     }
9145 
9146     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9147 
9148     /*
9149     * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
9150     * fields for holding the reference to the itemType.
9151     *
9152     * REVAMP TODO: Use the "base" and "baseNs" fields, since we will remove
9153     * the "ref" fields.
9154     */
9155     xmlSchemaPValAttrQName(ctxt, schema, NULL,
9156 	node, "itemType", &(type->baseNs), &(type->base));
9157     /*
9158     * And now for the children...
9159     */
9160     child = node->children;
9161     if (IS_SCHEMA(child, "annotation")) {
9162 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9163 	    xmlSchemaParseAnnotation(ctxt, child, 1));
9164         child = child->next;
9165     }
9166     if (IS_SCHEMA(child, "simpleType")) {
9167 	/*
9168 	* src-list-itemType-or-simpleType
9169 	* Either the itemType [attribute] or the <simpleType> [child] of
9170 	* the <list> element must be present, but not both.
9171 	*/
9172 	if (type->base != NULL) {
9173 	    xmlSchemaPCustomErr(ctxt,
9174 		XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9175 		NULL, node,
9176 		"The attribute 'itemType' and the <simpleType> child "
9177 		"are mutually exclusive", NULL);
9178 	} else {
9179 	    type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
9180 	}
9181         child = child->next;
9182     } else if (type->base == NULL) {
9183 	xmlSchemaPCustomErr(ctxt,
9184 	    XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9185 	    NULL, node,
9186 	    "Either the attribute 'itemType' or the <simpleType> child "
9187 	    "must be present", NULL);
9188     }
9189     if (child != NULL) {
9190 	xmlSchemaPContentErr(ctxt,
9191 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9192 	    NULL, node, child, NULL, "(annotation?, simpleType?)");
9193     }
9194     if ((type->base == NULL) &&
9195 	(type->subtypes == NULL) &&
9196 	(xmlSchemaGetPropNode(node, "itemType") == NULL)) {
9197 	xmlSchemaPCustomErr(ctxt,
9198 	    XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9199 	    NULL, node,
9200 	    "Either the attribute 'itemType' or the <simpleType> child "
9201 	    "must be present", NULL);
9202     }
9203     return (NULL);
9204 }
9205 
9206 /**
9207  * xmlSchemaParseSimpleType:
9208  * @ctxt:  a schema validation context
9209  * @schema:  the schema being built
9210  * @node:  a subtree containing XML Schema information
9211  *
9212  * parse a XML schema Simple Type definition
9213  * *WARNING* this interface is highly subject to change
9214  *
9215  * Returns -1 in case of error, 0 if the declaration is improper and
9216  * 1 in case of success.
9217  */
9218 static xmlSchemaTypePtr
xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int topLevel)9219 xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9220                          xmlNodePtr node, int topLevel)
9221 {
9222     xmlSchemaTypePtr type, oldCtxtType;
9223     xmlNodePtr child = NULL;
9224     const xmlChar *attrValue = NULL;
9225     xmlAttrPtr attr;
9226     int hasRestriction = 0;
9227 
9228     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9229         return (NULL);
9230 
9231     if (topLevel) {
9232 	attr = xmlSchemaGetPropNode(node, "name");
9233 	if (attr == NULL) {
9234 	    xmlSchemaPMissingAttrErr(ctxt,
9235 		XML_SCHEMAP_S4S_ATTR_MISSING,
9236 		NULL, node,
9237 		"name", NULL);
9238 	    return (NULL);
9239 	} else {
9240 	    if (xmlSchemaPValAttrNode(ctxt,
9241 		NULL, attr,
9242 		xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
9243 		return (NULL);
9244 	    /*
9245 	    * Skip built-in types.
9246 	    */
9247 	    if (ctxt->isS4S) {
9248 		xmlSchemaTypePtr biType;
9249 
9250 		if (ctxt->isRedefine) {
9251 		    /*
9252 		    * REDEFINE: Disallow redefinition of built-in-types.
9253 		    * TODO: It seems that the spec does not say anything
9254 		    * about this case.
9255 		    */
9256 		    xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
9257 			NULL, node,
9258 			"Redefinition of built-in simple types is not "
9259 			"supported", NULL);
9260 		    return(NULL);
9261 		}
9262 		biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
9263 		if (biType != NULL)
9264 		    return (biType);
9265 	    }
9266 	}
9267     }
9268     /*
9269     * TargetNamespace:
9270     * SPEC "The `actual value` of the targetNamespace [attribute]
9271     * of the <schema> ancestor element information item if present,
9272     * otherwise `absent`.
9273     */
9274     if (topLevel == 0) {
9275 #ifdef ENABLE_NAMED_LOCALS
9276         char buf[40];
9277 #endif
9278 	/*
9279 	* Parse as local simple type definition.
9280 	*/
9281 #ifdef ENABLE_NAMED_LOCALS
9282         snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
9283 	type = xmlSchemaAddType(ctxt, schema,
9284 	    XML_SCHEMA_TYPE_SIMPLE,
9285 	    xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
9286 	    ctxt->targetNamespace, node, 0);
9287 #else
9288 	type = xmlSchemaAddType(ctxt, schema,
9289 	    XML_SCHEMA_TYPE_SIMPLE,
9290 	    NULL, ctxt->targetNamespace, node, 0);
9291 #endif
9292 	if (type == NULL)
9293 	    return (NULL);
9294 	type->type = XML_SCHEMA_TYPE_SIMPLE;
9295 	type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
9296 	/*
9297 	* Check for illegal attributes.
9298 	*/
9299 	attr = node->properties;
9300 	while (attr != NULL) {
9301 	    if (attr->ns == NULL) {
9302 		if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
9303 		    xmlSchemaPIllegalAttrErr(ctxt,
9304 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9305 		}
9306 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9307 		    xmlSchemaPIllegalAttrErr(ctxt,
9308 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9309 	    }
9310 	    attr = attr->next;
9311 	}
9312     } else {
9313 	/*
9314 	* Parse as global simple type definition.
9315 	*
9316 	* Note that attrValue is the value of the attribute "name" here.
9317 	*/
9318 	type = xmlSchemaAddType(ctxt, schema, XML_SCHEMA_TYPE_SIMPLE,
9319 	    attrValue, ctxt->targetNamespace, node, 1);
9320 	if (type == NULL)
9321 	    return (NULL);
9322 	type->type = XML_SCHEMA_TYPE_SIMPLE;
9323 	type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
9324 	type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
9325 	/*
9326 	* Check for illegal attributes.
9327 	*/
9328 	attr = node->properties;
9329 	while (attr != NULL) {
9330 	    if (attr->ns == NULL) {
9331 		if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9332 		    (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
9333 		    (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
9334 		    xmlSchemaPIllegalAttrErr(ctxt,
9335 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9336 		}
9337 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9338 		xmlSchemaPIllegalAttrErr(ctxt,
9339 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9340 	    }
9341 	    attr = attr->next;
9342 	}
9343 	/*
9344 	* Attribute "final".
9345 	*/
9346 	attr = xmlSchemaGetPropNode(node, "final");
9347 	if (attr == NULL) {
9348 	    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9349 		type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
9350 	    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9351 		type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
9352 	    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9353 		type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
9354 	} else {
9355 	    attrValue = xmlSchemaGetProp(ctxt, node, "final");
9356 	    if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
9357 		-1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
9358 		XML_SCHEMAS_TYPE_FINAL_LIST,
9359 		XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
9360 
9361 		xmlSchemaPSimpleTypeErr(ctxt,
9362 		    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9363 		    WXS_BASIC_CAST type, (xmlNodePtr) attr,
9364 		    NULL, "(#all | List of (list | union | restriction)",
9365 		    attrValue, NULL, NULL, NULL);
9366 	    }
9367 	}
9368     }
9369     type->targetNamespace = ctxt->targetNamespace;
9370     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9371     /*
9372     * And now for the children...
9373     */
9374     oldCtxtType = ctxt->ctxtType;
9375 
9376     ctxt->ctxtType = type;
9377 
9378     child = node->children;
9379     if (IS_SCHEMA(child, "annotation")) {
9380         type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9381         child = child->next;
9382     }
9383     if (child == NULL) {
9384 	xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
9385 	    NULL, node, child, NULL,
9386 	    "(annotation?, (restriction | list | union))");
9387     } else if (IS_SCHEMA(child, "restriction")) {
9388         xmlSchemaParseRestriction(ctxt, schema, child,
9389 	    XML_SCHEMA_TYPE_SIMPLE);
9390 	hasRestriction = 1;
9391         child = child->next;
9392     } else if (IS_SCHEMA(child, "list")) {
9393         xmlSchemaParseList(ctxt, schema, child);
9394         child = child->next;
9395     } else if (IS_SCHEMA(child, "union")) {
9396         xmlSchemaParseUnion(ctxt, schema, child);
9397         child = child->next;
9398     }
9399     if (child != NULL) {
9400 	xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9401 	    NULL, node, child, NULL,
9402 	    "(annotation?, (restriction | list | union))");
9403     }
9404     /*
9405     * REDEFINE: SPEC src-redefine (5)
9406     * "Within the [children], each <simpleType> must have a
9407     * <restriction> among its [children] ... the `actual value` of whose
9408     * base [attribute] must be the same as the `actual value` of its own
9409     * name attribute plus target namespace;"
9410     */
9411     if (topLevel && ctxt->isRedefine && (! hasRestriction)) {
9412 	xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
9413 	    NULL, node, "This is a redefinition, thus the "
9414 	    "<simpleType> must have a <restriction> child", NULL);
9415     }
9416 
9417     ctxt->ctxtType = oldCtxtType;
9418     return (type);
9419 }
9420 
9421 /**
9422  * xmlSchemaParseModelGroupDefRef:
9423  * @ctxt:  the parser context
9424  * @schema: the schema being built
9425  * @node:  the node
9426  *
9427  * Parses a reference to a model group definition.
9428  *
9429  * We will return a particle component with a qname-component or
9430  * NULL in case of an error.
9431  */
9432 static xmlSchemaTreeItemPtr
xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)9433 xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
9434 			       xmlSchemaPtr schema,
9435 			       xmlNodePtr node)
9436 {
9437     xmlSchemaParticlePtr item;
9438     xmlNodePtr child = NULL;
9439     xmlAttrPtr attr;
9440     const xmlChar *ref = NULL, *refNs = NULL;
9441     int min, max;
9442 
9443     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9444         return (NULL);
9445 
9446     attr = xmlSchemaGetPropNode(node, "ref");
9447     if (attr == NULL) {
9448 	xmlSchemaPMissingAttrErr(ctxt,
9449 	    XML_SCHEMAP_S4S_ATTR_MISSING,
9450 	    NULL, node, "ref", NULL);
9451 	return (NULL);
9452     } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL,
9453 	attr, &refNs, &ref) != 0) {
9454 	return (NULL);
9455     }
9456     xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
9457     min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
9458     max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
9459 	"(xs:nonNegativeInteger | unbounded)");
9460     /*
9461     * Check for illegal attributes.
9462     */
9463     attr = node->properties;
9464     while (attr != NULL) {
9465 	if (attr->ns == NULL) {
9466 	    if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
9467 		(!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9468 		(!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
9469 		(!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
9470 		xmlSchemaPIllegalAttrErr(ctxt,
9471 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9472 	    }
9473 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9474 	    xmlSchemaPIllegalAttrErr(ctxt,
9475 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9476 	}
9477 	attr = attr->next;
9478     }
9479     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9480     item = xmlSchemaAddParticle(ctxt, node, min, max);
9481     if (item == NULL)
9482 	return (NULL);
9483     /*
9484     * Create a qname-reference and set as the term; it will be substituted
9485     * for the model group after the reference has been resolved.
9486     */
9487     item->children = (xmlSchemaTreeItemPtr)
9488 	xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_GROUP, ref, refNs);
9489     xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
9490     /*
9491     * And now for the children...
9492     */
9493     child = node->children;
9494     /* TODO: Is annotation even allowed for a model group reference? */
9495     if (IS_SCHEMA(child, "annotation")) {
9496 	/*
9497 	* TODO: What to do exactly with the annotation?
9498 	*/
9499 	item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9500 	child = child->next;
9501     }
9502     if (child != NULL) {
9503 	xmlSchemaPContentErr(ctxt,
9504 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9505 	    NULL, node, child, NULL,
9506 	    "(annotation?)");
9507     }
9508     /*
9509     * Corresponds to no component at all if minOccurs==maxOccurs==0.
9510     */
9511     if ((min == 0) && (max == 0))
9512 	return (NULL);
9513 
9514     return ((xmlSchemaTreeItemPtr) item);
9515 }
9516 
9517 /**
9518  * xmlSchemaParseModelGroupDefinition:
9519  * @ctxt:  a schema validation context
9520  * @schema:  the schema being built
9521  * @node:  a subtree containing XML Schema information
9522  *
9523  * Parses a XML schema model group definition.
9524  *
9525  * Note that the constraint src-redefine (6.2) can't be applied until
9526  * references have been resolved. So we will do this at the
9527  * component fixup level.
9528  *
9529  * *WARNING* this interface is highly subject to change
9530  *
9531  * Returns -1 in case of error, 0 if the declaration is improper and
9532  *         1 in case of success.
9533  */
9534 static xmlSchemaModelGroupDefPtr
xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)9535 xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
9536 				   xmlSchemaPtr schema,
9537 				   xmlNodePtr node)
9538 {
9539     xmlSchemaModelGroupDefPtr item;
9540     xmlNodePtr child = NULL;
9541     xmlAttrPtr attr;
9542     const xmlChar *name;
9543 
9544     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9545         return (NULL);
9546 
9547     attr = xmlSchemaGetPropNode(node, "name");
9548     if (attr == NULL) {
9549 	xmlSchemaPMissingAttrErr(ctxt,
9550 	    XML_SCHEMAP_S4S_ATTR_MISSING,
9551 	    NULL, node,
9552 	    "name", NULL);
9553 	return (NULL);
9554     } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
9555 	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
9556 	return (NULL);
9557     }
9558     item = xmlSchemaAddModelGroupDefinition(ctxt, schema, name,
9559 	ctxt->targetNamespace, node);
9560     if (item == NULL)
9561 	return (NULL);
9562     /*
9563     * Check for illegal attributes.
9564     */
9565     attr = node->properties;
9566     while (attr != NULL) {
9567 	if (attr->ns == NULL) {
9568 	    if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
9569 		(!xmlStrEqual(attr->name, BAD_CAST "id"))) {
9570 		xmlSchemaPIllegalAttrErr(ctxt,
9571 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9572 	    }
9573 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9574 	    xmlSchemaPIllegalAttrErr(ctxt,
9575 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9576 	}
9577 	attr = attr->next;
9578     }
9579     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9580     /*
9581     * And now for the children...
9582     */
9583     child = node->children;
9584     if (IS_SCHEMA(child, "annotation")) {
9585 	item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9586 	child = child->next;
9587     }
9588     if (IS_SCHEMA(child, "all")) {
9589 	item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9590 	    XML_SCHEMA_TYPE_ALL, 0);
9591 	child = child->next;
9592     } else if (IS_SCHEMA(child, "choice")) {
9593 	item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9594 	    XML_SCHEMA_TYPE_CHOICE, 0);
9595 	child = child->next;
9596     } else if (IS_SCHEMA(child, "sequence")) {
9597 	item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9598 	    XML_SCHEMA_TYPE_SEQUENCE, 0);
9599 	child = child->next;
9600     }
9601 
9602 
9603 
9604     if (child != NULL) {
9605 	xmlSchemaPContentErr(ctxt,
9606 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9607 	    NULL, node, child, NULL,
9608 	    "(annotation?, (all | choice | sequence)?)");
9609     }
9610     return (item);
9611 }
9612 
9613 /**
9614  * xmlSchemaCleanupDoc:
9615  * @ctxt:  a schema validation context
9616  * @node:  the root of the document.
9617  *
9618  * removes unwanted nodes in a schemas document tree
9619  */
9620 static void
xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr root)9621 xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
9622 {
9623     xmlNodePtr delete, cur;
9624 
9625     if ((ctxt == NULL) || (root == NULL)) return;
9626 
9627     /*
9628      * Remove all the blank text nodes
9629      */
9630     delete = NULL;
9631     cur = root;
9632     while (cur != NULL) {
9633         if (delete != NULL) {
9634             xmlUnlinkNode(delete);
9635             xmlFreeNode(delete);
9636             delete = NULL;
9637         }
9638         if (cur->type == XML_TEXT_NODE) {
9639             if (IS_BLANK_NODE(cur)) {
9640                 if (xmlNodeGetSpacePreserve(cur) != 1) {
9641                     delete = cur;
9642                 }
9643             }
9644         } else if ((cur->type != XML_ELEMENT_NODE) &&
9645                    (cur->type != XML_CDATA_SECTION_NODE)) {
9646             delete = cur;
9647             goto skip_children;
9648         }
9649 
9650         /*
9651          * Skip to next node
9652          */
9653         if (cur->children != NULL) {
9654             if ((cur->children->type != XML_ENTITY_DECL) &&
9655                 (cur->children->type != XML_ENTITY_REF_NODE) &&
9656                 (cur->children->type != XML_ENTITY_NODE)) {
9657                 cur = cur->children;
9658                 continue;
9659             }
9660         }
9661       skip_children:
9662         if (cur->next != NULL) {
9663             cur = cur->next;
9664             continue;
9665         }
9666 
9667         do {
9668             cur = cur->parent;
9669             if (cur == NULL)
9670                 break;
9671             if (cur == root) {
9672                 cur = NULL;
9673                 break;
9674             }
9675             if (cur->next != NULL) {
9676                 cur = cur->next;
9677                 break;
9678             }
9679         } while (cur != NULL);
9680     }
9681     if (delete != NULL) {
9682         xmlUnlinkNode(delete);
9683         xmlFreeNode(delete);
9684         delete = NULL;
9685     }
9686 }
9687 
9688 
9689 static void
xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)9690 xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
9691 {
9692     if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
9693 	schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
9694 
9695     if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
9696 	schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
9697 
9698     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
9699 	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
9700     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9701 	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
9702     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9703 	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
9704     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9705 	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
9706 
9707     if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
9708 	schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
9709     if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
9710 	schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
9711     if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
9712 	schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
9713 }
9714 
9715 static int
xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)9716 xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt,
9717 			     xmlSchemaPtr schema,
9718 			     xmlNodePtr node)
9719 {
9720     xmlAttrPtr attr;
9721     const xmlChar *val;
9722     int res = 0, oldErrs = ctxt->nberrors;
9723 
9724     /*
9725     * Those flags should be moved to the parser context flags,
9726     * since they are not visible at the component level. I.e.
9727     * they are used if processing schema *documents* only.
9728     */
9729     res = xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9730     HFAILURE;
9731 
9732     /*
9733     * Since the version is of type xs:token, we won't bother to
9734     * check it.
9735     */
9736     /* REMOVED:
9737     attr = xmlSchemaGetPropNode(node, "version");
9738     if (attr != NULL) {
9739 	res = xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9740 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &val);
9741 	HFAILURE;
9742     }
9743     */
9744     attr = xmlSchemaGetPropNode(node, "targetNamespace");
9745     if (attr != NULL) {
9746 	res = xmlSchemaPValAttrNode(ctxt, NULL, attr,
9747 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
9748 	HFAILURE;
9749 	if (res != 0) {
9750 	    ctxt->stop = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
9751 	    goto exit;
9752 	}
9753     }
9754     attr = xmlSchemaGetPropNode(node, "elementFormDefault");
9755     if (attr != NULL) {
9756 	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9757 	res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9758 	    XML_SCHEMAS_QUALIF_ELEM);
9759 	HFAILURE;
9760 	if (res != 0) {
9761 	    xmlSchemaPSimpleTypeErr(ctxt,
9762 		XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
9763 		NULL, (xmlNodePtr) attr, NULL,
9764 		"(qualified | unqualified)", val, NULL, NULL, NULL);
9765 	}
9766     }
9767     attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
9768     if (attr != NULL) {
9769 	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9770 	res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9771 	    XML_SCHEMAS_QUALIF_ATTR);
9772 	HFAILURE;
9773 	if (res != 0) {
9774 	    xmlSchemaPSimpleTypeErr(ctxt,
9775 		XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
9776 		NULL, (xmlNodePtr) attr, NULL,
9777 		"(qualified | unqualified)", val, NULL, NULL, NULL);
9778 	}
9779     }
9780     attr = xmlSchemaGetPropNode(node, "finalDefault");
9781     if (attr != NULL) {
9782 	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9783 	res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
9784 	    XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
9785 	    XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
9786 	    -1,
9787 	    XML_SCHEMAS_FINAL_DEFAULT_LIST,
9788 	    XML_SCHEMAS_FINAL_DEFAULT_UNION);
9789 	HFAILURE;
9790 	if (res != 0) {
9791 	    xmlSchemaPSimpleTypeErr(ctxt,
9792 		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9793 		NULL, (xmlNodePtr) attr, NULL,
9794 		"(#all | List of (extension | restriction | list | union))",
9795 		val, NULL, NULL, NULL);
9796 	}
9797     }
9798     attr = xmlSchemaGetPropNode(node, "blockDefault");
9799     if (attr != NULL) {
9800 	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9801 	res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
9802 	    XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
9803 	    XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
9804 	    XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1);
9805 	HFAILURE;
9806 	if (res != 0) {
9807 	    xmlSchemaPSimpleTypeErr(ctxt,
9808 		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9809 		NULL, (xmlNodePtr) attr, NULL,
9810 		"(#all | List of (extension | restriction | substitution))",
9811 		val, NULL, NULL, NULL);
9812 	}
9813     }
9814 
9815 exit:
9816     if (oldErrs != ctxt->nberrors)
9817 	res = ctxt->err;
9818     return(res);
9819 exit_failure:
9820     return(-1);
9821 }
9822 
9823 /**
9824  * xmlSchemaParseSchemaTopLevel:
9825  * @ctxt:  a schema validation context
9826  * @schema:  the schemas
9827  * @nodes:  the list of top level nodes
9828  *
9829  * Returns the internal XML Schema structure built from the resource or
9830  *         NULL in case of error
9831  */
9832 static int
xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr nodes)9833 xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
9834                              xmlSchemaPtr schema, xmlNodePtr nodes)
9835 {
9836     xmlNodePtr child;
9837     xmlSchemaAnnotPtr annot;
9838     int res = 0, oldErrs, tmpOldErrs;
9839 
9840     if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
9841         return(-1);
9842 
9843     oldErrs = ctxt->nberrors;
9844     child = nodes;
9845     while ((IS_SCHEMA(child, "include")) ||
9846 	   (IS_SCHEMA(child, "import")) ||
9847 	   (IS_SCHEMA(child, "redefine")) ||
9848 	   (IS_SCHEMA(child, "annotation"))) {
9849 	if (IS_SCHEMA(child, "annotation")) {
9850 	    annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9851 	    if (schema->annot == NULL)
9852 		schema->annot = annot;
9853 	    else
9854 		xmlSchemaFreeAnnot(annot);
9855 	} else if (IS_SCHEMA(child, "import")) {
9856 	    tmpOldErrs = ctxt->nberrors;
9857 	    res = xmlSchemaParseImport(ctxt, schema, child);
9858 	    HFAILURE;
9859 	    HSTOP(ctxt);
9860 	    if (tmpOldErrs != ctxt->nberrors)
9861 		goto exit;
9862 	} else if (IS_SCHEMA(child, "include")) {
9863 	    tmpOldErrs = ctxt->nberrors;
9864 	    res = xmlSchemaParseInclude(ctxt, schema, child);
9865 	    HFAILURE;
9866 	    HSTOP(ctxt);
9867 	    if (tmpOldErrs != ctxt->nberrors)
9868 		goto exit;
9869 	} else if (IS_SCHEMA(child, "redefine")) {
9870 	    tmpOldErrs = ctxt->nberrors;
9871 	    res = xmlSchemaParseRedefine(ctxt, schema, child);
9872 	    HFAILURE;
9873 	    HSTOP(ctxt);
9874 	    if (tmpOldErrs != ctxt->nberrors)
9875 		goto exit;
9876 	}
9877 	child = child->next;
9878     }
9879     /*
9880     * URGENT TODO: Change the functions to return int results.
9881     * We need especially to catch internal errors.
9882     */
9883     while (child != NULL) {
9884 	if (IS_SCHEMA(child, "complexType")) {
9885 	    xmlSchemaParseComplexType(ctxt, schema, child, 1);
9886 	    child = child->next;
9887 	} else if (IS_SCHEMA(child, "simpleType")) {
9888 	    xmlSchemaParseSimpleType(ctxt, schema, child, 1);
9889 	    child = child->next;
9890 	} else if (IS_SCHEMA(child, "element")) {
9891 	    xmlSchemaParseElement(ctxt, schema, child, NULL, 1);
9892 	    child = child->next;
9893 	} else if (IS_SCHEMA(child, "attribute")) {
9894 	    xmlSchemaParseGlobalAttribute(ctxt, schema, child);
9895 	    child = child->next;
9896 	} else if (IS_SCHEMA(child, "attributeGroup")) {
9897 	    xmlSchemaParseAttributeGroupDefinition(ctxt, schema, child);
9898 	    child = child->next;
9899 	} else if (IS_SCHEMA(child, "group")) {
9900 	    xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
9901 	    child = child->next;
9902 	} else if (IS_SCHEMA(child, "notation")) {
9903 	    xmlSchemaParseNotation(ctxt, schema, child);
9904 	    child = child->next;
9905 	} else {
9906 	    xmlSchemaPContentErr(ctxt,
9907 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9908 		NULL, child->parent, child,
9909 		NULL, "((include | import | redefine | annotation)*, "
9910 		"(((simpleType | complexType | group | attributeGroup) "
9911 		"| element | attribute | notation), annotation*)*)");
9912 	    child = child->next;
9913 	}
9914 	while (IS_SCHEMA(child, "annotation")) {
9915 	    /*
9916 	    * TODO: We should add all annotations.
9917 	    */
9918 	    annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9919 	    if (schema->annot == NULL)
9920 		schema->annot = annot;
9921 	    else
9922 		xmlSchemaFreeAnnot(annot);
9923 	    child = child->next;
9924 	}
9925     }
9926 exit:
9927     ctxt->ctxtType = NULL;
9928     if (oldErrs != ctxt->nberrors)
9929 	res = ctxt->err;
9930     return(res);
9931 exit_failure:
9932     return(-1);
9933 }
9934 
9935 static xmlSchemaSchemaRelationPtr
xmlSchemaSchemaRelationCreate(void)9936 xmlSchemaSchemaRelationCreate(void)
9937 {
9938     xmlSchemaSchemaRelationPtr ret;
9939 
9940     ret = (xmlSchemaSchemaRelationPtr)
9941 	xmlMalloc(sizeof(xmlSchemaSchemaRelation));
9942     if (ret == NULL) {
9943 	xmlSchemaPErrMemory(NULL, "allocating schema relation", NULL);
9944 	return(NULL);
9945     }
9946     memset(ret, 0, sizeof(xmlSchemaSchemaRelation));
9947     return(ret);
9948 }
9949 
9950 #if 0
9951 static void
9952 xmlSchemaSchemaRelationFree(xmlSchemaSchemaRelationPtr rel)
9953 {
9954     xmlFree(rel);
9955 }
9956 #endif
9957 
9958 static void
xmlSchemaRedefListFree(xmlSchemaRedefPtr redef)9959 xmlSchemaRedefListFree(xmlSchemaRedefPtr redef)
9960 {
9961     xmlSchemaRedefPtr prev;
9962 
9963     while (redef != NULL) {
9964 	prev = redef;
9965 	redef = redef->next;
9966 	xmlFree(prev);
9967     }
9968 }
9969 
9970 static void
xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con)9971 xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con)
9972 {
9973     /*
9974     * After the construction context has been freed, there will be
9975     * no schema graph available any more. Only the schema buckets
9976     * will stay alive, which are put into the "schemasImports" and
9977     * "includes" slots of the xmlSchema.
9978     */
9979     if (con->buckets != NULL)
9980 	xmlSchemaItemListFree(con->buckets);
9981     if (con->pending != NULL)
9982 	xmlSchemaItemListFree(con->pending);
9983     if (con->substGroups != NULL)
9984 	xmlHashFree(con->substGroups, xmlSchemaSubstGroupFreeEntry);
9985     if (con->redefs != NULL)
9986 	xmlSchemaRedefListFree(con->redefs);
9987     if (con->dict != NULL)
9988 	xmlDictFree(con->dict);
9989     xmlFree(con);
9990 }
9991 
9992 static xmlSchemaConstructionCtxtPtr
xmlSchemaConstructionCtxtCreate(xmlDictPtr dict)9993 xmlSchemaConstructionCtxtCreate(xmlDictPtr dict)
9994 {
9995     xmlSchemaConstructionCtxtPtr ret;
9996 
9997     ret = (xmlSchemaConstructionCtxtPtr)
9998 	xmlMalloc(sizeof(xmlSchemaConstructionCtxt));
9999     if (ret == NULL) {
10000         xmlSchemaPErrMemory(NULL,
10001 	    "allocating schema construction context", NULL);
10002         return (NULL);
10003     }
10004     memset(ret, 0, sizeof(xmlSchemaConstructionCtxt));
10005 
10006     ret->buckets = xmlSchemaItemListCreate();
10007     if (ret->buckets == NULL) {
10008 	xmlSchemaPErrMemory(NULL,
10009 	    "allocating list of schema buckets", NULL);
10010 	xmlFree(ret);
10011         return (NULL);
10012     }
10013     ret->pending = xmlSchemaItemListCreate();
10014     if (ret->pending == NULL) {
10015 	xmlSchemaPErrMemory(NULL,
10016 	    "allocating list of pending global components", NULL);
10017 	xmlSchemaConstructionCtxtFree(ret);
10018         return (NULL);
10019     }
10020     ret->dict = dict;
10021     xmlDictReference(dict);
10022     return(ret);
10023 }
10024 
10025 static xmlSchemaParserCtxtPtr
xmlSchemaParserCtxtCreate(void)10026 xmlSchemaParserCtxtCreate(void)
10027 {
10028     xmlSchemaParserCtxtPtr ret;
10029 
10030     ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10031     if (ret == NULL) {
10032         xmlSchemaPErrMemory(NULL, "allocating schema parser context",
10033                             NULL);
10034         return (NULL);
10035     }
10036     memset(ret, 0, sizeof(xmlSchemaParserCtxt));
10037     ret->type = XML_SCHEMA_CTXT_PARSER;
10038     ret->attrProhibs = xmlSchemaItemListCreate();
10039     if (ret->attrProhibs == NULL) {
10040 	xmlFree(ret);
10041 	return(NULL);
10042     }
10043     return(ret);
10044 }
10045 
10046 /**
10047  * xmlSchemaNewParserCtxtUseDict:
10048  * @URL:  the location of the schema
10049  * @dict: the dictionary to be used
10050  *
10051  * Create an XML Schemas parse context for that file/resource expected
10052  * to contain an XML Schemas file.
10053  *
10054  * Returns the parser context or NULL in case of error
10055  */
10056 static xmlSchemaParserCtxtPtr
xmlSchemaNewParserCtxtUseDict(const char * URL,xmlDictPtr dict)10057 xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
10058 {
10059     xmlSchemaParserCtxtPtr ret;
10060 
10061     ret = xmlSchemaParserCtxtCreate();
10062     if (ret == NULL)
10063         return (NULL);
10064     ret->dict = dict;
10065     xmlDictReference(dict);
10066     if (URL != NULL)
10067 	ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
10068     return (ret);
10069 }
10070 
10071 static int
xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)10072 xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
10073 {
10074     if (vctxt->pctxt == NULL) {
10075         if (vctxt->schema != NULL)
10076 	    vctxt->pctxt =
10077 		xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
10078 	else
10079 	    vctxt->pctxt = xmlSchemaNewParserCtxt("*");
10080 	if (vctxt->pctxt == NULL) {
10081 	    VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
10082 		"failed to create a temp. parser context");
10083 	    return (-1);
10084 	}
10085 	/* TODO: Pass user data. */
10086 	xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error,
10087 	    vctxt->warning, vctxt->errCtxt);
10088 	xmlSchemaSetParserStructuredErrors(vctxt->pctxt, vctxt->serror,
10089 	    vctxt->errCtxt);
10090     }
10091     return (0);
10092 }
10093 
10094 /**
10095  * xmlSchemaGetSchemaBucket:
10096  * @pctxt: the schema parser context
10097  * @schemaLocation: the URI of the schema document
10098  *
10099  * Returns a schema bucket if it was already parsed.
10100  *
10101  * Returns a schema bucket if it was already parsed from
10102  *         @schemaLocation, NULL otherwise.
10103  */
10104 static xmlSchemaBucketPtr
xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt,const xmlChar * schemaLocation)10105 xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10106 			    const xmlChar *schemaLocation)
10107 {
10108     xmlSchemaBucketPtr cur;
10109     xmlSchemaItemListPtr list;
10110 
10111     list = pctxt->constructor->buckets;
10112     if (list->nbItems == 0)
10113 	return(NULL);
10114     else {
10115 	int i;
10116 	for (i = 0; i < list->nbItems; i++) {
10117 	    cur = (xmlSchemaBucketPtr) list->items[i];
10118 	    /* Pointer comparison! */
10119 	    if (cur->schemaLocation == schemaLocation)
10120 		return(cur);
10121 	}
10122     }
10123     return(NULL);
10124 }
10125 
10126 static xmlSchemaBucketPtr
xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt,const xmlChar * schemaLocation,const xmlChar * targetNamespace)10127 xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10128 				     const xmlChar *schemaLocation,
10129 				     const xmlChar *targetNamespace)
10130 {
10131     xmlSchemaBucketPtr cur;
10132     xmlSchemaItemListPtr list;
10133 
10134     list = pctxt->constructor->buckets;
10135     if (list->nbItems == 0)
10136 	return(NULL);
10137     else {
10138 	int i;
10139 	for (i = 0; i < list->nbItems; i++) {
10140 	    cur = (xmlSchemaBucketPtr) list->items[i];
10141 	    /* Pointer comparison! */
10142 	    if ((cur->origTargetNamespace == NULL) &&
10143 		(cur->schemaLocation == schemaLocation) &&
10144 		(cur->targetNamespace == targetNamespace))
10145 		return(cur);
10146 	}
10147     }
10148     return(NULL);
10149 }
10150 
10151 
10152 #define IS_BAD_SCHEMA_DOC(b) \
10153     (((b)->doc == NULL) && ((b)->schemaLocation != NULL))
10154 
10155 static xmlSchemaBucketPtr
xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt,const xmlChar * targetNamespace,int imported)10156 xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt,
10157 				 const xmlChar *targetNamespace,
10158 				 int imported)
10159 {
10160     xmlSchemaBucketPtr cur;
10161     xmlSchemaItemListPtr list;
10162 
10163     list = pctxt->constructor->buckets;
10164     if (list->nbItems == 0)
10165 	return(NULL);
10166     else {
10167 	int i;
10168 	for (i = 0; i < list->nbItems; i++) {
10169 	    cur = (xmlSchemaBucketPtr) list->items[i];
10170 	    if ((! IS_BAD_SCHEMA_DOC(cur)) &&
10171 		(cur->origTargetNamespace == targetNamespace) &&
10172 		((imported && cur->imported) ||
10173 		 ((!imported) && (!cur->imported))))
10174 		return(cur);
10175 	}
10176     }
10177     return(NULL);
10178 }
10179 
10180 static int
xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlSchemaBucketPtr bucket)10181 xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt,
10182 		     xmlSchemaPtr schema,
10183 		     xmlSchemaBucketPtr bucket)
10184 {
10185     int oldFlags;
10186     xmlDocPtr oldDoc;
10187     xmlNodePtr node;
10188     int ret, oldErrs;
10189     xmlSchemaBucketPtr oldbucket = pctxt->constructor->bucket;
10190 
10191     /*
10192     * Save old values; reset the *main* schema.
10193     * URGENT TODO: This is not good; move the per-document information
10194     * to the parser. Get rid of passing the main schema to the
10195     * parsing functions.
10196     */
10197     oldFlags = schema->flags;
10198     oldDoc = schema->doc;
10199     if (schema->flags != 0)
10200 	xmlSchemaClearSchemaDefaults(schema);
10201     schema->doc = bucket->doc;
10202     pctxt->schema = schema;
10203     /*
10204     * Keep the current target namespace on the parser *not* on the
10205     * main schema.
10206     */
10207     pctxt->targetNamespace = bucket->targetNamespace;
10208     WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
10209 
10210     if ((bucket->targetNamespace != NULL) &&
10211 	xmlStrEqual(bucket->targetNamespace, xmlSchemaNs)) {
10212 	/*
10213 	* We are parsing the schema for schemas!
10214 	*/
10215 	pctxt->isS4S = 1;
10216     }
10217     /* Mark it as parsed, even if parsing fails. */
10218     bucket->parsed++;
10219     /* Compile the schema doc. */
10220     node = xmlDocGetRootElement(bucket->doc);
10221     ret = xmlSchemaParseSchemaElement(pctxt, schema, node);
10222     if (ret != 0)
10223 	goto exit;
10224     /* An empty schema; just get out. */
10225     if (node->children == NULL)
10226 	goto exit;
10227     oldErrs = pctxt->nberrors;
10228     ret = xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
10229     if (ret != 0)
10230 	goto exit;
10231     /*
10232     * TODO: Not nice, but I'm not 100% sure we will get always an error
10233     * as a result of the above functions; so better rely on pctxt->err
10234     * as well.
10235     */
10236     if ((ret == 0) && (oldErrs != pctxt->nberrors)) {
10237 	ret = pctxt->err;
10238 	goto exit;
10239     }
10240 
10241 exit:
10242     WXS_CONSTRUCTOR(pctxt)->bucket = oldbucket;
10243     /* Restore schema values. */
10244     schema->doc = oldDoc;
10245     schema->flags = oldFlags;
10246     return(ret);
10247 }
10248 
10249 static int
xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlSchemaBucketPtr bucket)10250 xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt,
10251 		     xmlSchemaPtr schema,
10252 		     xmlSchemaBucketPtr bucket)
10253 {
10254     xmlSchemaParserCtxtPtr newpctxt;
10255     int res = 0;
10256 
10257     if (bucket == NULL)
10258 	return(0);
10259     if (bucket->parsed) {
10260 	PERROR_INT("xmlSchemaParseNewDoc",
10261 	    "reparsing a schema doc");
10262 	return(-1);
10263     }
10264     if (bucket->doc == NULL) {
10265 	PERROR_INT("xmlSchemaParseNewDoc",
10266 	    "parsing a schema doc, but there's no doc");
10267 	return(-1);
10268     }
10269     if (pctxt->constructor == NULL) {
10270 	PERROR_INT("xmlSchemaParseNewDoc",
10271 	    "no constructor");
10272 	return(-1);
10273     }
10274     /* Create and init the temporary parser context. */
10275     newpctxt = xmlSchemaNewParserCtxtUseDict(
10276 	(const char *) bucket->schemaLocation, pctxt->dict);
10277     if (newpctxt == NULL)
10278 	return(-1);
10279     newpctxt->constructor = pctxt->constructor;
10280     /*
10281     * TODO: Can we avoid that the parser knows about the main schema?
10282     * It would be better if he knows about the current schema bucket
10283     * only.
10284     */
10285     newpctxt->schema = schema;
10286     xmlSchemaSetParserErrors(newpctxt, pctxt->error, pctxt->warning,
10287 	pctxt->errCtxt);
10288     xmlSchemaSetParserStructuredErrors(newpctxt, pctxt->serror,
10289 	pctxt->errCtxt);
10290     newpctxt->counter = pctxt->counter;
10291 
10292 
10293     res = xmlSchemaParseNewDocWithContext(newpctxt, schema, bucket);
10294 
10295     /* Channel back errors and cleanup the temporary parser context. */
10296     if (res != 0)
10297 	pctxt->err = res;
10298     pctxt->nberrors += newpctxt->nberrors;
10299     pctxt->counter = newpctxt->counter;
10300     newpctxt->constructor = NULL;
10301     /* Free the parser context. */
10302     xmlSchemaFreeParserCtxt(newpctxt);
10303     return(res);
10304 }
10305 
10306 static void
xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket,xmlSchemaSchemaRelationPtr rel)10307 xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket,
10308 				xmlSchemaSchemaRelationPtr rel)
10309 {
10310     xmlSchemaSchemaRelationPtr cur = bucket->relations;
10311 
10312     if (cur == NULL) {
10313 	bucket->relations = rel;
10314 	return;
10315     }
10316     while (cur->next != NULL)
10317 	cur = cur->next;
10318     cur->next = rel;
10319 }
10320 
10321 
10322 static const xmlChar *
xmlSchemaBuildAbsoluteURI(xmlDictPtr dict,const xmlChar * location,xmlNodePtr ctxtNode)10323 xmlSchemaBuildAbsoluteURI(xmlDictPtr dict, const xmlChar* location,
10324 			  xmlNodePtr ctxtNode)
10325 {
10326     /*
10327     * Build an absolute location URI.
10328     */
10329     if (location != NULL) {
10330 	if (ctxtNode == NULL)
10331 	    return(location);
10332 	else {
10333 	    xmlChar *base, *URI;
10334 	    const xmlChar *ret = NULL;
10335 
10336 	    base = xmlNodeGetBase(ctxtNode->doc, ctxtNode);
10337 	    if (base == NULL) {
10338 		URI = xmlBuildURI(location, ctxtNode->doc->URL);
10339 	    } else {
10340 		URI = xmlBuildURI(location, base);
10341 		xmlFree(base);
10342 	    }
10343 	    if (URI != NULL) {
10344 		ret = xmlDictLookup(dict, URI, -1);
10345 		xmlFree(URI);
10346 		return(ret);
10347 	    }
10348 	}
10349     }
10350     return(NULL);
10351 }
10352 
10353 
10354 
10355 /**
10356  * xmlSchemaAddSchemaDoc:
10357  * @pctxt:  a schema validation context
10358  * @schema:  the schema being built
10359  * @node:  a subtree containing XML Schema information
10360  *
10361  * Parse an included (and to-be-redefined) XML schema document.
10362  *
10363  * Returns 0 on success, a positive error code on errors and
10364  *         -1 in case of an internal or API error.
10365  */
10366 
10367 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)10368 xmlSchemaAddSchemaDoc(xmlSchemaParserCtxtPtr pctxt,
10369 		int type, /* import or include or redefine */
10370 		const xmlChar *schemaLocation,
10371 		xmlDocPtr schemaDoc,
10372 		const char *schemaBuffer,
10373 		int schemaBufferLen,
10374 		xmlNodePtr invokingNode,
10375 		const xmlChar *sourceTargetNamespace,
10376 		const xmlChar *importNamespace,
10377 		xmlSchemaBucketPtr *bucket)
10378 {
10379     const xmlChar *targetNamespace = NULL;
10380     xmlSchemaSchemaRelationPtr relation = NULL;
10381     xmlDocPtr doc = NULL;
10382     int res = 0, err = 0, located = 0, preserveDoc = 0;
10383     xmlSchemaBucketPtr bkt = NULL;
10384 
10385     if (bucket != NULL)
10386 	*bucket = NULL;
10387 
10388     switch (type) {
10389 	case XML_SCHEMA_SCHEMA_IMPORT:
10390 	case XML_SCHEMA_SCHEMA_MAIN:
10391 	    err = XML_SCHEMAP_SRC_IMPORT;
10392 	    break;
10393 	case XML_SCHEMA_SCHEMA_INCLUDE:
10394 	    err = XML_SCHEMAP_SRC_INCLUDE;
10395 	    break;
10396 	case XML_SCHEMA_SCHEMA_REDEFINE:
10397 	    err = XML_SCHEMAP_SRC_REDEFINE;
10398 	    break;
10399     }
10400 
10401 
10402     /* Special handling for the main schema:
10403     * skip the location and relation logic and just parse the doc.
10404     * We need just a bucket to be returned in this case.
10405     */
10406     if ((type == XML_SCHEMA_SCHEMA_MAIN) || (! WXS_HAS_BUCKETS(pctxt)))
10407 	goto doc_load;
10408 
10409     /* Note that we expect the location to be an absolute URI. */
10410     if (schemaLocation != NULL) {
10411 	bkt = xmlSchemaGetSchemaBucket(pctxt, schemaLocation);
10412 	if ((bkt != NULL) &&
10413 	    (pctxt->constructor->bucket == bkt)) {
10414 	    /* Report self-imports/inclusions/redefinitions. */
10415 
10416 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10417 		invokingNode, NULL,
10418 		"The schema must not import/include/redefine itself",
10419 		NULL, NULL);
10420 	    goto exit;
10421 	}
10422     }
10423     /*
10424     * Create a relation for the graph of schemas.
10425     */
10426     relation = xmlSchemaSchemaRelationCreate();
10427     if (relation == NULL)
10428 	return(-1);
10429     xmlSchemaSchemaRelationAddChild(pctxt->constructor->bucket,
10430 	relation);
10431     relation->type = type;
10432 
10433     /*
10434     * Save the namespace import information.
10435     */
10436     if (WXS_IS_BUCKET_IMPMAIN(type)) {
10437 	relation->importNamespace = importNamespace;
10438 	if (schemaLocation == NULL) {
10439 	    /*
10440 	    * No location; this is just an import of the namespace.
10441 	    * Note that we don't assign a bucket to the relation
10442 	    * in this case.
10443 	    */
10444 	    goto exit;
10445 	}
10446 	targetNamespace = importNamespace;
10447     }
10448 
10449     /* Did we already fetch the doc? */
10450     if (bkt != NULL) {
10451 	if ((WXS_IS_BUCKET_IMPMAIN(type)) && (! bkt->imported)) {
10452 	    /*
10453 	    * We included/redefined and then try to import a schema,
10454 	    * but the new location provided for import was different.
10455 	    */
10456 	    if (schemaLocation == NULL)
10457 		schemaLocation = BAD_CAST "in_memory_buffer";
10458 	    if (!xmlStrEqual(schemaLocation,
10459 		bkt->schemaLocation)) {
10460 		xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10461 		    invokingNode, NULL,
10462 		    "The schema document '%s' cannot be imported, since "
10463 		    "it was already included or redefined",
10464 		    schemaLocation, NULL);
10465 		goto exit;
10466 	    }
10467 	} else if ((! WXS_IS_BUCKET_IMPMAIN(type)) && (bkt->imported)) {
10468 	    /*
10469 	    * We imported and then try to include/redefine a schema,
10470 	    * but the new location provided for the include/redefine
10471 	    * was different.
10472 	    */
10473 	    if (schemaLocation == NULL)
10474 		schemaLocation = BAD_CAST "in_memory_buffer";
10475 	    if (!xmlStrEqual(schemaLocation,
10476 		bkt->schemaLocation)) {
10477 		xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10478 		    invokingNode, NULL,
10479 		    "The schema document '%s' cannot be included or "
10480 		    "redefined, since it was already imported",
10481 		    schemaLocation, NULL);
10482 		goto exit;
10483 	    }
10484 	}
10485     }
10486 
10487     if (WXS_IS_BUCKET_IMPMAIN(type)) {
10488 	/*
10489 	* Given that the schemaLocation [attribute] is only a hint, it is open
10490 	* to applications to ignore all but the first <import> for a given
10491 	* namespace, regardless of the `actual value` of schemaLocation, but
10492 	* such a strategy risks missing useful information when new
10493 	* schemaLocations are offered.
10494 	*
10495 	* We will use the first <import> that comes with a location.
10496 	* Further <import>s *with* a location, will result in an error.
10497 	* TODO: Better would be to just report a warning here, but
10498 	* we'll try it this way until someone complains.
10499 	*
10500 	* Schema Document Location Strategy:
10501 	* 3 Based on the namespace name, identify an existing schema document,
10502 	* either as a resource which is an XML document or a <schema> element
10503 	* information item, in some local schema repository;
10504 	* 5 Attempt to resolve the namespace name to locate such a resource.
10505 	*
10506 	* NOTE: (3) and (5) are not supported.
10507 	*/
10508 	if (bkt != NULL) {
10509 	    relation->bucket = bkt;
10510 	    goto exit;
10511 	}
10512 	bkt = xmlSchemaGetSchemaBucketByTNS(pctxt,
10513 	    importNamespace, 1);
10514 
10515 	if (bkt != NULL) {
10516 	    relation->bucket = bkt;
10517 	    if (bkt->schemaLocation == NULL) {
10518 		/* First given location of the schema; load the doc. */
10519 		bkt->schemaLocation = schemaLocation;
10520 	    } else {
10521 		if (!xmlStrEqual(schemaLocation,
10522 		    bkt->schemaLocation)) {
10523 		    /*
10524 		    * Additional location given; just skip it.
10525 		    * URGENT TODO: We should report a warning here.
10526 		    * res = XML_SCHEMAP_SRC_IMPORT;
10527 		    */
10528 		    if (schemaLocation == NULL)
10529 			schemaLocation = BAD_CAST "in_memory_buffer";
10530 
10531 		    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10532 			XML_SCHEMAP_WARN_SKIP_SCHEMA,
10533 			invokingNode, NULL,
10534 			"Skipping import of schema located at '%s' for the "
10535 			"namespace '%s', since this namespace was already "
10536 			"imported with the schema located at '%s'",
10537 			schemaLocation, importNamespace, bkt->schemaLocation);
10538 		}
10539 		goto exit;
10540 	    }
10541 	}
10542 	/*
10543 	* No bucket + first location: load the doc and create a
10544 	* bucket.
10545 	*/
10546     } else {
10547 	/* <include> and <redefine> */
10548 	if (bkt != NULL) {
10549 
10550 	    if ((bkt->origTargetNamespace == NULL) &&
10551 		(bkt->targetNamespace != sourceTargetNamespace)) {
10552 		xmlSchemaBucketPtr chamel;
10553 
10554 		/*
10555 		* Chameleon include/redefine: skip loading only if it was
10556 		* already build for the targetNamespace of the including
10557 		* schema.
10558 		*/
10559 		/*
10560 		* URGENT TODO: If the schema is a chameleon-include then copy
10561 		* the components into the including schema and modify the
10562 		* targetNamespace of those components, do nothing otherwise.
10563 		* NOTE: This is currently worked-around by compiling the
10564 		* chameleon for every distinct including targetNamespace; thus
10565 		* not performant at the moment.
10566 		* TODO: Check when the namespace in wildcards for chameleons
10567 		* needs to be converted: before we built wildcard intersections
10568 		* or after.
10569 		*   Answer: after!
10570 		*/
10571 		chamel = xmlSchemaGetChameleonSchemaBucket(pctxt,
10572 		    schemaLocation, sourceTargetNamespace);
10573 		if (chamel != NULL) {
10574 		    /* A fitting chameleon was already parsed; NOP. */
10575 		    relation->bucket = chamel;
10576 		    goto exit;
10577 		}
10578 		/*
10579 		* We need to parse the chameleon again for a different
10580 		* targetNamespace.
10581 		* CHAMELEON TODO: Optimize this by only parsing the
10582 		* chameleon once, and then copying the components to
10583 		* the new targetNamespace.
10584 		*/
10585 		bkt = NULL;
10586 	    } else {
10587 		relation->bucket = bkt;
10588 		goto exit;
10589 	    }
10590 	}
10591     }
10592     if ((bkt != NULL) && (bkt->doc != NULL)) {
10593 	PERROR_INT("xmlSchemaAddSchemaDoc",
10594 	    "trying to load a schema doc, but a doc is already "
10595 	    "assigned to the schema bucket");
10596 	goto exit_failure;
10597     }
10598 
10599 doc_load:
10600     /*
10601     * Load the document.
10602     */
10603     if (schemaDoc != NULL) {
10604 	doc = schemaDoc;
10605 	/* Don' free this one, since it was provided by the caller. */
10606 	preserveDoc = 1;
10607 	/* TODO: Does the context or the doc hold the location? */
10608 	if (schemaDoc->URL != NULL)
10609 	    schemaLocation = xmlDictLookup(pctxt->dict,
10610 		schemaDoc->URL, -1);
10611         else
10612 	    schemaLocation = BAD_CAST "in_memory_buffer";
10613     } else if ((schemaLocation != NULL) || (schemaBuffer != NULL)) {
10614 	xmlParserCtxtPtr parserCtxt;
10615 
10616 	parserCtxt = xmlNewParserCtxt();
10617 	if (parserCtxt == NULL) {
10618 	    xmlSchemaPErrMemory(NULL, "xmlSchemaGetDoc, "
10619 		"allocating a parser context", NULL);
10620 	    goto exit_failure;
10621 	}
10622 	if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
10623 	    /*
10624 	    * TODO: Do we have to burden the schema parser dict with all
10625 	    * the content of the schema doc?
10626 	    */
10627 	    xmlDictFree(parserCtxt->dict);
10628 	    parserCtxt->dict = pctxt->dict;
10629 	    xmlDictReference(parserCtxt->dict);
10630 	}
10631 	if (schemaLocation != NULL) {
10632 	    /* Parse from file. */
10633 	    doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
10634 		NULL, SCHEMAS_PARSE_OPTIONS);
10635 	} else if (schemaBuffer != NULL) {
10636 	    /* Parse from memory buffer. */
10637 	    doc = xmlCtxtReadMemory(parserCtxt, schemaBuffer, schemaBufferLen,
10638 		NULL, NULL, SCHEMAS_PARSE_OPTIONS);
10639 	    schemaLocation = BAD_CAST "in_memory_buffer";
10640 	    if (doc != NULL)
10641 		doc->URL = xmlStrdup(schemaLocation);
10642 	}
10643 	/*
10644 	* For <import>:
10645 	* 2.1 The referent is (a fragment of) a resource which is an
10646 	* XML document (see clause 1.1), which in turn corresponds to
10647 	* a <schema> element information item in a well-formed information
10648 	* set, which in turn corresponds to a valid schema.
10649 	* TODO: (2.1) fragments of XML documents are not supported.
10650 	*
10651 	* 2.2 The referent is a <schema> element information item in
10652 	* a well-formed information set, which in turn corresponds
10653 	* to a valid schema.
10654 	* TODO: (2.2) is not supported.
10655 	*/
10656 	if (doc == NULL) {
10657 	    xmlErrorPtr lerr;
10658 	    lerr = xmlGetLastError();
10659 	    /*
10660 	    * Check if this a parser error, or if the document could
10661 	    * just not be located.
10662 	    * TODO: Try to find specific error codes to react only on
10663 	    * localisation failures.
10664 	    */
10665 	    if ((lerr == NULL) || (lerr->domain != XML_FROM_IO)) {
10666 		/*
10667 		* We assume a parser error here.
10668 		*/
10669 		located = 1;
10670 		/* TODO: Error code ?? */
10671 		res = XML_SCHEMAP_SRC_IMPORT_2_1;
10672 		xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10673 		    invokingNode, NULL,
10674 		    "Failed to parse the XML resource '%s'",
10675 		    schemaLocation, NULL);
10676 	    }
10677 	}
10678 	xmlFreeParserCtxt(parserCtxt);
10679 	if ((doc == NULL) && located)
10680 	    goto exit_error;
10681     } else {
10682 	xmlSchemaPErr(pctxt, NULL,
10683 	    XML_SCHEMAP_NOTHING_TO_PARSE,
10684 	    "No information for parsing was provided with the "
10685 	    "given schema parser context.\n",
10686 	    NULL, NULL);
10687 	goto exit_failure;
10688     }
10689     /*
10690     * Preprocess the document.
10691     */
10692     if (doc != NULL) {
10693 	xmlNodePtr docElem = NULL;
10694 
10695 	located = 1;
10696 	docElem = xmlDocGetRootElement(doc);
10697 	if (docElem == NULL) {
10698 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOROOT,
10699 		invokingNode, NULL,
10700 		"The document '%s' has no document element",
10701 		schemaLocation, NULL);
10702 	    goto exit_error;
10703 	}
10704 	/*
10705 	* Remove all the blank text nodes.
10706 	*/
10707 	xmlSchemaCleanupDoc(pctxt, docElem);
10708 	/*
10709 	* Check the schema's top level element.
10710 	*/
10711 	if (!IS_SCHEMA(docElem, "schema")) {
10712 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOT_SCHEMA,
10713 		invokingNode, NULL,
10714 		"The XML document '%s' is not a schema document",
10715 		schemaLocation, NULL);
10716 	    goto exit_error;
10717 	}
10718 	/*
10719 	* Note that we don't apply a type check for the
10720 	* targetNamespace value here.
10721 	*/
10722 	targetNamespace = xmlSchemaGetProp(pctxt, docElem,
10723 	    "targetNamespace");
10724     }
10725 
10726 /* after_doc_loading: */
10727     if ((bkt == NULL) && located) {
10728 	/* Only create a bucket if the schema was located. */
10729         bkt = xmlSchemaBucketCreate(pctxt, type,
10730 	    targetNamespace);
10731 	if (bkt == NULL)
10732 	    goto exit_failure;
10733     }
10734     if (bkt != NULL) {
10735 	bkt->schemaLocation = schemaLocation;
10736 	bkt->located = located;
10737 	if (doc != NULL) {
10738 	    bkt->doc = doc;
10739 	    bkt->targetNamespace = targetNamespace;
10740 	    bkt->origTargetNamespace = targetNamespace;
10741 	    if (preserveDoc)
10742 		bkt->preserveDoc = 1;
10743 	}
10744 	if (WXS_IS_BUCKET_IMPMAIN(type))
10745 	    bkt->imported++;
10746 	    /*
10747 	    * Add it to the graph of schemas.
10748 	    */
10749 	if (relation != NULL)
10750 	    relation->bucket = bkt;
10751     }
10752 
10753 exit:
10754     /*
10755     * Return the bucket explicitly; this is needed for the
10756     * main schema.
10757     */
10758     if (bucket != NULL)
10759 	*bucket = bkt;
10760     return (0);
10761 
10762 exit_error:
10763     if ((doc != NULL) && (! preserveDoc)) {
10764 	xmlFreeDoc(doc);
10765 	if (bkt != NULL)
10766 	    bkt->doc = NULL;
10767     }
10768     return(pctxt->err);
10769 
10770 exit_failure:
10771     if ((doc != NULL) && (! preserveDoc)) {
10772 	xmlFreeDoc(doc);
10773 	if (bkt != NULL)
10774 	    bkt->doc = NULL;
10775     }
10776     return (-1);
10777 }
10778 
10779 /**
10780  * xmlSchemaParseImport:
10781  * @ctxt:  a schema validation context
10782  * @schema:  the schema being built
10783  * @node:  a subtree containing XML Schema information
10784  *
10785  * parse a XML schema Import definition
10786  * *WARNING* this interface is highly subject to change
10787  *
10788  * Returns 0 in case of success, a positive error code if
10789  * not valid and -1 in case of an internal error.
10790  */
10791 static int
xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)10792 xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
10793                      xmlNodePtr node)
10794 {
10795     xmlNodePtr child;
10796     const xmlChar *namespaceName = NULL, *schemaLocation = NULL;
10797     const xmlChar *thisTargetNamespace;
10798     xmlAttrPtr attr;
10799     int ret = 0;
10800     xmlSchemaBucketPtr bucket = NULL;
10801 
10802     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10803         return (-1);
10804 
10805     /*
10806     * Check for illegal attributes.
10807     */
10808     attr = node->properties;
10809     while (attr != NULL) {
10810 	if (attr->ns == NULL) {
10811 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10812 		(!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
10813 		(!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10814 		xmlSchemaPIllegalAttrErr(pctxt,
10815 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10816 	    }
10817 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10818 	    xmlSchemaPIllegalAttrErr(pctxt,
10819 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10820 	}
10821 	attr = attr->next;
10822     }
10823     /*
10824     * Extract and validate attributes.
10825     */
10826     if (xmlSchemaPValAttr(pctxt, NULL, node,
10827 	"namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10828 	&namespaceName) != 0) {
10829 	xmlSchemaPSimpleTypeErr(pctxt,
10830 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10831 	    NULL, node,
10832 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10833 	    NULL, namespaceName, NULL, NULL, NULL);
10834 	return (pctxt->err);
10835     }
10836 
10837     if (xmlSchemaPValAttr(pctxt, NULL, node,
10838 	"schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10839 	&schemaLocation) != 0) {
10840 	xmlSchemaPSimpleTypeErr(pctxt,
10841 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10842 	    NULL, node,
10843 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10844 	    NULL, schemaLocation, NULL, NULL, NULL);
10845 	return (pctxt->err);
10846     }
10847     /*
10848     * And now for the children...
10849     */
10850     child = node->children;
10851     if (IS_SCHEMA(child, "annotation")) {
10852         /*
10853          * the annotation here is simply discarded ...
10854 	 * TODO: really?
10855          */
10856         child = child->next;
10857     }
10858     if (child != NULL) {
10859 	xmlSchemaPContentErr(pctxt,
10860 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10861 	    NULL, node, child, NULL,
10862 	    "(annotation?)");
10863     }
10864     /*
10865     * Apply additional constraints.
10866     *
10867     * Note that it is important to use the original @targetNamespace
10868     * (or none at all), to rule out imports of schemas _with_ a
10869     * @targetNamespace if the importing schema is a chameleon schema
10870     * (with no @targetNamespace).
10871     */
10872     thisTargetNamespace = WXS_BUCKET(pctxt)->origTargetNamespace;
10873     if (namespaceName != NULL) {
10874 	/*
10875 	* 1.1 If the namespace [attribute] is present, then its `actual value`
10876 	* must not match the `actual value` of the enclosing <schema>'s
10877 	* targetNamespace [attribute].
10878 	*/
10879 	if (xmlStrEqual(thisTargetNamespace, namespaceName)) {
10880 	    xmlSchemaPCustomErr(pctxt,
10881 		XML_SCHEMAP_SRC_IMPORT_1_1,
10882 		NULL, node,
10883 		"The value of the attribute 'namespace' must not match "
10884 		"the target namespace '%s' of the importing schema",
10885 		thisTargetNamespace);
10886 	    return (pctxt->err);
10887 	}
10888     } else {
10889 	/*
10890 	* 1.2 If the namespace [attribute] is not present, then the enclosing
10891 	* <schema> must have a targetNamespace [attribute].
10892 	*/
10893 	if (thisTargetNamespace == NULL) {
10894 	    xmlSchemaPCustomErr(pctxt,
10895 		XML_SCHEMAP_SRC_IMPORT_1_2,
10896 		NULL, node,
10897 		"The attribute 'namespace' must be existent if "
10898 		"the importing schema has no target namespace",
10899 		NULL);
10900 	    return (pctxt->err);
10901 	}
10902     }
10903     /*
10904     * Locate and acquire the schema document.
10905     */
10906     if (schemaLocation != NULL)
10907 	schemaLocation = xmlSchemaBuildAbsoluteURI(pctxt->dict,
10908 	    schemaLocation, node);
10909     ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
10910 	schemaLocation, NULL, NULL, 0, node, thisTargetNamespace,
10911 	namespaceName, &bucket);
10912 
10913     if (ret != 0)
10914 	return(ret);
10915 
10916     /*
10917     * For <import>: "It is *not* an error for the application
10918     * schema reference strategy to fail."
10919     * So just don't parse if no schema document was found.
10920     * Note that we will get no bucket if the schema could not be
10921     * located or if there was no schemaLocation.
10922     */
10923     if ((bucket == NULL) && (schemaLocation != NULL)) {
10924 	xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10925 	    XML_SCHEMAP_WARN_UNLOCATED_SCHEMA,
10926 	    node, NULL,
10927 	    "Failed to locate a schema at location '%s'. "
10928 	    "Skipping the import", schemaLocation, NULL, NULL);
10929     }
10930 
10931     if ((bucket != NULL) && CAN_PARSE_SCHEMA(bucket)) {
10932 	ret = xmlSchemaParseNewDoc(pctxt, schema, bucket);
10933     }
10934 
10935     return (ret);
10936 }
10937 
10938 static int
xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlChar ** schemaLocation,int type)10939 xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,
10940 				     xmlSchemaPtr schema,
10941 				     xmlNodePtr node,
10942 				     xmlChar **schemaLocation,
10943 				     int type)
10944 {
10945     xmlAttrPtr attr;
10946 
10947     if ((pctxt == NULL) || (schema == NULL) || (node == NULL) ||
10948 	(schemaLocation == NULL))
10949         return (-1);
10950 
10951     *schemaLocation = NULL;
10952     /*
10953     * Check for illegal attributes.
10954     * Applies for both <include> and <redefine>.
10955     */
10956     attr = node->properties;
10957     while (attr != NULL) {
10958 	if (attr->ns == NULL) {
10959 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10960 		(!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10961 		xmlSchemaPIllegalAttrErr(pctxt,
10962 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10963 	    }
10964 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10965 	    xmlSchemaPIllegalAttrErr(pctxt,
10966 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10967 	}
10968 	attr = attr->next;
10969     }
10970     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
10971     /*
10972     * Preliminary step, extract the URI-Reference and make an URI
10973     * from the base.
10974     */
10975     /*
10976     * Attribute "schemaLocation" is mandatory.
10977     */
10978     attr = xmlSchemaGetPropNode(node, "schemaLocation");
10979     if (attr != NULL) {
10980         xmlChar *base = NULL;
10981         xmlChar *uri = NULL;
10982 
10983 	if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
10984 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10985 	    (const xmlChar **) schemaLocation) != 0)
10986 	    goto exit_error;
10987 	base = xmlNodeGetBase(node->doc, node);
10988 	if (base == NULL) {
10989 	    uri = xmlBuildURI(*schemaLocation, node->doc->URL);
10990 	} else {
10991 	    uri = xmlBuildURI(*schemaLocation, base);
10992 	    xmlFree(base);
10993 	}
10994 	if (uri == NULL) {
10995 	    PERROR_INT("xmlSchemaParseIncludeOrRedefine",
10996 		"could not build an URI from the schemaLocation")
10997 	    goto exit_failure;
10998 	}
10999 	(*schemaLocation) = (xmlChar *) xmlDictLookup(pctxt->dict, uri, -1);
11000 	xmlFree(uri);
11001     } else {
11002 	xmlSchemaPMissingAttrErr(pctxt,
11003 	    XML_SCHEMAP_S4S_ATTR_MISSING,
11004 	    NULL, node, "schemaLocation", NULL);
11005 	goto exit_error;
11006     }
11007     /*
11008     * Report self-inclusion and self-redefinition.
11009     */
11010     if (xmlStrEqual(*schemaLocation, pctxt->URL)) {
11011 	if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11012 	    xmlSchemaPCustomErr(pctxt,
11013 		XML_SCHEMAP_SRC_REDEFINE,
11014 		NULL, node,
11015 		"The schema document '%s' cannot redefine itself.",
11016 		*schemaLocation);
11017 	} else {
11018 	    xmlSchemaPCustomErr(pctxt,
11019 		XML_SCHEMAP_SRC_INCLUDE,
11020 		NULL, node,
11021 		"The schema document '%s' cannot include itself.",
11022 		*schemaLocation);
11023 	}
11024 	goto exit_error;
11025     }
11026 
11027     return(0);
11028 exit_error:
11029     return(pctxt->err);
11030 exit_failure:
11031     return(-1);
11032 }
11033 
11034 static int
xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node,int type)11035 xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,
11036 				xmlSchemaPtr schema,
11037 				xmlNodePtr node,
11038 				int type)
11039 {
11040     xmlNodePtr child = NULL;
11041     const xmlChar *schemaLocation = NULL;
11042     int res = 0; /* hasRedefinitions = 0 */
11043     int isChameleon = 0, wasChameleon = 0;
11044     xmlSchemaBucketPtr bucket = NULL;
11045 
11046     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
11047         return (-1);
11048 
11049     /*
11050     * Parse attributes. Note that the returned schemaLocation will
11051     * be already converted to an absolute URI.
11052     */
11053     res = xmlSchemaParseIncludeOrRedefineAttrs(pctxt, schema,
11054 	node, (xmlChar **) (&schemaLocation), type);
11055     if (res != 0)
11056 	return(res);
11057     /*
11058     * Load and add the schema document.
11059     */
11060     res = xmlSchemaAddSchemaDoc(pctxt, type, schemaLocation, NULL,
11061 	NULL, 0, node, pctxt->targetNamespace, NULL, &bucket);
11062     if (res != 0)
11063 	return(res);
11064     /*
11065     * If we get no schema bucket back, then this means that the schema
11066     * document could not be located or was broken XML or was not
11067     * a schema document.
11068     */
11069     if ((bucket == NULL) || (bucket->doc == NULL)) {
11070 	if (type == XML_SCHEMA_SCHEMA_INCLUDE) {
11071 	    /*
11072 	    * WARNING for <include>:
11073 	    * We will raise an error if the schema cannot be located
11074 	    * for inclusions, since the that was the feedback from the
11075 	    * schema people. I.e. the following spec piece will *not* be
11076 	    * satisfied:
11077 	    * SPEC src-include: "It is not an error for the `actual value` of the
11078 	    * schemaLocation [attribute] to fail to resolve it all, in which
11079 	    * case no corresponding inclusion is performed.
11080 	    * So do we need a warning report here?"
11081 	    */
11082 	    res = XML_SCHEMAP_SRC_INCLUDE;
11083 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
11084 		node, NULL,
11085 		"Failed to load the document '%s' for inclusion",
11086 		schemaLocation, NULL);
11087 	} else {
11088 	    /*
11089 	    * NOTE: This was changed to raise an error even if no redefinitions
11090 	    * are specified.
11091 	    *
11092 	    * SPEC src-redefine (1)
11093 	    * "If there are any element information items among the [children]
11094 	    * other than <annotation> then the `actual value` of the
11095 	    * schemaLocation [attribute] must successfully resolve."
11096 	    * TODO: Ask the WG if a the location has always to resolve
11097 	    * here as well!
11098 	    */
11099 	    res = XML_SCHEMAP_SRC_REDEFINE;
11100 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
11101 		node, NULL,
11102 		"Failed to load the document '%s' for redefinition",
11103 		schemaLocation, NULL);
11104 	}
11105     } else {
11106 	/*
11107 	* Check targetNamespace sanity before parsing the new schema.
11108 	* TODO: Note that we won't check further content if the
11109 	* targetNamespace was bad.
11110 	*/
11111 	if (bucket->origTargetNamespace != NULL) {
11112 	    /*
11113 	    * SPEC src-include (2.1)
11114 	    * "SII has a targetNamespace [attribute], and its `actual
11115 	    * value` is identical to the `actual value` of the targetNamespace
11116 	    * [attribute] of SII' (which must have such an [attribute])."
11117 	    */
11118 	    if (pctxt->targetNamespace == NULL) {
11119 		xmlSchemaCustomErr(ACTXT_CAST pctxt,
11120 		    XML_SCHEMAP_SRC_INCLUDE,
11121 		    node, NULL,
11122 		    "The target namespace of the included/redefined schema "
11123 		    "'%s' has to be absent, since the including/redefining "
11124 		    "schema has no target namespace",
11125 		    schemaLocation, NULL);
11126 		goto exit_error;
11127 	    } else if (!xmlStrEqual(bucket->origTargetNamespace,
11128 		pctxt->targetNamespace)) {
11129 		/* TODO: Change error function. */
11130 		xmlSchemaPCustomErrExt(pctxt,
11131 		    XML_SCHEMAP_SRC_INCLUDE,
11132 		    NULL, node,
11133 		    "The target namespace '%s' of the included/redefined "
11134 		    "schema '%s' differs from '%s' of the "
11135 		    "including/redefining schema",
11136 		    bucket->origTargetNamespace, schemaLocation,
11137 		    pctxt->targetNamespace);
11138 		goto exit_error;
11139 	    }
11140 	} else if (pctxt->targetNamespace != NULL) {
11141 	    /*
11142 	    * Chameleons: the original target namespace will
11143 	    * differ from the resulting namespace.
11144 	    */
11145 	    isChameleon = 1;
11146 	    if (bucket->parsed &&
11147 		bucket->origTargetNamespace != NULL) {
11148 		xmlSchemaCustomErr(ACTXT_CAST pctxt,
11149 		    XML_SCHEMAP_SRC_INCLUDE,
11150 		    node, NULL,
11151 		    "The target namespace of the included/redefined schema "
11152 		    "'%s' has to be absent or the same as the "
11153 		    "including/redefining schema's target namespace",
11154 		    schemaLocation, NULL);
11155 		goto exit_error;
11156 	    }
11157 	    bucket->targetNamespace = pctxt->targetNamespace;
11158 	}
11159     }
11160     /*
11161     * Parse the schema.
11162     */
11163     if (bucket && (!bucket->parsed) && (bucket->doc != NULL)) {
11164 	if (isChameleon) {
11165 	    /* TODO: Get rid of this flag on the schema itself. */
11166 	    if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
11167 		schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11168 	    } else
11169 		wasChameleon = 1;
11170 	}
11171 	xmlSchemaParseNewDoc(pctxt, schema, bucket);
11172 	/* Restore chameleon flag. */
11173 	if (isChameleon && (!wasChameleon))
11174 	    schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11175     }
11176     /*
11177     * And now for the children...
11178     */
11179     child = node->children;
11180     if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11181 	/*
11182 	* Parse (simpleType | complexType | group | attributeGroup))*
11183 	*/
11184 	pctxt->redefined = bucket;
11185 	/*
11186 	* How to proceed if the redefined schema was not located?
11187 	*/
11188 	pctxt->isRedefine = 1;
11189 	while (IS_SCHEMA(child, "annotation") ||
11190 	    IS_SCHEMA(child, "simpleType") ||
11191 	    IS_SCHEMA(child, "complexType") ||
11192 	    IS_SCHEMA(child, "group") ||
11193 	    IS_SCHEMA(child, "attributeGroup")) {
11194 	    if (IS_SCHEMA(child, "annotation")) {
11195 		/*
11196 		* TODO: discard or not?
11197 		*/
11198 	    } else if (IS_SCHEMA(child, "simpleType")) {
11199 		xmlSchemaParseSimpleType(pctxt, schema, child, 1);
11200 	    } else if (IS_SCHEMA(child, "complexType")) {
11201 		xmlSchemaParseComplexType(pctxt, schema, child, 1);
11202 		/* hasRedefinitions = 1; */
11203 	    } else if (IS_SCHEMA(child, "group")) {
11204 		/* hasRedefinitions = 1; */
11205 		xmlSchemaParseModelGroupDefinition(pctxt,
11206 		    schema, child);
11207 	    } else if (IS_SCHEMA(child, "attributeGroup")) {
11208 		/* hasRedefinitions = 1; */
11209 		xmlSchemaParseAttributeGroupDefinition(pctxt, schema,
11210 		    child);
11211 	    }
11212 	    child = child->next;
11213 	}
11214 	pctxt->redefined = NULL;
11215 	pctxt->isRedefine = 0;
11216     } else {
11217 	if (IS_SCHEMA(child, "annotation")) {
11218 	    /*
11219 	    * TODO: discard or not?
11220 	    */
11221 	    child = child->next;
11222 	}
11223     }
11224     if (child != NULL) {
11225 	res = XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED;
11226 	if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11227 	    xmlSchemaPContentErr(pctxt, res,
11228 		NULL, node, child, NULL,
11229 		"(annotation | (simpleType | complexType | group | attributeGroup))*");
11230 	} else {
11231 	     xmlSchemaPContentErr(pctxt, res,
11232 		NULL, node, child, NULL,
11233 		"(annotation?)");
11234 	}
11235     }
11236     return(res);
11237 
11238 exit_error:
11239     return(pctxt->err);
11240 }
11241 
11242 static int
xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)11243 xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11244                        xmlNodePtr node)
11245 {
11246     int res;
11247 #ifndef ENABLE_REDEFINE
11248     TODO
11249     return(0);
11250 #endif
11251     res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11252 	XML_SCHEMA_SCHEMA_REDEFINE);
11253     if (res != 0)
11254 	return(res);
11255     return(0);
11256 }
11257 
11258 static int
xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)11259 xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11260                        xmlNodePtr node)
11261 {
11262     int res;
11263 
11264     res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11265 	XML_SCHEMA_SCHEMA_INCLUDE);
11266     if (res != 0)
11267 	return(res);
11268     return(0);
11269 }
11270 
11271 /**
11272  * xmlSchemaParseModelGroup:
11273  * @ctxt:  a schema validation context
11274  * @schema:  the schema being built
11275  * @node:  a subtree containing XML Schema information
11276  * @type: the "compositor" type
11277  * @particleNeeded: if a a model group with a particle
11278  *
11279  * parse a XML schema Sequence definition.
11280  * Applies parts of:
11281  *   Schema Representation Constraint:
11282  *     Redefinition Constraints and Semantics (src-redefine)
11283  *     (6.1), (6.1.1), (6.1.2)
11284  *
11285  *   Schema Component Constraint:
11286  *     All Group Limited (cos-all-limited) (2)
11287  *     TODO: Actually this should go to component-level checks,
11288  *     but is done here due to performance. Move it to an other layer
11289  *     is schema construction via an API is implemented.
11290  *
11291  * *WARNING* this interface is highly subject to change
11292  *
11293  * Returns -1 in case of error, 0 if the declaration is improper and
11294  *         1 in case of success.
11295  */
11296 static xmlSchemaTreeItemPtr
xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlSchemaTypeType type,int withParticle)11297 xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11298 			 xmlNodePtr node, xmlSchemaTypeType type,
11299 			 int withParticle)
11300 {
11301     xmlSchemaModelGroupPtr item;
11302     xmlSchemaParticlePtr particle = NULL;
11303     xmlNodePtr child = NULL;
11304     xmlAttrPtr attr;
11305     int min = 1, max = 1, isElemRef, hasRefs = 0;
11306 
11307     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11308         return (NULL);
11309     /*
11310     * Create a model group with the given compositor.
11311     */
11312     item = xmlSchemaAddModelGroup(ctxt, schema, type, node);
11313     if (item == NULL)
11314 	return (NULL);
11315 
11316     if (withParticle) {
11317 	if (type == XML_SCHEMA_TYPE_ALL) {
11318 	    min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
11319 	    max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
11320 	} else {
11321 	    /* choice + sequence */
11322 	    min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
11323 	    max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
11324 		"(xs:nonNegativeInteger | unbounded)");
11325 	}
11326 	xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
11327 	/*
11328 	* Create a particle
11329 	*/
11330 	particle = xmlSchemaAddParticle(ctxt, node, min, max);
11331 	if (particle == NULL)
11332 	    return (NULL);
11333 	particle->children = (xmlSchemaTreeItemPtr) item;
11334 	/*
11335 	* Check for illegal attributes.
11336 	*/
11337 	attr = node->properties;
11338 	while (attr != NULL) {
11339 	    if (attr->ns == NULL) {
11340 		if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11341 		    (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
11342 		    (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
11343 		    xmlSchemaPIllegalAttrErr(ctxt,
11344 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11345 		}
11346 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11347 		xmlSchemaPIllegalAttrErr(ctxt,
11348 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11349 	    }
11350 	    attr = attr->next;
11351 	}
11352     } else {
11353 	/*
11354 	* Check for illegal attributes.
11355 	*/
11356 	attr = node->properties;
11357 	while (attr != NULL) {
11358 	    if (attr->ns == NULL) {
11359 		if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
11360 		    xmlSchemaPIllegalAttrErr(ctxt,
11361 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11362 		}
11363 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11364 		xmlSchemaPIllegalAttrErr(ctxt,
11365 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11366 	    }
11367 	    attr = attr->next;
11368 	}
11369     }
11370 
11371     /*
11372     * Extract and validate attributes.
11373     */
11374     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11375     /*
11376     * And now for the children...
11377     */
11378     child = node->children;
11379     if (IS_SCHEMA(child, "annotation")) {
11380         item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
11381         child = child->next;
11382     }
11383     if (type == XML_SCHEMA_TYPE_ALL) {
11384 	xmlSchemaParticlePtr part, last = NULL;
11385 
11386 	while (IS_SCHEMA(child, "element")) {
11387 	    part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
11388 		schema, child, &isElemRef, 0);
11389 	    /*
11390 	    * SPEC cos-all-limited (2)
11391 	    * "The {max occurs} of all the particles in the {particles}
11392 	    * of the ('all') group must be 0 or 1.
11393 	    */
11394 	    if (part != NULL) {
11395 		if (isElemRef)
11396 		    hasRefs++;
11397 		if (part->minOccurs > 1) {
11398 		    xmlSchemaPCustomErr(ctxt,
11399 			XML_SCHEMAP_COS_ALL_LIMITED,
11400 			NULL, child,
11401 			"Invalid value for minOccurs (must be 0 or 1)",
11402 			NULL);
11403 		    /* Reset to 1. */
11404 		    part->minOccurs = 1;
11405 		}
11406 		if (part->maxOccurs > 1) {
11407 		    xmlSchemaPCustomErr(ctxt,
11408 			XML_SCHEMAP_COS_ALL_LIMITED,
11409 			NULL, child,
11410 			"Invalid value for maxOccurs (must be 0 or 1)",
11411 			NULL);
11412 		    /* Reset to 1. */
11413 		    part->maxOccurs = 1;
11414 		}
11415 		if (last == NULL)
11416 		    item->children = (xmlSchemaTreeItemPtr) part;
11417 		else
11418 		    last->next = (xmlSchemaTreeItemPtr) part;
11419 		last = part;
11420 	    }
11421 	    child = child->next;
11422 	}
11423 	if (child != NULL) {
11424 	    xmlSchemaPContentErr(ctxt,
11425 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11426 		NULL, node, child, NULL,
11427 		"(annotation?, (annotation?, element*)");
11428 	}
11429     } else {
11430 	/* choice + sequence */
11431 	xmlSchemaTreeItemPtr part = NULL, last = NULL;
11432 
11433 	while ((IS_SCHEMA(child, "element")) ||
11434 	    (IS_SCHEMA(child, "group")) ||
11435 	    (IS_SCHEMA(child, "any")) ||
11436 	    (IS_SCHEMA(child, "choice")) ||
11437 	    (IS_SCHEMA(child, "sequence"))) {
11438 
11439 	    if (IS_SCHEMA(child, "element")) {
11440 		part = (xmlSchemaTreeItemPtr)
11441 		    xmlSchemaParseElement(ctxt, schema, child, &isElemRef, 0);
11442 		if (part && isElemRef)
11443 		    hasRefs++;
11444 	    } else if (IS_SCHEMA(child, "group")) {
11445 		part =
11446 		    xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11447 		if (part != NULL)
11448 		    hasRefs++;
11449 		/*
11450 		* Handle redefinitions.
11451 		*/
11452 		if (ctxt->isRedefine && ctxt->redef &&
11453 		    (ctxt->redef->item->type == XML_SCHEMA_TYPE_GROUP) &&
11454 		    part && part->children)
11455 		{
11456 		    if ((xmlSchemaGetQNameRefName(part->children) ==
11457 			    ctxt->redef->refName) &&
11458 			(xmlSchemaGetQNameRefTargetNs(part->children) ==
11459 			    ctxt->redef->refTargetNs))
11460 		    {
11461 			/*
11462 			* SPEC src-redefine:
11463 			* (6.1) "If it has a <group> among its contents at
11464 			* some level the `actual value` of whose ref
11465 			* [attribute] is the same as the `actual value` of
11466 			* its own name attribute plus target namespace, then
11467 			* all of the following must be true:"
11468 			* (6.1.1) "It must have exactly one such group."
11469 			*/
11470 			if (ctxt->redefCounter != 0) {
11471 			    xmlChar *str = NULL;
11472 
11473 			    xmlSchemaCustomErr(ACTXT_CAST ctxt,
11474 				XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11475 				"The redefining model group definition "
11476 				"'%s' must not contain more than one "
11477 				"reference to the redefined definition",
11478 				xmlSchemaFormatQName(&str,
11479 				    ctxt->redef->refTargetNs,
11480 				    ctxt->redef->refName),
11481 				NULL);
11482 			    FREE_AND_NULL(str)
11483 			    part = NULL;
11484 			} else if (((WXS_PARTICLE(part))->minOccurs != 1) ||
11485 			    ((WXS_PARTICLE(part))->maxOccurs != 1))
11486 			{
11487 			    xmlChar *str = NULL;
11488 			    /*
11489 			    * SPEC src-redefine:
11490 			    * (6.1.2) "The `actual value` of both that
11491 			    * group's minOccurs and maxOccurs [attribute]
11492 			    * must be 1 (or `absent`).
11493 			    */
11494 			    xmlSchemaCustomErr(ACTXT_CAST ctxt,
11495 				XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11496 				"The redefining model group definition "
11497 				"'%s' must not contain a reference to the "
11498 				"redefined definition with a "
11499 				"maxOccurs/minOccurs other than 1",
11500 				xmlSchemaFormatQName(&str,
11501 				    ctxt->redef->refTargetNs,
11502 				    ctxt->redef->refName),
11503 				NULL);
11504 			    FREE_AND_NULL(str)
11505 			    part = NULL;
11506 			}
11507 			ctxt->redef->reference = WXS_BASIC_CAST part;
11508 			ctxt->redefCounter++;
11509 		    }
11510 		}
11511 	    } else if (IS_SCHEMA(child, "any")) {
11512 		part = (xmlSchemaTreeItemPtr)
11513 		    xmlSchemaParseAny(ctxt, schema, child);
11514 	    } else if (IS_SCHEMA(child, "choice")) {
11515 		part = xmlSchemaParseModelGroup(ctxt, schema, child,
11516 		    XML_SCHEMA_TYPE_CHOICE, 1);
11517 	    } else if (IS_SCHEMA(child, "sequence")) {
11518 		part = xmlSchemaParseModelGroup(ctxt, schema, child,
11519 		    XML_SCHEMA_TYPE_SEQUENCE, 1);
11520 	    }
11521 	    if (part != NULL) {
11522 		if (last == NULL)
11523 		    item->children = part;
11524 		else
11525 		    last->next = part;
11526 		last = part;
11527 	    }
11528 	    child = child->next;
11529 	}
11530 	if (child != NULL) {
11531 	    xmlSchemaPContentErr(ctxt,
11532 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11533 		NULL, node, child, NULL,
11534 		"(annotation?, (element | group | choice | sequence | any)*)");
11535 	}
11536     }
11537     if ((max == 0) && (min == 0))
11538 	return (NULL);
11539     if (hasRefs) {
11540 	/*
11541 	* We need to resolve references.
11542 	*/
11543 	WXS_ADD_PENDING(ctxt, item);
11544     }
11545     if (withParticle)
11546 	return ((xmlSchemaTreeItemPtr) particle);
11547     else
11548 	return ((xmlSchemaTreeItemPtr) item);
11549 }
11550 
11551 /**
11552  * xmlSchemaParseRestriction:
11553  * @ctxt:  a schema validation context
11554  * @schema:  the schema being built
11555  * @node:  a subtree containing XML Schema information
11556  *
11557  * parse a XML schema Restriction definition
11558  * *WARNING* this interface is highly subject to change
11559  *
11560  * Returns the type definition or NULL in case of error
11561  */
11562 static xmlSchemaTypePtr
xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlSchemaTypeType parentType)11563 xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11564                           xmlNodePtr node, xmlSchemaTypeType parentType)
11565 {
11566     xmlSchemaTypePtr type;
11567     xmlNodePtr child = NULL;
11568     xmlAttrPtr attr;
11569 
11570     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11571         return (NULL);
11572     /* Not a component, don't create it. */
11573     type = ctxt->ctxtType;
11574     type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
11575 
11576     /*
11577     * Check for illegal attributes.
11578     */
11579     attr = node->properties;
11580     while (attr != NULL) {
11581 	if (attr->ns == NULL) {
11582 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11583 		(!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11584 		xmlSchemaPIllegalAttrErr(ctxt,
11585 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11586 	    }
11587 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11588 	    xmlSchemaPIllegalAttrErr(ctxt,
11589 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11590 	}
11591 	attr = attr->next;
11592     }
11593     /*
11594     * Extract and validate attributes.
11595     */
11596     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11597     /*
11598     * Attribute
11599     */
11600     /*
11601     * Extract the base type. The "base" attribute is mandatory if inside
11602     * a complex type or if redefining.
11603     *
11604     * SPEC (1.2) "...otherwise (<restriction> has no <simpleType> "
11605     * among its [children]), the simple type definition which is
11606     * the {content type} of the type definition `resolved` to by
11607     * the `actual value` of the base [attribute]"
11608     */
11609     if (xmlSchemaPValAttrQName(ctxt, schema, NULL, node, "base",
11610 	&(type->baseNs), &(type->base)) == 0)
11611     {
11612 	if ((type->base == NULL) && (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
11613 	    xmlSchemaPMissingAttrErr(ctxt,
11614 		XML_SCHEMAP_S4S_ATTR_MISSING,
11615 		NULL, node, "base", NULL);
11616 	} else if ((ctxt->isRedefine) &&
11617 	    (type->flags & XML_SCHEMAS_TYPE_GLOBAL))
11618 	{
11619 	    if (type->base == NULL) {
11620 		xmlSchemaPMissingAttrErr(ctxt,
11621 		    XML_SCHEMAP_S4S_ATTR_MISSING,
11622 		    NULL, node, "base", NULL);
11623 	    } else if ((! xmlStrEqual(type->base, type->name)) ||
11624 		(! xmlStrEqual(type->baseNs, type->targetNamespace)))
11625 	    {
11626 		xmlChar *str1 = NULL, *str2 = NULL;
11627 		/*
11628 		* REDEFINE: SPEC src-redefine (5)
11629 		* "Within the [children], each <simpleType> must have a
11630 		* <restriction> among its [children] ... the `actual value` of
11631 		* whose base [attribute] must be the same as the `actual value`
11632 		* of its own name attribute plus target namespace;"
11633 		*/
11634 		xmlSchemaPCustomErrExt(ctxt, XML_SCHEMAP_SRC_REDEFINE,
11635 		    NULL, node, "This is a redefinition, but the QName "
11636 		    "value '%s' of the 'base' attribute does not match the "
11637 		    "type's designation '%s'",
11638 		    xmlSchemaFormatQName(&str1, type->baseNs, type->base),
11639 		    xmlSchemaFormatQName(&str2, type->targetNamespace,
11640 			type->name), NULL);
11641 		FREE_AND_NULL(str1);
11642 		FREE_AND_NULL(str2);
11643 		/* Avoid confusion and erase the values. */
11644 		type->base = NULL;
11645 		type->baseNs = NULL;
11646 	    }
11647 	}
11648     }
11649     /*
11650     * And now for the children...
11651     */
11652     child = node->children;
11653     if (IS_SCHEMA(child, "annotation")) {
11654 	/*
11655 	* Add the annotation to the simple type ancestor.
11656 	*/
11657 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11658 	    xmlSchemaParseAnnotation(ctxt, child, 1));
11659         child = child->next;
11660     }
11661     if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
11662 	/*
11663 	* Corresponds to <simpleType><restriction><simpleType>.
11664 	*/
11665 	if (IS_SCHEMA(child, "simpleType")) {
11666 	    if (type->base != NULL) {
11667 		/*
11668 		* src-restriction-base-or-simpleType
11669 		* Either the base [attribute] or the simpleType [child] of the
11670 		* <restriction> element must be present, but not both.
11671 		*/
11672 		xmlSchemaPContentErr(ctxt,
11673 		    XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11674 		    NULL, node, child,
11675 		    "The attribute 'base' and the <simpleType> child are "
11676 		    "mutually exclusive", NULL);
11677 	    } else {
11678 		type->baseType = (xmlSchemaTypePtr)
11679 		    xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11680 	    }
11681 	    child = child->next;
11682 	} else if (type->base == NULL) {
11683 	    xmlSchemaPContentErr(ctxt,
11684 		XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11685 		NULL, node, child,
11686 		"Either the attribute 'base' or a <simpleType> child "
11687 		"must be present", NULL);
11688 	}
11689     } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11690 	/*
11691 	* Corresponds to <complexType><complexContent><restriction>...
11692 	* followed by:
11693 	*
11694 	* Model groups <all>, <choice> and <sequence>.
11695 	*/
11696 	if (IS_SCHEMA(child, "all")) {
11697 	    type->subtypes = (xmlSchemaTypePtr)
11698 		xmlSchemaParseModelGroup(ctxt, schema, child,
11699 		    XML_SCHEMA_TYPE_ALL, 1);
11700 	    child = child->next;
11701 	} else if (IS_SCHEMA(child, "choice")) {
11702 	    type->subtypes = (xmlSchemaTypePtr)
11703 		xmlSchemaParseModelGroup(ctxt,
11704 		    schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
11705 	    child = child->next;
11706 	} else if (IS_SCHEMA(child, "sequence")) {
11707 	    type->subtypes = (xmlSchemaTypePtr)
11708 		xmlSchemaParseModelGroup(ctxt, schema, child,
11709 		    XML_SCHEMA_TYPE_SEQUENCE, 1);
11710 	    child = child->next;
11711 	/*
11712 	* Model group reference <group>.
11713 	*/
11714 	} else if (IS_SCHEMA(child, "group")) {
11715 	    type->subtypes = (xmlSchemaTypePtr)
11716 		xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11717 	    /*
11718 	    * Note that the reference will be resolved in
11719 	    * xmlSchemaResolveTypeReferences();
11720 	    */
11721 	    child = child->next;
11722 	}
11723     } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11724 	/*
11725 	* Corresponds to <complexType><simpleContent><restriction>...
11726 	*
11727 	* "1.1 the simple type definition corresponding to the <simpleType>
11728 	* among the [children] of <restriction> if there is one;"
11729 	*/
11730 	if (IS_SCHEMA(child, "simpleType")) {
11731 	    /*
11732 	    * We will store the to-be-restricted simple type in
11733 	    * type->contentTypeDef *temporarily*.
11734 	    */
11735 	    type->contentTypeDef = (xmlSchemaTypePtr)
11736 		xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11737 	    if ( type->contentTypeDef == NULL)
11738 		return (NULL);
11739 	    child = child->next;
11740 	}
11741     }
11742 
11743     if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
11744 	(parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
11745 	xmlSchemaFacetPtr facet, lastfacet = NULL;
11746 	/*
11747 	* Corresponds to <complexType><simpleContent><restriction>...
11748 	* <simpleType><restriction>...
11749 	*/
11750 
11751 	/*
11752 	* Add the facets to the simple type ancestor.
11753 	*/
11754 	/*
11755 	* TODO: Datatypes: 4.1.3 Constraints on XML Representation of
11756 	* Simple Type Definition Schema Representation Constraint:
11757 	* *Single Facet Value*
11758 	*/
11759 	while ((IS_SCHEMA(child, "minInclusive")) ||
11760 	    (IS_SCHEMA(child, "minExclusive")) ||
11761 	    (IS_SCHEMA(child, "maxInclusive")) ||
11762 	    (IS_SCHEMA(child, "maxExclusive")) ||
11763 	    (IS_SCHEMA(child, "totalDigits")) ||
11764 	    (IS_SCHEMA(child, "fractionDigits")) ||
11765 	    (IS_SCHEMA(child, "pattern")) ||
11766 	    (IS_SCHEMA(child, "enumeration")) ||
11767 	    (IS_SCHEMA(child, "whiteSpace")) ||
11768 	    (IS_SCHEMA(child, "length")) ||
11769 	    (IS_SCHEMA(child, "maxLength")) ||
11770 	    (IS_SCHEMA(child, "minLength"))) {
11771 	    facet = xmlSchemaParseFacet(ctxt, schema, child);
11772 	    if (facet != NULL) {
11773 		if (lastfacet == NULL)
11774 		    type->facets = facet;
11775 		else
11776 		    lastfacet->next = facet;
11777 		lastfacet = facet;
11778 		lastfacet->next = NULL;
11779 	    }
11780 	    child = child->next;
11781 	}
11782 	/*
11783 	* Create links for derivation and validation.
11784 	*/
11785 	if (type->facets != NULL) {
11786 	    xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
11787 
11788 	    facet = type->facets;
11789 	    do {
11790 		facetLink = (xmlSchemaFacetLinkPtr)
11791 		    xmlMalloc(sizeof(xmlSchemaFacetLink));
11792 		if (facetLink == NULL) {
11793 		    xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
11794 		    xmlFree(facetLink);
11795 		    return (NULL);
11796 		}
11797 		facetLink->facet = facet;
11798 		facetLink->next = NULL;
11799 		if (lastFacetLink == NULL)
11800 		    type->facetSet = facetLink;
11801 		else
11802 		    lastFacetLink->next = facetLink;
11803 		lastFacetLink = facetLink;
11804 		facet = facet->next;
11805 	    } while (facet != NULL);
11806 	}
11807     }
11808     if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
11809 	/*
11810 	* Attribute uses/declarations.
11811 	*/
11812 	if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11813 	    (xmlSchemaItemListPtr *) &(type->attrUses),
11814 	    XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
11815 	    return(NULL);
11816 	/*
11817 	* Attribute wildcard.
11818 	*/
11819 	if (IS_SCHEMA(child, "anyAttribute")) {
11820 	    type->attributeWildcard =
11821 		xmlSchemaParseAnyAttribute(ctxt, schema, child);
11822 	    child = child->next;
11823 	}
11824     }
11825     if (child != NULL) {
11826 	if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11827 	    xmlSchemaPContentErr(ctxt,
11828 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11829 		NULL, node, child, NULL,
11830 		"annotation?, (group | all | choice | sequence)?, "
11831 		"((attribute | attributeGroup)*, anyAttribute?))");
11832 	} else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11833 	     xmlSchemaPContentErr(ctxt,
11834 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11835 		NULL, node, child, NULL,
11836 		"(annotation?, (simpleType?, (minExclusive | minInclusive | "
11837 		"maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11838 		"length | minLength | maxLength | enumeration | whiteSpace | "
11839 		"pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
11840 	} else {
11841 	    /* Simple type */
11842 	    xmlSchemaPContentErr(ctxt,
11843 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11844 		NULL, node, child, NULL,
11845 		"(annotation?, (simpleType?, (minExclusive | minInclusive | "
11846 		"maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11847 		"length | minLength | maxLength | enumeration | whiteSpace | "
11848 		"pattern)*))");
11849 	}
11850     }
11851     return (NULL);
11852 }
11853 
11854 /**
11855  * xmlSchemaParseExtension:
11856  * @ctxt:  a schema validation context
11857  * @schema:  the schema being built
11858  * @node:  a subtree containing XML Schema information
11859  *
11860  * Parses an <extension>, which is found inside a
11861  * <simpleContent> or <complexContent>.
11862  * *WARNING* this interface is highly subject to change.
11863  *
11864  * TODO: Returns the type definition or NULL in case of error
11865  */
11866 static xmlSchemaTypePtr
xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlSchemaTypeType parentType)11867 xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11868                         xmlNodePtr node, xmlSchemaTypeType parentType)
11869 {
11870     xmlSchemaTypePtr type;
11871     xmlNodePtr child = NULL;
11872     xmlAttrPtr attr;
11873 
11874     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11875         return (NULL);
11876     /* Not a component, don't create it. */
11877     type = ctxt->ctxtType;
11878     type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
11879 
11880     /*
11881     * Check for illegal attributes.
11882     */
11883     attr = node->properties;
11884     while (attr != NULL) {
11885 	if (attr->ns == NULL) {
11886 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11887 		(!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11888 		xmlSchemaPIllegalAttrErr(ctxt,
11889 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11890 	    }
11891 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11892 	    xmlSchemaPIllegalAttrErr(ctxt,
11893 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11894 	}
11895 	attr = attr->next;
11896     }
11897 
11898     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11899 
11900     /*
11901     * Attribute "base" - mandatory.
11902     */
11903     if ((xmlSchemaPValAttrQName(ctxt, schema, NULL, node,
11904 	"base", &(type->baseNs), &(type->base)) == 0) &&
11905 	(type->base == NULL)) {
11906 	xmlSchemaPMissingAttrErr(ctxt,
11907 	    XML_SCHEMAP_S4S_ATTR_MISSING,
11908 	    NULL, node, "base", NULL);
11909     }
11910     /*
11911     * And now for the children...
11912     */
11913     child = node->children;
11914     if (IS_SCHEMA(child, "annotation")) {
11915 	/*
11916 	* Add the annotation to the type ancestor.
11917 	*/
11918 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11919 	    xmlSchemaParseAnnotation(ctxt, child, 1));
11920         child = child->next;
11921     }
11922     if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11923 	/*
11924 	* Corresponds to <complexType><complexContent><extension>... and:
11925 	*
11926 	* Model groups <all>, <choice>, <sequence> and <group>.
11927 	*/
11928 	if (IS_SCHEMA(child, "all")) {
11929 	    type->subtypes = (xmlSchemaTypePtr)
11930 		xmlSchemaParseModelGroup(ctxt, schema,
11931 		    child, XML_SCHEMA_TYPE_ALL, 1);
11932 	    child = child->next;
11933 	} else if (IS_SCHEMA(child, "choice")) {
11934 	    type->subtypes = (xmlSchemaTypePtr)
11935 		xmlSchemaParseModelGroup(ctxt, schema,
11936 		    child, XML_SCHEMA_TYPE_CHOICE, 1);
11937 	    child = child->next;
11938 	} else if (IS_SCHEMA(child, "sequence")) {
11939 	    type->subtypes = (xmlSchemaTypePtr)
11940 		xmlSchemaParseModelGroup(ctxt, schema,
11941 		child, XML_SCHEMA_TYPE_SEQUENCE, 1);
11942 	    child = child->next;
11943 	} else if (IS_SCHEMA(child, "group")) {
11944 	    type->subtypes = (xmlSchemaTypePtr)
11945 		xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11946 	    /*
11947 	    * Note that the reference will be resolved in
11948 	    * xmlSchemaResolveTypeReferences();
11949 	    */
11950 	    child = child->next;
11951 	}
11952     }
11953     if (child != NULL) {
11954 	/*
11955 	* Attribute uses/declarations.
11956 	*/
11957 	if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11958 	    (xmlSchemaItemListPtr *) &(type->attrUses),
11959 	    XML_SCHEMA_TYPE_EXTENSION, NULL) == -1)
11960 	    return(NULL);
11961 	/*
11962 	* Attribute wildcard.
11963 	*/
11964 	if (IS_SCHEMA(child, "anyAttribute")) {
11965 	    ctxt->ctxtType->attributeWildcard =
11966 		xmlSchemaParseAnyAttribute(ctxt, schema, child);
11967 	    child = child->next;
11968 	}
11969     }
11970     if (child != NULL) {
11971 	if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11972 	    /* Complex content extension. */
11973 	    xmlSchemaPContentErr(ctxt,
11974 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11975 		NULL, node, child, NULL,
11976 		"(annotation?, ((group | all | choice | sequence)?, "
11977 		"((attribute | attributeGroup)*, anyAttribute?)))");
11978 	} else {
11979 	    /* Simple content extension. */
11980 	    xmlSchemaPContentErr(ctxt,
11981 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11982 		NULL, node, child, NULL,
11983 		"(annotation?, ((attribute | attributeGroup)*, "
11984 		"anyAttribute?))");
11985 	}
11986     }
11987     return (NULL);
11988 }
11989 
11990 /**
11991  * xmlSchemaParseSimpleContent:
11992  * @ctxt:  a schema validation context
11993  * @schema:  the schema being built
11994  * @node:  a subtree containing XML Schema information
11995  *
11996  * parse a XML schema SimpleContent definition
11997  * *WARNING* this interface is highly subject to change
11998  *
11999  * Returns the type definition or NULL in case of error
12000  */
12001 static int
xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int * hasRestrictionOrExtension)12002 xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
12003                             xmlSchemaPtr schema, xmlNodePtr node,
12004 			    int *hasRestrictionOrExtension)
12005 {
12006     xmlSchemaTypePtr type;
12007     xmlNodePtr child = NULL;
12008     xmlAttrPtr attr;
12009 
12010     if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
12011 	(hasRestrictionOrExtension == NULL))
12012         return (-1);
12013     *hasRestrictionOrExtension = 0;
12014     /* Not a component, don't create it. */
12015     type = ctxt->ctxtType;
12016     type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
12017     /*
12018     * Check for illegal attributes.
12019     */
12020     attr = node->properties;
12021     while (attr != NULL) {
12022 	if (attr->ns == NULL) {
12023 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
12024 		xmlSchemaPIllegalAttrErr(ctxt,
12025 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12026 	    }
12027 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12028 	    xmlSchemaPIllegalAttrErr(ctxt,
12029 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12030 	}
12031 	attr = attr->next;
12032     }
12033 
12034     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12035 
12036     /*
12037     * And now for the children...
12038     */
12039     child = node->children;
12040     if (IS_SCHEMA(child, "annotation")) {
12041 	/*
12042 	* Add the annotation to the complex type ancestor.
12043 	*/
12044 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
12045 	    xmlSchemaParseAnnotation(ctxt, child, 1));
12046         child = child->next;
12047     }
12048     if (child == NULL) {
12049 	xmlSchemaPContentErr(ctxt,
12050 	    XML_SCHEMAP_S4S_ELEM_MISSING,
12051 	    NULL, node, NULL, NULL,
12052 	    "(annotation?, (restriction | extension))");
12053     }
12054     if (child == NULL) {
12055 	xmlSchemaPContentErr(ctxt,
12056 	    XML_SCHEMAP_S4S_ELEM_MISSING,
12057 	    NULL, node, NULL, NULL,
12058 	    "(annotation?, (restriction | extension))");
12059     }
12060     if (IS_SCHEMA(child, "restriction")) {
12061         xmlSchemaParseRestriction(ctxt, schema, child,
12062 	    XML_SCHEMA_TYPE_SIMPLE_CONTENT);
12063 	(*hasRestrictionOrExtension) = 1;
12064         child = child->next;
12065     } else if (IS_SCHEMA(child, "extension")) {
12066         xmlSchemaParseExtension(ctxt, schema, child,
12067 	    XML_SCHEMA_TYPE_SIMPLE_CONTENT);
12068 	(*hasRestrictionOrExtension) = 1;
12069         child = child->next;
12070     }
12071     if (child != NULL) {
12072 	xmlSchemaPContentErr(ctxt,
12073 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12074 	    NULL, node, child, NULL,
12075 	    "(annotation?, (restriction | extension))");
12076     }
12077     return (0);
12078 }
12079 
12080 /**
12081  * xmlSchemaParseComplexContent:
12082  * @ctxt:  a schema validation context
12083  * @schema:  the schema being built
12084  * @node:  a subtree containing XML Schema information
12085  *
12086  * parse a XML schema ComplexContent definition
12087  * *WARNING* this interface is highly subject to change
12088  *
12089  * Returns the type definition or NULL in case of error
12090  */
12091 static int
xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int * hasRestrictionOrExtension)12092 xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
12093                              xmlSchemaPtr schema, xmlNodePtr node,
12094 			     int *hasRestrictionOrExtension)
12095 {
12096     xmlSchemaTypePtr type;
12097     xmlNodePtr child = NULL;
12098     xmlAttrPtr attr;
12099 
12100     if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
12101 	(hasRestrictionOrExtension == NULL))
12102         return (-1);
12103     *hasRestrictionOrExtension = 0;
12104     /* Not a component, don't create it. */
12105     type = ctxt->ctxtType;
12106     /*
12107     * Check for illegal attributes.
12108     */
12109     attr = node->properties;
12110     while (attr != NULL) {
12111 	if (attr->ns == NULL) {
12112 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
12113 		(!xmlStrEqual(attr->name, BAD_CAST "mixed")))
12114 	    {
12115 		xmlSchemaPIllegalAttrErr(ctxt,
12116 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12117 	    }
12118 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12119 	    xmlSchemaPIllegalAttrErr(ctxt,
12120 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12121 	}
12122 	attr = attr->next;
12123     }
12124 
12125     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12126 
12127     /*
12128     * Set the 'mixed' on the complex type ancestor.
12129     */
12130     if (xmlGetBooleanProp(ctxt, node, "mixed", 0))  {
12131 	if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
12132 	    type->flags |= XML_SCHEMAS_TYPE_MIXED;
12133     }
12134     child = node->children;
12135     if (IS_SCHEMA(child, "annotation")) {
12136 	/*
12137 	* Add the annotation to the complex type ancestor.
12138 	*/
12139 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
12140 	    xmlSchemaParseAnnotation(ctxt, child, 1));
12141         child = child->next;
12142     }
12143     if (child == NULL) {
12144 	xmlSchemaPContentErr(ctxt,
12145 	    XML_SCHEMAP_S4S_ELEM_MISSING,
12146 	    NULL, node, NULL,
12147 	    NULL, "(annotation?, (restriction | extension))");
12148     }
12149     if (child == NULL) {
12150 	xmlSchemaPContentErr(ctxt,
12151 	    XML_SCHEMAP_S4S_ELEM_MISSING,
12152 	    NULL, node, NULL,
12153 	    NULL, "(annotation?, (restriction | extension))");
12154     }
12155     if (IS_SCHEMA(child, "restriction")) {
12156         xmlSchemaParseRestriction(ctxt, schema, child,
12157 	    XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12158 	(*hasRestrictionOrExtension) = 1;
12159         child = child->next;
12160     } else if (IS_SCHEMA(child, "extension")) {
12161         xmlSchemaParseExtension(ctxt, schema, child,
12162 	    XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12163 	(*hasRestrictionOrExtension) = 1;
12164         child = child->next;
12165     }
12166     if (child != NULL) {
12167 	xmlSchemaPContentErr(ctxt,
12168 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12169 	    NULL, node, child,
12170 	    NULL, "(annotation?, (restriction | extension))");
12171     }
12172     return (0);
12173 }
12174 
12175 /**
12176  * xmlSchemaParseComplexType:
12177  * @ctxt:  a schema validation context
12178  * @schema:  the schema being built
12179  * @node:  a subtree containing XML Schema information
12180  *
12181  * parse a XML schema Complex Type definition
12182  * *WARNING* this interface is highly subject to change
12183  *
12184  * Returns the type definition or NULL in case of error
12185  */
12186 static xmlSchemaTypePtr
xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int topLevel)12187 xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
12188                           xmlNodePtr node, int topLevel)
12189 {
12190     xmlSchemaTypePtr type, ctxtType;
12191     xmlNodePtr child = NULL;
12192     const xmlChar *name = NULL;
12193     xmlAttrPtr attr;
12194     const xmlChar *attrValue;
12195 #ifdef ENABLE_NAMED_LOCALS
12196     char buf[40];
12197 #endif
12198     int final = 0, block = 0, hasRestrictionOrExtension = 0;
12199 
12200 
12201     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
12202         return (NULL);
12203 
12204     ctxtType = ctxt->ctxtType;
12205 
12206     if (topLevel) {
12207 	attr = xmlSchemaGetPropNode(node, "name");
12208 	if (attr == NULL) {
12209 	    xmlSchemaPMissingAttrErr(ctxt,
12210 		XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
12211 	    return (NULL);
12212 	} else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
12213 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
12214 	    return (NULL);
12215 	}
12216     }
12217 
12218     if (topLevel == 0) {
12219 	/*
12220 	* Parse as local complex type definition.
12221 	*/
12222 #ifdef ENABLE_NAMED_LOCALS
12223         snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
12224 	type = xmlSchemaAddType(ctxt, schema,
12225 	    XML_SCHEMA_TYPE_COMPLEX,
12226 	    xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
12227 	    ctxt->targetNamespace, node, 0);
12228 #else
12229 	type = xmlSchemaAddType(ctxt, schema,
12230 	    XML_SCHEMA_TYPE_COMPLEX,
12231 	    NULL, ctxt->targetNamespace, node, 0);
12232 #endif
12233 	if (type == NULL)
12234 	    return (NULL);
12235 	name = type->name;
12236 	type->node = node;
12237 	type->type = XML_SCHEMA_TYPE_COMPLEX;
12238 	/*
12239 	* TODO: We need the target namespace.
12240 	*/
12241     } else {
12242 	/*
12243 	* Parse as global complex type definition.
12244 	*/
12245 	type = xmlSchemaAddType(ctxt, schema,
12246 	    XML_SCHEMA_TYPE_COMPLEX,
12247 	    name, ctxt->targetNamespace, node, 1);
12248 	if (type == NULL)
12249 	    return (NULL);
12250 	type->node = node;
12251 	type->type = XML_SCHEMA_TYPE_COMPLEX;
12252 	type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
12253     }
12254     type->targetNamespace = ctxt->targetNamespace;
12255     /*
12256     * Handle attributes.
12257     */
12258     attr = node->properties;
12259     while (attr != NULL) {
12260 	if (attr->ns == NULL) {
12261 	    if (xmlStrEqual(attr->name, BAD_CAST "id")) {
12262 		/*
12263 		* Attribute "id".
12264 		*/
12265 		xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12266 	    } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
12267 		/*
12268 		* Attribute "mixed".
12269 		*/
12270 		if (xmlSchemaPGetBoolNodeValue(ctxt,
12271 			NULL, (xmlNodePtr) attr))
12272 		    type->flags |= XML_SCHEMAS_TYPE_MIXED;
12273 	    } else if (topLevel) {
12274 		/*
12275 		* Attributes of global complex type definitions.
12276 		*/
12277 		if (xmlStrEqual(attr->name, BAD_CAST "name")) {
12278 		    /* Pass. */
12279 		} else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
12280 		    /*
12281 		    * Attribute "abstract".
12282 		    */
12283 		    if (xmlSchemaPGetBoolNodeValue(ctxt,
12284 			    NULL, (xmlNodePtr) attr))
12285 			type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
12286 		} else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
12287 		    /*
12288 		    * Attribute "final".
12289 		    */
12290 		    attrValue = xmlSchemaGetNodeContent(ctxt,
12291 			(xmlNodePtr) attr);
12292 		    if (xmlSchemaPValAttrBlockFinal(attrValue,
12293 			&(type->flags),
12294 			-1,
12295 			XML_SCHEMAS_TYPE_FINAL_EXTENSION,
12296 			XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
12297 			-1, -1, -1) != 0)
12298 		    {
12299 			xmlSchemaPSimpleTypeErr(ctxt,
12300 			    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12301 			    NULL, (xmlNodePtr) attr, NULL,
12302 			    "(#all | List of (extension | restriction))",
12303 			    attrValue, NULL, NULL, NULL);
12304 		    } else
12305 			final = 1;
12306 		} else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
12307 		    /*
12308 		    * Attribute "block".
12309 		    */
12310 		    attrValue = xmlSchemaGetNodeContent(ctxt,
12311 			(xmlNodePtr) attr);
12312 		    if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
12313 			-1,
12314 			XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
12315 			XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
12316 			-1, -1, -1) != 0) {
12317 			xmlSchemaPSimpleTypeErr(ctxt,
12318 			    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12319 			    NULL, (xmlNodePtr) attr, NULL,
12320 			    "(#all | List of (extension | restriction)) ",
12321 			    attrValue, NULL, NULL, NULL);
12322 		    } else
12323 			block = 1;
12324 		} else {
12325 			xmlSchemaPIllegalAttrErr(ctxt,
12326 			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12327 		}
12328 	    } else {
12329 		xmlSchemaPIllegalAttrErr(ctxt,
12330 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12331 	    }
12332 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12333 	    xmlSchemaPIllegalAttrErr(ctxt,
12334 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12335 	}
12336 	attr = attr->next;
12337     }
12338     if (! block) {
12339 	/*
12340 	* Apply default "block" values.
12341 	*/
12342 	if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
12343 	    type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
12344 	if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
12345 	    type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
12346     }
12347     if (! final) {
12348 	/*
12349 	* Apply default "block" values.
12350 	*/
12351 	if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
12352 	    type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
12353 	if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
12354 	    type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
12355     }
12356     /*
12357     * And now for the children...
12358     */
12359     child = node->children;
12360     if (IS_SCHEMA(child, "annotation")) {
12361         type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
12362         child = child->next;
12363     }
12364     ctxt->ctxtType = type;
12365     if (IS_SCHEMA(child, "simpleContent")) {
12366 	/*
12367 	* <complexType><simpleContent>...
12368 	* 3.4.3 : 2.2
12369 	* Specifying mixed='true' when the <simpleContent>
12370 	* alternative is chosen has no effect
12371 	*/
12372 	if (type->flags & XML_SCHEMAS_TYPE_MIXED)
12373 	    type->flags ^= XML_SCHEMAS_TYPE_MIXED;
12374         xmlSchemaParseSimpleContent(ctxt, schema, child,
12375 	    &hasRestrictionOrExtension);
12376         child = child->next;
12377     } else if (IS_SCHEMA(child, "complexContent")) {
12378 	/*
12379 	* <complexType><complexContent>...
12380 	*/
12381 	type->contentType = XML_SCHEMA_CONTENT_EMPTY;
12382         xmlSchemaParseComplexContent(ctxt, schema, child,
12383 	    &hasRestrictionOrExtension);
12384         child = child->next;
12385     } else {
12386 	/*
12387 	* E.g <complexType><sequence>... or <complexType><attribute>... etc.
12388 	*
12389 	* SPEC
12390 	* "...the third alternative (neither <simpleContent> nor
12391 	* <complexContent>) is chosen. This case is understood as shorthand
12392 	* for complex content restricting the `ur-type definition`, and the
12393 	* details of the mappings should be modified as necessary.
12394 	*/
12395 	type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12396 	type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
12397 	/*
12398 	* Parse model groups.
12399 	*/
12400         if (IS_SCHEMA(child, "all")) {
12401             type->subtypes = (xmlSchemaTypePtr)
12402 		xmlSchemaParseModelGroup(ctxt, schema, child,
12403 		    XML_SCHEMA_TYPE_ALL, 1);
12404             child = child->next;
12405         } else if (IS_SCHEMA(child, "choice")) {
12406             type->subtypes = (xmlSchemaTypePtr)
12407 		xmlSchemaParseModelGroup(ctxt, schema, child,
12408 		    XML_SCHEMA_TYPE_CHOICE, 1);
12409             child = child->next;
12410         } else if (IS_SCHEMA(child, "sequence")) {
12411             type->subtypes = (xmlSchemaTypePtr)
12412 		xmlSchemaParseModelGroup(ctxt, schema, child,
12413 		    XML_SCHEMA_TYPE_SEQUENCE, 1);
12414             child = child->next;
12415         } else if (IS_SCHEMA(child, "group")) {
12416             type->subtypes = (xmlSchemaTypePtr)
12417 		xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
12418 	    /*
12419 	    * Note that the reference will be resolved in
12420 	    * xmlSchemaResolveTypeReferences();
12421 	    */
12422             child = child->next;
12423         }
12424 	/*
12425 	* Parse attribute decls/refs.
12426 	*/
12427         if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
12428 	    (xmlSchemaItemListPtr *) &(type->attrUses),
12429 	    XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
12430 	    return(NULL);
12431 	/*
12432 	* Parse attribute wildcard.
12433 	*/
12434 	if (IS_SCHEMA(child, "anyAttribute")) {
12435 	    type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
12436 	    child = child->next;
12437 	}
12438     }
12439     if (child != NULL) {
12440 	xmlSchemaPContentErr(ctxt,
12441 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12442 	    NULL, node, child,
12443 	    NULL, "(annotation?, (simpleContent | complexContent | "
12444 	    "((group | all | choice | sequence)?, ((attribute | "
12445 	    "attributeGroup)*, anyAttribute?))))");
12446     }
12447     /*
12448     * REDEFINE: SPEC src-redefine (5)
12449     */
12450     if (topLevel && ctxt->isRedefine && (! hasRestrictionOrExtension)) {
12451 	xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
12452 	    NULL, node, "This is a redefinition, thus the "
12453 	    "<complexType> must have a <restriction> or <extension> "
12454 	    "grand-child", NULL);
12455     }
12456     ctxt->ctxtType = ctxtType;
12457     return (type);
12458 }
12459 
12460 /************************************************************************
12461  *									*
12462  *			Validating using Schemas			*
12463  *									*
12464  ************************************************************************/
12465 
12466 /************************************************************************
12467  *									*
12468  *			Reading/Writing Schemas				*
12469  *									*
12470  ************************************************************************/
12471 
12472 #if 0 /* Will be enabled if it is clear what options are needed. */
12473 /**
12474  * xmlSchemaParserCtxtSetOptions:
12475  * @ctxt:	a schema parser context
12476  * @options: a combination of xmlSchemaParserOption
12477  *
12478  * Sets the options to be used during the parse.
12479  *
12480  * Returns 0 in case of success, -1 in case of an
12481  * API error.
12482  */
12483 static int
12484 xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
12485 			      int options)
12486 
12487 {
12488     int i;
12489 
12490     if (ctxt == NULL)
12491 	return (-1);
12492     /*
12493     * WARNING: Change the start value if adding to the
12494     * xmlSchemaParseOption.
12495     */
12496     for (i = 1; i < (int) sizeof(int) * 8; i++) {
12497         if (options & 1<<i) {
12498 	    return (-1);
12499         }
12500     }
12501     ctxt->options = options;
12502     return (0);
12503 }
12504 
12505 /**
12506  * xmlSchemaValidCtxtGetOptions:
12507  * @ctxt: a schema parser context
12508  *
12509  * Returns the option combination of the parser context.
12510  */
12511 static int
12512 xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
12513 
12514 {
12515     if (ctxt == NULL)
12516 	return (-1);
12517     else
12518 	return (ctxt->options);
12519 }
12520 #endif
12521 
12522 /**
12523  * xmlSchemaNewParserCtxt:
12524  * @URL:  the location of the schema
12525  *
12526  * Create an XML Schemas parse context for that file/resource expected
12527  * to contain an XML Schemas file.
12528  *
12529  * Returns the parser context or NULL in case of error
12530  */
12531 xmlSchemaParserCtxtPtr
xmlSchemaNewParserCtxt(const char * URL)12532 xmlSchemaNewParserCtxt(const char *URL)
12533 {
12534     xmlSchemaParserCtxtPtr ret;
12535 
12536     if (URL == NULL)
12537         return (NULL);
12538 
12539     ret = xmlSchemaParserCtxtCreate();
12540     if (ret == NULL)
12541 	return(NULL);
12542     ret->dict = xmlDictCreate();
12543     ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
12544     return (ret);
12545 }
12546 
12547 /**
12548  * xmlSchemaNewMemParserCtxt:
12549  * @buffer:  a pointer to a char array containing the schemas
12550  * @size:  the size of the array
12551  *
12552  * Create an XML Schemas parse context for that memory buffer expected
12553  * to contain an XML Schemas file.
12554  *
12555  * Returns the parser context or NULL in case of error
12556  */
12557 xmlSchemaParserCtxtPtr
xmlSchemaNewMemParserCtxt(const char * buffer,int size)12558 xmlSchemaNewMemParserCtxt(const char *buffer, int size)
12559 {
12560     xmlSchemaParserCtxtPtr ret;
12561 
12562     if ((buffer == NULL) || (size <= 0))
12563         return (NULL);
12564     ret = xmlSchemaParserCtxtCreate();
12565     if (ret == NULL)
12566 	return(NULL);
12567     ret->buffer = buffer;
12568     ret->size = size;
12569     ret->dict = xmlDictCreate();
12570     return (ret);
12571 }
12572 
12573 /**
12574  * xmlSchemaNewDocParserCtxt:
12575  * @doc:  a preparsed document tree
12576  *
12577  * Create an XML Schemas parse context for that document.
12578  * NB. The document may be modified during the parsing process.
12579  *
12580  * Returns the parser context or NULL in case of error
12581  */
12582 xmlSchemaParserCtxtPtr
xmlSchemaNewDocParserCtxt(xmlDocPtr doc)12583 xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
12584 {
12585     xmlSchemaParserCtxtPtr ret;
12586 
12587     if (doc == NULL)
12588       return (NULL);
12589     ret = xmlSchemaParserCtxtCreate();
12590     if (ret == NULL)
12591 	return(NULL);
12592     ret->doc = doc;
12593     ret->dict = xmlDictCreate();
12594     /* The application has responsibility for the document */
12595     ret->preserve = 1;
12596 
12597     return (ret);
12598 }
12599 
12600 /**
12601  * xmlSchemaFreeParserCtxt:
12602  * @ctxt:  the schema parser context
12603  *
12604  * Free the resources associated to the schema parser context
12605  */
12606 void
xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)12607 xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
12608 {
12609     if (ctxt == NULL)
12610         return;
12611     if (ctxt->doc != NULL && !ctxt->preserve)
12612         xmlFreeDoc(ctxt->doc);
12613     if (ctxt->vctxt != NULL) {
12614 	xmlSchemaFreeValidCtxt(ctxt->vctxt);
12615     }
12616     if (ctxt->ownsConstructor && (ctxt->constructor != NULL)) {
12617 	xmlSchemaConstructionCtxtFree(ctxt->constructor);
12618 	ctxt->constructor = NULL;
12619 	ctxt->ownsConstructor = 0;
12620     }
12621     if (ctxt->attrProhibs != NULL)
12622 	xmlSchemaItemListFree(ctxt->attrProhibs);
12623     xmlDictFree(ctxt->dict);
12624     xmlFree(ctxt);
12625 }
12626 
12627 /************************************************************************
12628  *									*
12629  *			Building the content models			*
12630  *									*
12631  ************************************************************************/
12632 
12633 /**
12634  * xmlSchemaBuildContentModelForSubstGroup:
12635  *
12636  * Returns 1 if nillable, 0 otherwise
12637  */
12638 static int
xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,xmlSchemaParticlePtr particle,int counter,xmlAutomataStatePtr end)12639 xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
12640 	xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end)
12641 {
12642     xmlAutomataStatePtr start, tmp;
12643     xmlSchemaElementPtr elemDecl, member;
12644     xmlSchemaSubstGroupPtr substGroup;
12645     int i;
12646     int ret = 0;
12647 
12648     elemDecl = (xmlSchemaElementPtr) particle->children;
12649     /*
12650     * Wrap the substitution group with a CHOICE.
12651     */
12652     start = pctxt->state;
12653     if (end == NULL)
12654 	end = xmlAutomataNewState(pctxt->am);
12655     substGroup = xmlSchemaSubstGroupGet(pctxt, elemDecl);
12656     if (substGroup == NULL) {
12657 	xmlSchemaPErr(pctxt, WXS_ITEM_NODE(particle),
12658 	    XML_SCHEMAP_INTERNAL,
12659 	    "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
12660 	    "declaration is marked having a subst. group but none "
12661 	    "available.\n", elemDecl->name, NULL);
12662 	return(0);
12663     }
12664     if (counter >= 0) {
12665 	/*
12666 	* NOTE that we put the declaration in, even if it's abstract.
12667 	* However, an error will be raised during *validation* if an element
12668 	* information item shall be validated against an abstract element
12669 	* declaration.
12670 	*/
12671 	tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter);
12672         xmlAutomataNewTransition2(pctxt->am, tmp, end,
12673 	            elemDecl->name, elemDecl->targetNamespace, elemDecl);
12674 	/*
12675 	* Add subst. group members.
12676 	*/
12677 	for (i = 0; i < substGroup->members->nbItems; i++) {
12678 	    member = (xmlSchemaElementPtr) substGroup->members->items[i];
12679             xmlAutomataNewTransition2(pctxt->am, tmp, end,
12680 		               member->name, member->targetNamespace, member);
12681 	}
12682     } else if (particle->maxOccurs == 1) {
12683 	/*
12684 	* NOTE that we put the declaration in, even if it's abstract,
12685 	*/
12686 	xmlAutomataNewEpsilon(pctxt->am,
12687 	    xmlAutomataNewTransition2(pctxt->am,
12688 	    start, NULL,
12689 	    elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
12690 	/*
12691 	* Add subst. group members.
12692 	*/
12693 	for (i = 0; i < substGroup->members->nbItems; i++) {
12694 	    member = (xmlSchemaElementPtr) substGroup->members->items[i];
12695 	    /*
12696 	    * NOTE: This fixes bug #341150. xmlAutomataNewOnceTrans2()
12697 	    *  was incorrectly used instead of xmlAutomataNewTransition2()
12698 	    *  (seems like a copy&paste bug from the XML_SCHEMA_TYPE_ALL
12699 	    *  section in xmlSchemaBuildAContentModel() ).
12700 	    * TODO: Check if xmlAutomataNewOnceTrans2() was instead
12701 	    *  intended for the above "counter" section originally. I.e.,
12702 	    *  check xs:all with subst-groups.
12703 	    *
12704 	    * tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL,
12705 	    *	               member->name, member->targetNamespace,
12706 	    *		       1, 1, member);
12707 	    */
12708 	    tmp = xmlAutomataNewTransition2(pctxt->am, start, NULL,
12709 		member->name, member->targetNamespace, member);
12710 	    xmlAutomataNewEpsilon(pctxt->am, tmp, end);
12711 	}
12712     } else {
12713 	xmlAutomataStatePtr hop;
12714 	int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12715 	    UNBOUNDED : particle->maxOccurs - 1;
12716 	int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12717 
12718 	counter =
12719 	    xmlAutomataNewCounter(pctxt->am, minOccurs,
12720 	    maxOccurs);
12721 	hop = xmlAutomataNewState(pctxt->am);
12722 
12723 	xmlAutomataNewEpsilon(pctxt->am,
12724 	    xmlAutomataNewTransition2(pctxt->am,
12725 	    start, NULL,
12726 	    elemDecl->name, elemDecl->targetNamespace, elemDecl),
12727 	    hop);
12728 	/*
12729 	 * Add subst. group members.
12730 	 */
12731 	for (i = 0; i < substGroup->members->nbItems; i++) {
12732 	    member = (xmlSchemaElementPtr) substGroup->members->items[i];
12733 	    xmlAutomataNewEpsilon(pctxt->am,
12734 		xmlAutomataNewTransition2(pctxt->am,
12735 		start, NULL,
12736 		member->name, member->targetNamespace, member),
12737 		hop);
12738 	}
12739 	xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12740 	xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12741     }
12742     if (particle->minOccurs == 0) {
12743 	xmlAutomataNewEpsilon(pctxt->am, start, end);
12744         ret = 1;
12745     }
12746     pctxt->state = end;
12747     return(ret);
12748 }
12749 
12750 /**
12751  * xmlSchemaBuildContentModelForElement:
12752  *
12753  * Returns 1 if nillable, 0 otherwise
12754  */
12755 static int
xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr particle)12756 xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
12757 				     xmlSchemaParticlePtr particle)
12758 {
12759     int ret = 0;
12760 
12761     if (((xmlSchemaElementPtr) particle->children)->flags &
12762 	XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
12763 	/*
12764 	* Substitution groups.
12765 	*/
12766 	ret = xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
12767     } else {
12768 	xmlSchemaElementPtr elemDecl;
12769 	xmlAutomataStatePtr start;
12770 
12771 	elemDecl = (xmlSchemaElementPtr) particle->children;
12772 
12773 	if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
12774 	    return(0);
12775 	if (particle->maxOccurs == 1) {
12776 	    start = ctxt->state;
12777 	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12778 		    elemDecl->name, elemDecl->targetNamespace, elemDecl);
12779 	} else if ((particle->maxOccurs >= UNBOUNDED) &&
12780 	           (particle->minOccurs < 2)) {
12781 	    /* Special case. */
12782 	    start = ctxt->state;
12783 	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12784 		elemDecl->name, elemDecl->targetNamespace, elemDecl);
12785 	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, ctxt->state, ctxt->state,
12786 		elemDecl->name, elemDecl->targetNamespace, elemDecl);
12787 	} else {
12788 	    int counter;
12789 	    int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12790 			    UNBOUNDED : particle->maxOccurs - 1;
12791 	    int minOccurs = particle->minOccurs < 1 ?
12792 			    0 : particle->minOccurs - 1;
12793 
12794 	    start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
12795 	    counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
12796 	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12797 		elemDecl->name, elemDecl->targetNamespace, elemDecl);
12798 	    xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
12799 	    ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
12800 		NULL, counter);
12801 	}
12802 	if (particle->minOccurs == 0) {
12803 	    xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
12804             ret = 1;
12805         }
12806     }
12807     return(ret);
12808 }
12809 
12810 /**
12811  * xmlSchemaBuildAContentModel:
12812  * @ctxt:  the schema parser context
12813  * @particle:  the particle component
12814  * @name:  the complex type's name whose content is being built
12815  *
12816  * Create the automaton for the {content type} of a complex type.
12817  *
12818  * Returns 1 if the content is nillable, 0 otherwise
12819  */
12820 static int
xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,xmlSchemaParticlePtr particle)12821 xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
12822 			    xmlSchemaParticlePtr particle)
12823 {
12824     int ret = 0, tmp2;
12825 
12826     if (particle == NULL) {
12827 	PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL");
12828 	return(1);
12829     }
12830     if (particle->children == NULL) {
12831 	/*
12832 	* Just return in this case. A missing "term" of the particle
12833 	* might arise due to an invalid "term" component.
12834 	*/
12835 	return(1);
12836     }
12837 
12838     switch (particle->children->type) {
12839 	case XML_SCHEMA_TYPE_ANY: {
12840 	    xmlAutomataStatePtr start, end;
12841 	    xmlSchemaWildcardPtr wild;
12842 	    xmlSchemaWildcardNsPtr ns;
12843 
12844 	    wild = (xmlSchemaWildcardPtr) particle->children;
12845 
12846 	    start = pctxt->state;
12847 	    end = xmlAutomataNewState(pctxt->am);
12848 
12849 	    if (particle->maxOccurs == 1) {
12850 		if (wild->any == 1) {
12851 		    /*
12852 		    * We need to add both transitions:
12853 		    *
12854 		    * 1. the {"*", "*"} for elements in a namespace.
12855 		    */
12856 		    pctxt->state =
12857 			xmlAutomataNewTransition2(pctxt->am,
12858 			start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12859 		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12860 		    /*
12861 		    * 2. the {"*"} for elements in no namespace.
12862 		    */
12863 		    pctxt->state =
12864 			xmlAutomataNewTransition2(pctxt->am,
12865 			start, NULL, BAD_CAST "*", NULL, wild);
12866 		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12867 
12868 		} else if (wild->nsSet != NULL) {
12869 		    ns = wild->nsSet;
12870 		    do {
12871 			pctxt->state = start;
12872 			pctxt->state = xmlAutomataNewTransition2(pctxt->am,
12873 			    pctxt->state, NULL, BAD_CAST "*", ns->value, wild);
12874 			xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12875 			ns = ns->next;
12876 		    } while (ns != NULL);
12877 
12878 		} else if (wild->negNsSet != NULL) {
12879 		    pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12880 			start, end, BAD_CAST "*", wild->negNsSet->value,
12881 			wild);
12882 		}
12883 	    } else {
12884 		int counter;
12885 		xmlAutomataStatePtr hop;
12886 		int maxOccurs =
12887 		    particle->maxOccurs == UNBOUNDED ? UNBOUNDED :
12888                                            particle->maxOccurs - 1;
12889 		int minOccurs =
12890 		    particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12891 
12892 		counter = xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12893 		hop = xmlAutomataNewState(pctxt->am);
12894 		if (wild->any == 1) {
12895 		    pctxt->state =
12896 			xmlAutomataNewTransition2(pctxt->am,
12897 			start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12898 		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12899 		    pctxt->state =
12900 			xmlAutomataNewTransition2(pctxt->am,
12901 			start, NULL, BAD_CAST "*", NULL, wild);
12902 		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12903 		} else if (wild->nsSet != NULL) {
12904 		    ns = wild->nsSet;
12905 		    do {
12906 			pctxt->state =
12907 			    xmlAutomataNewTransition2(pctxt->am,
12908 				start, NULL, BAD_CAST "*", ns->value, wild);
12909 			xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12910 			ns = ns->next;
12911 		    } while (ns != NULL);
12912 
12913 		} else if (wild->negNsSet != NULL) {
12914 		    pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12915 			start, hop, BAD_CAST "*", wild->negNsSet->value,
12916 			wild);
12917 		}
12918 		xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12919 		xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12920 	    }
12921 	    if (particle->minOccurs == 0) {
12922 		xmlAutomataNewEpsilon(pctxt->am, start, end);
12923                 ret = 1;
12924 	    }
12925 	    pctxt->state = end;
12926             break;
12927 	}
12928         case XML_SCHEMA_TYPE_ELEMENT:
12929 	    ret = xmlSchemaBuildContentModelForElement(pctxt, particle);
12930 	    break;
12931         case XML_SCHEMA_TYPE_SEQUENCE:{
12932             xmlSchemaTreeItemPtr sub;
12933 
12934             ret = 1;
12935             /*
12936              * If max and min occurrences are default (1) then
12937              * simply iterate over the particles of the <sequence>.
12938              */
12939             if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
12940                 sub = particle->children->children;
12941 
12942                 while (sub != NULL) {
12943                     tmp2 = xmlSchemaBuildAContentModel(pctxt,
12944                                         (xmlSchemaParticlePtr) sub);
12945                     if (tmp2 != 1) ret = 0;
12946                     sub = sub->next;
12947                 }
12948             } else {
12949                 xmlAutomataStatePtr oldstate = pctxt->state;
12950 
12951                 if (particle->maxOccurs >= UNBOUNDED) {
12952                     if (particle->minOccurs > 1) {
12953                         xmlAutomataStatePtr tmp;
12954                         int counter;
12955 
12956                         pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12957                             oldstate, NULL);
12958                         oldstate = pctxt->state;
12959 
12960                         counter = xmlAutomataNewCounter(pctxt->am,
12961                             particle->minOccurs - 1, UNBOUNDED);
12962 
12963                         sub = particle->children->children;
12964                         while (sub != NULL) {
12965                             tmp2 = xmlSchemaBuildAContentModel(pctxt,
12966                                             (xmlSchemaParticlePtr) sub);
12967                             if (tmp2 != 1) ret = 0;
12968                             sub = sub->next;
12969                         }
12970                         tmp = pctxt->state;
12971                         xmlAutomataNewCountedTrans(pctxt->am, tmp,
12972                                                    oldstate, counter);
12973                         pctxt->state =
12974                             xmlAutomataNewCounterTrans(pctxt->am, tmp,
12975                                                        NULL, counter);
12976                         if (ret == 1)
12977                             xmlAutomataNewEpsilon(pctxt->am,
12978                                                 oldstate, pctxt->state);
12979 
12980                     } else {
12981                         pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12982                             oldstate, NULL);
12983                         oldstate = pctxt->state;
12984 
12985                         sub = particle->children->children;
12986                         while (sub != NULL) {
12987                             tmp2 = xmlSchemaBuildAContentModel(pctxt,
12988                                         (xmlSchemaParticlePtr) sub);
12989                             if (tmp2 != 1) ret = 0;
12990                             sub = sub->next;
12991                         }
12992                         xmlAutomataNewEpsilon(pctxt->am, pctxt->state,
12993                                               oldstate);
12994                         /*
12995                          * epsilon needed to block previous trans from
12996                          * being allowed to enter back from another
12997                          * construct
12998                          */
12999                         pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
13000                                             pctxt->state, NULL);
13001                         if (particle->minOccurs == 0) {
13002                             xmlAutomataNewEpsilon(pctxt->am,
13003                                 oldstate, pctxt->state);
13004                             ret = 1;
13005                         }
13006                     }
13007                 } else if ((particle->maxOccurs > 1)
13008                            || (particle->minOccurs > 1)) {
13009                     xmlAutomataStatePtr tmp;
13010                     int counter;
13011 
13012                     pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
13013                         oldstate, NULL);
13014                     oldstate = pctxt->state;
13015 
13016                     counter = xmlAutomataNewCounter(pctxt->am,
13017                         particle->minOccurs - 1,
13018                         particle->maxOccurs - 1);
13019 
13020                     sub = particle->children->children;
13021                     while (sub != NULL) {
13022                         tmp2 = xmlSchemaBuildAContentModel(pctxt,
13023                                         (xmlSchemaParticlePtr) sub);
13024                         if (tmp2 != 1) ret = 0;
13025                         sub = sub->next;
13026                     }
13027                     tmp = pctxt->state;
13028                     xmlAutomataNewCountedTrans(pctxt->am,
13029                         tmp, oldstate, counter);
13030                     pctxt->state =
13031                         xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL,
13032                                                    counter);
13033                     if ((particle->minOccurs == 0) || (ret == 1)) {
13034                         xmlAutomataNewEpsilon(pctxt->am,
13035                                             oldstate, pctxt->state);
13036                         ret = 1;
13037                     }
13038                 } else {
13039                     sub = particle->children->children;
13040                     while (sub != NULL) {
13041                         tmp2 = xmlSchemaBuildAContentModel(pctxt,
13042                                         (xmlSchemaParticlePtr) sub);
13043                         if (tmp2 != 1) ret = 0;
13044                         sub = sub->next;
13045                     }
13046 
13047 		    /*
13048 		     * epsilon needed to block previous trans from
13049 		     * being allowed to enter back from another
13050 		     * construct
13051 		     */
13052 		    pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
13053 					pctxt->state, NULL);
13054 
13055                     if (particle->minOccurs == 0) {
13056                         xmlAutomataNewEpsilon(pctxt->am, oldstate,
13057                                               pctxt->state);
13058                         ret = 1;
13059                     }
13060                 }
13061             }
13062             break;
13063         }
13064         case XML_SCHEMA_TYPE_CHOICE:{
13065             xmlSchemaTreeItemPtr sub;
13066             xmlAutomataStatePtr start, end;
13067 
13068             ret = 0;
13069             start = pctxt->state;
13070             end = xmlAutomataNewState(pctxt->am);
13071 
13072             /*
13073              * iterate over the subtypes and remerge the end with an
13074              * epsilon transition
13075              */
13076             if (particle->maxOccurs == 1) {
13077                 sub = particle->children->children;
13078                 while (sub != NULL) {
13079                     pctxt->state = start;
13080                     tmp2 = xmlSchemaBuildAContentModel(pctxt,
13081                                         (xmlSchemaParticlePtr) sub);
13082                     if (tmp2 == 1) ret = 1;
13083                     xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
13084                     sub = sub->next;
13085                 }
13086             } else {
13087                 int counter;
13088                 xmlAutomataStatePtr hop, base;
13089                 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
13090                     UNBOUNDED : particle->maxOccurs - 1;
13091                 int minOccurs =
13092                     particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
13093 
13094                 /*
13095                  * use a counter to keep track of the number of transitions
13096                  * which went through the choice.
13097                  */
13098                 counter =
13099                     xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
13100                 hop = xmlAutomataNewState(pctxt->am);
13101                 base = xmlAutomataNewState(pctxt->am);
13102 
13103                 sub = particle->children->children;
13104                 while (sub != NULL) {
13105                     pctxt->state = base;
13106                     tmp2 = xmlSchemaBuildAContentModel(pctxt,
13107                                         (xmlSchemaParticlePtr) sub);
13108                     if (tmp2 == 1) ret = 1;
13109                     xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
13110                     sub = sub->next;
13111                 }
13112                 xmlAutomataNewEpsilon(pctxt->am, start, base);
13113                 xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter);
13114                 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
13115                 if (ret == 1)
13116                     xmlAutomataNewEpsilon(pctxt->am, base, end);
13117             }
13118             if (particle->minOccurs == 0) {
13119                 xmlAutomataNewEpsilon(pctxt->am, start, end);
13120                 ret = 1;
13121             }
13122             pctxt->state = end;
13123             break;
13124         }
13125         case XML_SCHEMA_TYPE_ALL:{
13126             xmlAutomataStatePtr start, tmp;
13127             xmlSchemaParticlePtr sub;
13128             xmlSchemaElementPtr elemDecl;
13129 
13130             ret = 1;
13131 
13132             sub = (xmlSchemaParticlePtr) particle->children->children;
13133             if (sub == NULL)
13134                 break;
13135 
13136             ret = 0;
13137 
13138             start = pctxt->state;
13139             tmp = xmlAutomataNewState(pctxt->am);
13140             xmlAutomataNewEpsilon(pctxt->am, pctxt->state, tmp);
13141             pctxt->state = tmp;
13142             while (sub != NULL) {
13143                 pctxt->state = tmp;
13144 
13145                 elemDecl = (xmlSchemaElementPtr) sub->children;
13146                 if (elemDecl == NULL) {
13147                     PERROR_INT("xmlSchemaBuildAContentModel",
13148                         "<element> particle has no term");
13149                     return(ret);
13150                 };
13151                 /*
13152                 * NOTE: The {max occurs} of all the particles in the
13153                 * {particles} of the group must be 0 or 1; this is
13154                 * already ensured during the parse of the content of
13155                 * <all>.
13156                 */
13157                 if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
13158                     int counter;
13159 
13160                     /*
13161                      * This is an abstract group, we need to share
13162                      * the same counter for all the element transitions
13163                      * derived from the group
13164                      */
13165                     counter = xmlAutomataNewCounter(pctxt->am,
13166                                        sub->minOccurs, sub->maxOccurs);
13167                     xmlSchemaBuildContentModelForSubstGroup(pctxt,
13168                                        sub, counter, pctxt->state);
13169                 } else {
13170                     if ((sub->minOccurs == 1) &&
13171                         (sub->maxOccurs == 1)) {
13172                         xmlAutomataNewOnceTrans2(pctxt->am, pctxt->state,
13173                                                 pctxt->state,
13174                                                 elemDecl->name,
13175                                                 elemDecl->targetNamespace,
13176                                                 1, 1, elemDecl);
13177                     } else if ((sub->minOccurs == 0) &&
13178                         (sub->maxOccurs == 1)) {
13179 
13180                         xmlAutomataNewCountTrans2(pctxt->am, pctxt->state,
13181                                                  pctxt->state,
13182                                                  elemDecl->name,
13183                                                  elemDecl->targetNamespace,
13184                                                  0,
13185                                                  1,
13186                                                  elemDecl);
13187                     }
13188                 }
13189                 sub = (xmlSchemaParticlePtr) sub->next;
13190             }
13191             pctxt->state =
13192                 xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, 0);
13193             if (particle->minOccurs == 0) {
13194                 xmlAutomataNewEpsilon(pctxt->am, start, pctxt->state);
13195                 ret = 1;
13196             }
13197             break;
13198         }
13199 	case XML_SCHEMA_TYPE_GROUP:
13200 	    /*
13201 	    * If we hit a model group definition, then this means that
13202 	    * it was empty, thus was not substituted for the containing
13203 	    * model group. Just do nothing in this case.
13204 	    * TODO: But the group should be substituted and not occur at
13205 	    * all in the content model at this point. Fix this.
13206 	    */
13207             ret = 1;
13208 	    break;
13209         default:
13210 	    xmlSchemaInternalErr2(ACTXT_CAST pctxt,
13211 		"xmlSchemaBuildAContentModel",
13212 		"found unexpected term of type '%s' in content model",
13213 		WXS_ITEM_TYPE_NAME(particle->children), NULL);
13214             return(ret);
13215     }
13216     return(ret);
13217 }
13218 
13219 /**
13220  * xmlSchemaBuildContentModel:
13221  * @ctxt:  the schema parser context
13222  * @type:  the complex type definition
13223  * @name:  the element name
13224  *
13225  * Builds the content model of the complex type.
13226  */
13227 static void
xmlSchemaBuildContentModel(xmlSchemaTypePtr type,xmlSchemaParserCtxtPtr ctxt)13228 xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
13229 			   xmlSchemaParserCtxtPtr ctxt)
13230 {
13231     if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
13232 	(type->contModel != NULL) ||
13233 	((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
13234 	(type->contentType != XML_SCHEMA_CONTENT_MIXED)))
13235 	return;
13236 
13237 #ifdef DEBUG_CONTENT
13238     xmlGenericError(xmlGenericErrorContext,
13239                     "Building content model for %s\n", name);
13240 #endif
13241     ctxt->am = NULL;
13242     ctxt->am = xmlNewAutomata();
13243     if (ctxt->am == NULL) {
13244         xmlGenericError(xmlGenericErrorContext,
13245 	    "Cannot create automata for complex type %s\n", type->name);
13246         return;
13247     }
13248     ctxt->state = xmlAutomataGetInitState(ctxt->am);
13249     /*
13250     * Build the automaton.
13251     */
13252     xmlSchemaBuildAContentModel(ctxt, WXS_TYPE_PARTICLE(type));
13253     xmlAutomataSetFinalState(ctxt->am, ctxt->state);
13254     type->contModel = xmlAutomataCompile(ctxt->am);
13255     if (type->contModel == NULL) {
13256         xmlSchemaPCustomErr(ctxt,
13257 	    XML_SCHEMAP_INTERNAL,
13258 	    WXS_BASIC_CAST type, type->node,
13259 	    "Failed to compile the content model", NULL);
13260     } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
13261         xmlSchemaPCustomErr(ctxt,
13262 	    XML_SCHEMAP_NOT_DETERMINISTIC,
13263 	    /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
13264 	    WXS_BASIC_CAST type, type->node,
13265 	    "The content model is not determinist", NULL);
13266     } else {
13267 #ifdef DEBUG_CONTENT_REGEXP
13268         xmlGenericError(xmlGenericErrorContext,
13269                         "Content model of %s:\n", type->name);
13270         xmlRegexpPrint(stderr, type->contModel);
13271 #endif
13272     }
13273     ctxt->state = NULL;
13274     xmlFreeAutomata(ctxt->am);
13275     ctxt->am = NULL;
13276 }
13277 
13278 /**
13279  * xmlSchemaResolveElementReferences:
13280  * @elem:  the schema element context
13281  * @ctxt:  the schema parser context
13282  *
13283  * Resolves the references of an element declaration
13284  * or particle, which has an element declaration as it's
13285  * term.
13286  */
13287 static void
xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,xmlSchemaParserCtxtPtr ctxt)13288 xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,
13289 				  xmlSchemaParserCtxtPtr ctxt)
13290 {
13291     if ((ctxt == NULL) || (elemDecl == NULL) ||
13292 	((elemDecl != NULL) &&
13293 	(elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
13294         return;
13295     elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
13296 
13297     if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
13298 	xmlSchemaTypePtr type;
13299 
13300 	/* (type definition) ... otherwise the type definition `resolved`
13301 	* to by the `actual value` of the type [attribute] ...
13302 	*/
13303 	type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
13304 	    elemDecl->namedTypeNs);
13305 	if (type == NULL) {
13306 	    xmlSchemaPResCompAttrErr(ctxt,
13307 		XML_SCHEMAP_SRC_RESOLVE,
13308 		WXS_BASIC_CAST elemDecl, elemDecl->node,
13309 		"type", elemDecl->namedType, elemDecl->namedTypeNs,
13310 		XML_SCHEMA_TYPE_BASIC, "type definition");
13311 	} else
13312 	    elemDecl->subtypes = type;
13313     }
13314     if (elemDecl->substGroup != NULL) {
13315 	xmlSchemaElementPtr substHead;
13316 
13317 	/*
13318 	* FIXME TODO: Do we need a new field in _xmlSchemaElement for
13319 	* substitutionGroup?
13320 	*/
13321 	substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
13322 	    elemDecl->substGroupNs);
13323 	if (substHead == NULL) {
13324 	    xmlSchemaPResCompAttrErr(ctxt,
13325 		XML_SCHEMAP_SRC_RESOLVE,
13326 		WXS_BASIC_CAST elemDecl, NULL,
13327 		"substitutionGroup", elemDecl->substGroup,
13328 		elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
13329 	} else {
13330 	    xmlSchemaResolveElementReferences(substHead, ctxt);
13331 	    /*
13332 	    * Set the "substitution group affiliation".
13333 	    * NOTE that now we use the "refDecl" field for this.
13334 	    */
13335 	    WXS_SUBST_HEAD(elemDecl) = substHead;
13336 	    /*
13337 	    * The type definitions is set to:
13338 	    * SPEC "...the {type definition} of the element
13339 	    * declaration `resolved` to by the `actual value`
13340 	    * of the substitutionGroup [attribute], if present"
13341 	    */
13342 	    if (elemDecl->subtypes == NULL)
13343 		elemDecl->subtypes = substHead->subtypes;
13344 	}
13345     }
13346     /*
13347     * SPEC "The definition of anyType serves as the default type definition
13348     * for element declarations whose XML representation does not specify one."
13349     */
13350     if ((elemDecl->subtypes == NULL) &&
13351 	(elemDecl->namedType == NULL) &&
13352 	(elemDecl->substGroup == NULL))
13353 	elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
13354 }
13355 
13356 /**
13357  * xmlSchemaResolveUnionMemberTypes:
13358  * @ctxt:  the schema parser context
13359  * @type:  the schema simple type definition
13360  *
13361  * Checks and builds the "member type definitions" property of the union
13362  * simple type. This handles part (1), part (2) is done in
13363  * xmlSchemaFinishMemberTypeDefinitionsProperty()
13364  *
13365  * Returns -1 in case of an internal error, 0 otherwise.
13366  */
13367 static int
xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)13368 xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
13369 				 xmlSchemaTypePtr type)
13370 {
13371 
13372     xmlSchemaTypeLinkPtr link, lastLink, newLink;
13373     xmlSchemaTypePtr memberType;
13374 
13375     /*
13376     * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
13377     * define the explicit members as the type definitions `resolved`
13378     * to by the items in the `actual value` of the memberTypes [attribute],
13379     * if any, followed by the type definitions corresponding to the
13380     * <simpleType>s among the [children] of <union>, if any."
13381     */
13382     /*
13383     * Resolve references.
13384     */
13385     link = type->memberTypes;
13386     lastLink = NULL;
13387     while (link != NULL) {
13388 	const xmlChar *name, *nsName;
13389 
13390 	name = ((xmlSchemaQNameRefPtr) link->type)->name;
13391 	nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
13392 
13393 	memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
13394 	if ((memberType == NULL) || (! WXS_IS_SIMPLE(memberType))) {
13395 	    xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
13396 		WXS_BASIC_CAST type, type->node, "memberTypes",
13397 		name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
13398 	    /*
13399 	    * Remove the member type link.
13400 	    */
13401 	    if (lastLink == NULL)
13402 		type->memberTypes = link->next;
13403 	    else
13404 		lastLink->next = link->next;
13405 	    newLink = link;
13406 	    link = link->next;
13407 	    xmlFree(newLink);
13408 	} else {
13409 	    link->type = memberType;
13410 	    lastLink = link;
13411 	    link = link->next;
13412 	}
13413     }
13414     /*
13415     * Add local simple types,
13416     */
13417     memberType = type->subtypes;
13418     while (memberType != NULL) {
13419 	link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
13420 	if (link == NULL) {
13421 	    xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
13422 	    return (-1);
13423 	}
13424 	link->type = memberType;
13425 	link->next = NULL;
13426 	if (lastLink == NULL)
13427 	    type->memberTypes = link;
13428 	else
13429 	    lastLink->next = link;
13430 	lastLink = link;
13431 	memberType = memberType->next;
13432     }
13433     return (0);
13434 }
13435 
13436 /**
13437  * xmlSchemaIsDerivedFromBuiltInType:
13438  * @ctxt:  the schema parser context
13439  * @type:  the type definition
13440  * @valType: the value type
13441  *
13442  *
13443  * Returns 1 if the type has the given value type, or
13444  * is derived from such a type.
13445  */
13446 static int
xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type,int valType)13447 xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13448 {
13449     if (type == NULL)
13450 	return (0);
13451     if (WXS_IS_COMPLEX(type))
13452 	return (0);
13453     if (type->type == XML_SCHEMA_TYPE_BASIC) {
13454 	if (type->builtInType == valType)
13455 	    return(1);
13456 	if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13457 	    (type->builtInType == XML_SCHEMAS_ANYTYPE))
13458 	    return (0);
13459 	return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13460     }
13461     return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13462 }
13463 
13464 #if 0
13465 /**
13466  * xmlSchemaIsDerivedFromBuiltInType:
13467  * @ctxt:  the schema parser context
13468  * @type:  the type definition
13469  * @valType: the value type
13470  *
13471  *
13472  * Returns 1 if the type has the given value type, or
13473  * is derived from such a type.
13474  */
13475 static int
13476 xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13477 {
13478     if (type == NULL)
13479 	return (0);
13480     if (WXS_IS_COMPLEX(type))
13481 	return (0);
13482     if (type->type == XML_SCHEMA_TYPE_BASIC) {
13483 	if (type->builtInType == valType)
13484 	    return(1);
13485 	return (0);
13486     } else
13487 	return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13488 
13489     return (0);
13490 }
13491 
13492 static xmlSchemaTypePtr
13493 xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
13494 {
13495     if (type == NULL)
13496 	return (NULL);
13497     if (WXS_IS_COMPLEX(type))
13498 	return (NULL);
13499     if (type->type == XML_SCHEMA_TYPE_BASIC)
13500 	return(type);
13501     return(xmlSchemaQueryBuiltInType(type->subtypes));
13502 }
13503 #endif
13504 
13505 /**
13506  * xmlSchemaGetPrimitiveType:
13507  * @type:  the simpleType definition
13508  *
13509  * Returns the primitive type of the given type or
13510  * NULL in case of error.
13511  */
13512 static xmlSchemaTypePtr
xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)13513 xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
13514 {
13515 
13516     while (type != NULL) {
13517 	/*
13518 	* Note that anySimpleType is actually not a primitive type
13519 	* but we need that here.
13520 	*/
13521 	if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13522 	   (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
13523 	    return (type);
13524 	type = type->baseType;
13525     }
13526 
13527     return (NULL);
13528 }
13529 
13530 #if 0
13531 /**
13532  * xmlSchemaGetBuiltInTypeAncestor:
13533  * @type:  the simpleType definition
13534  *
13535  * Returns the primitive type of the given type or
13536  * NULL in case of error.
13537  */
13538 static xmlSchemaTypePtr
13539 xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
13540 {
13541     if (WXS_IS_LIST(type) || WXS_IS_UNION(type))
13542 	return (0);
13543     while (type != NULL) {
13544 	if (type->type == XML_SCHEMA_TYPE_BASIC)
13545 	    return (type);
13546 	type = type->baseType;
13547     }
13548 
13549     return (NULL);
13550 }
13551 #endif
13552 
13553 /**
13554  * xmlSchemaCloneWildcardNsConstraints:
13555  * @ctxt:  the schema parser context
13556  * @dest:  the destination wildcard
13557  * @source: the source wildcard
13558  *
13559  * Clones the namespace constraints of source
13560  * and assigns them to dest.
13561  * Returns -1 on internal error, 0 otherwise.
13562  */
13563 static int
xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,xmlSchemaWildcardPtr dest,xmlSchemaWildcardPtr source)13564 xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
13565 				    xmlSchemaWildcardPtr dest,
13566 				    xmlSchemaWildcardPtr source)
13567 {
13568     xmlSchemaWildcardNsPtr cur, tmp, last;
13569 
13570     if ((source == NULL) || (dest == NULL))
13571 	return(-1);
13572     dest->any = source->any;
13573     cur = source->nsSet;
13574     last = NULL;
13575     while (cur != NULL) {
13576 	tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13577 	if (tmp == NULL)
13578 	    return(-1);
13579 	tmp->value = cur->value;
13580 	if (last == NULL)
13581 	    dest->nsSet = tmp;
13582 	else
13583 	    last->next = tmp;
13584 	last = tmp;
13585 	cur = cur->next;
13586     }
13587     if (dest->negNsSet != NULL)
13588 	xmlSchemaFreeWildcardNsSet(dest->negNsSet);
13589     if (source->negNsSet != NULL) {
13590 	dest->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13591 	if (dest->negNsSet == NULL)
13592 	    return(-1);
13593 	dest->negNsSet->value = source->negNsSet->value;
13594     } else
13595 	dest->negNsSet = NULL;
13596     return(0);
13597 }
13598 
13599 /**
13600  * xmlSchemaUnionWildcards:
13601  * @ctxt:  the schema parser context
13602  * @completeWild:  the first wildcard
13603  * @curWild: the second wildcard
13604  *
13605  * Unions the namespace constraints of the given wildcards.
13606  * @completeWild will hold the resulting union.
13607  * Returns a positive error code on failure, -1 in case of an
13608  * internal error, 0 otherwise.
13609  */
13610 static int
xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,xmlSchemaWildcardPtr completeWild,xmlSchemaWildcardPtr curWild)13611 xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
13612 			    xmlSchemaWildcardPtr completeWild,
13613 			    xmlSchemaWildcardPtr curWild)
13614 {
13615     xmlSchemaWildcardNsPtr cur, curB, tmp;
13616 
13617     /*
13618     * 1 If O1 and O2 are the same value, then that value must be the
13619     * value.
13620     */
13621     if ((completeWild->any == curWild->any) &&
13622 	((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13623 	((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13624 
13625 	if ((completeWild->negNsSet == NULL) ||
13626 	    (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13627 
13628 	    if (completeWild->nsSet != NULL) {
13629 		int found = 0;
13630 
13631 		/*
13632 		* Check equality of sets.
13633 		*/
13634 		cur = completeWild->nsSet;
13635 		while (cur != NULL) {
13636 		    found = 0;
13637 		    curB = curWild->nsSet;
13638 		    while (curB != NULL) {
13639 			if (cur->value == curB->value) {
13640 			    found = 1;
13641 			    break;
13642 			}
13643 			curB = curB->next;
13644 		    }
13645 		    if (!found)
13646 			break;
13647 		    cur = cur->next;
13648 		}
13649 		if (found)
13650 		    return(0);
13651 	    } else
13652 		return(0);
13653 	}
13654     }
13655     /*
13656     * 2 If either O1 or O2 is any, then any must be the value
13657     */
13658     if (completeWild->any != curWild->any) {
13659 	if (completeWild->any == 0) {
13660 	    completeWild->any = 1;
13661 	    if (completeWild->nsSet != NULL) {
13662 		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13663 		completeWild->nsSet = NULL;
13664 	    }
13665 	    if (completeWild->negNsSet != NULL) {
13666 		xmlFree(completeWild->negNsSet);
13667 		completeWild->negNsSet = NULL;
13668 	    }
13669 	}
13670 	return (0);
13671     }
13672     /*
13673     * 3 If both O1 and O2 are sets of (namespace names or `absent`),
13674     * then the union of those sets must be the value.
13675     */
13676     if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13677 	int found;
13678 	xmlSchemaWildcardNsPtr start;
13679 
13680 	cur = curWild->nsSet;
13681 	start = completeWild->nsSet;
13682 	while (cur != NULL) {
13683 	    found = 0;
13684 	    curB = start;
13685 	    while (curB != NULL) {
13686 		if (cur->value == curB->value) {
13687 		    found = 1;
13688 		    break;
13689 		}
13690 		curB = curB->next;
13691 	    }
13692 	    if (!found) {
13693 		tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13694 		if (tmp == NULL)
13695 		    return (-1);
13696 		tmp->value = cur->value;
13697 		tmp->next = completeWild->nsSet;
13698 		completeWild->nsSet = tmp;
13699 	    }
13700 	    cur = cur->next;
13701 	}
13702 
13703 	return(0);
13704     }
13705     /*
13706     * 4 If the two are negations of different values (namespace names
13707     * or `absent`), then a pair of not and `absent` must be the value.
13708     */
13709     if ((completeWild->negNsSet != NULL) &&
13710 	(curWild->negNsSet != NULL) &&
13711 	(completeWild->negNsSet->value != curWild->negNsSet->value)) {
13712 	completeWild->negNsSet->value = NULL;
13713 
13714 	return(0);
13715     }
13716     /*
13717      * 5.
13718      */
13719     if (((completeWild->negNsSet != NULL) &&
13720 	(completeWild->negNsSet->value != NULL) &&
13721 	(curWild->nsSet != NULL)) ||
13722 	((curWild->negNsSet != NULL) &&
13723 	(curWild->negNsSet->value != NULL) &&
13724 	(completeWild->nsSet != NULL))) {
13725 
13726 	int nsFound, absentFound = 0;
13727 
13728 	if (completeWild->nsSet != NULL) {
13729 	    cur = completeWild->nsSet;
13730 	    curB = curWild->negNsSet;
13731 	} else {
13732 	    cur = curWild->nsSet;
13733 	    curB = completeWild->negNsSet;
13734 	}
13735 	nsFound = 0;
13736 	while (cur != NULL) {
13737 	    if (cur->value == NULL)
13738 		absentFound = 1;
13739 	    else if (cur->value == curB->value)
13740 		nsFound = 1;
13741 	    if (nsFound && absentFound)
13742 		break;
13743 	    cur = cur->next;
13744 	}
13745 
13746 	if (nsFound && absentFound) {
13747 	    /*
13748 	    * 5.1 If the set S includes both the negated namespace
13749 	    * name and `absent`, then any must be the value.
13750 	    */
13751 	    completeWild->any = 1;
13752 	    if (completeWild->nsSet != NULL) {
13753 		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13754 		completeWild->nsSet = NULL;
13755 	    }
13756 	    if (completeWild->negNsSet != NULL) {
13757 		xmlFree(completeWild->negNsSet);
13758 		completeWild->negNsSet = NULL;
13759 	    }
13760 	} else if (nsFound && (!absentFound)) {
13761 	    /*
13762 	    * 5.2 If the set S includes the negated namespace name
13763 	    * but not `absent`, then a pair of not and `absent` must
13764 	    * be the value.
13765 	    */
13766 	    if (completeWild->nsSet != NULL) {
13767 		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13768 		completeWild->nsSet = NULL;
13769 	    }
13770 	    if (completeWild->negNsSet == NULL) {
13771 		completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13772 		if (completeWild->negNsSet == NULL)
13773 		    return (-1);
13774 	    }
13775 	    completeWild->negNsSet->value = NULL;
13776 	} else if ((!nsFound) && absentFound) {
13777 	    /*
13778 	    * 5.3 If the set S includes `absent` but not the negated
13779 	    * namespace name, then the union is not expressible.
13780 	    */
13781 	    xmlSchemaPErr(ctxt, completeWild->node,
13782 		XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
13783 		"The union of the wildcard is not expressible.\n",
13784 		NULL, NULL);
13785 	    return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
13786 	} else if ((!nsFound) && (!absentFound)) {
13787 	    /*
13788 	    * 5.4 If the set S does not include either the negated namespace
13789 	    * name or `absent`, then whichever of O1 or O2 is a pair of not
13790 	    * and a namespace name must be the value.
13791 	    */
13792 	    if (completeWild->negNsSet == NULL) {
13793 		if (completeWild->nsSet != NULL) {
13794 		    xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13795 		    completeWild->nsSet = NULL;
13796 		}
13797 		completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13798 		if (completeWild->negNsSet == NULL)
13799 		    return (-1);
13800 		completeWild->negNsSet->value = curWild->negNsSet->value;
13801 	    }
13802 	}
13803 	return (0);
13804     }
13805     /*
13806      * 6.
13807      */
13808     if (((completeWild->negNsSet != NULL) &&
13809 	(completeWild->negNsSet->value == NULL) &&
13810 	(curWild->nsSet != NULL)) ||
13811 	((curWild->negNsSet != NULL) &&
13812 	(curWild->negNsSet->value == NULL) &&
13813 	(completeWild->nsSet != NULL))) {
13814 
13815 	if (completeWild->nsSet != NULL) {
13816 	    cur = completeWild->nsSet;
13817 	} else {
13818 	    cur = curWild->nsSet;
13819 	}
13820 	while (cur != NULL) {
13821 	    if (cur->value == NULL) {
13822 		/*
13823 		* 6.1 If the set S includes `absent`, then any must be the
13824 		* value.
13825 		*/
13826 		completeWild->any = 1;
13827 		if (completeWild->nsSet != NULL) {
13828 		    xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13829 		    completeWild->nsSet = NULL;
13830 		}
13831 		if (completeWild->negNsSet != NULL) {
13832 		    xmlFree(completeWild->negNsSet);
13833 		    completeWild->negNsSet = NULL;
13834 		}
13835 		return (0);
13836 	    }
13837 	    cur = cur->next;
13838 	}
13839 	if (completeWild->negNsSet == NULL) {
13840 	    /*
13841 	    * 6.2 If the set S does not include `absent`, then a pair of not
13842 	    * and `absent` must be the value.
13843 	    */
13844 	    if (completeWild->nsSet != NULL) {
13845 		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13846 		completeWild->nsSet = NULL;
13847 	    }
13848 	    completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13849 	    if (completeWild->negNsSet == NULL)
13850 		return (-1);
13851 	    completeWild->negNsSet->value = NULL;
13852 	}
13853 	return (0);
13854     }
13855     return (0);
13856 
13857 }
13858 
13859 /**
13860  * xmlSchemaIntersectWildcards:
13861  * @ctxt:  the schema parser context
13862  * @completeWild:  the first wildcard
13863  * @curWild: the second wildcard
13864  *
13865  * Intersects the namespace constraints of the given wildcards.
13866  * @completeWild will hold the resulting intersection.
13867  * Returns a positive error code on failure, -1 in case of an
13868  * internal error, 0 otherwise.
13869  */
13870 static int
xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,xmlSchemaWildcardPtr completeWild,xmlSchemaWildcardPtr curWild)13871 xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
13872 			    xmlSchemaWildcardPtr completeWild,
13873 			    xmlSchemaWildcardPtr curWild)
13874 {
13875     xmlSchemaWildcardNsPtr cur, curB, prev,  tmp;
13876 
13877     /*
13878     * 1 If O1 and O2 are the same value, then that value must be the
13879     * value.
13880     */
13881     if ((completeWild->any == curWild->any) &&
13882 	((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13883 	((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13884 
13885 	if ((completeWild->negNsSet == NULL) ||
13886 	    (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13887 
13888 	    if (completeWild->nsSet != NULL) {
13889 		int found = 0;
13890 
13891 		/*
13892 		* Check equality of sets.
13893 		*/
13894 		cur = completeWild->nsSet;
13895 		while (cur != NULL) {
13896 		    found = 0;
13897 		    curB = curWild->nsSet;
13898 		    while (curB != NULL) {
13899 			if (cur->value == curB->value) {
13900 			    found = 1;
13901 			    break;
13902 			}
13903 			curB = curB->next;
13904 		    }
13905 		    if (!found)
13906 			break;
13907 		    cur = cur->next;
13908 		}
13909 		if (found)
13910 		    return(0);
13911 	    } else
13912 		return(0);
13913 	}
13914     }
13915     /*
13916     * 2 If either O1 or O2 is any, then the other must be the value.
13917     */
13918     if ((completeWild->any != curWild->any) && (completeWild->any)) {
13919 	if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13920 	    return(-1);
13921 	return(0);
13922     }
13923     /*
13924     * 3 If either O1 or O2 is a pair of not and a value (a namespace
13925     * name or `absent`) and the other is a set of (namespace names or
13926     * `absent`), then that set, minus the negated value if it was in
13927     * the set, minus `absent` if it was in the set, must be the value.
13928     */
13929     if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
13930 	((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
13931 	const xmlChar *neg;
13932 
13933 	if (completeWild->nsSet == NULL) {
13934 	    neg = completeWild->negNsSet->value;
13935 	    if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13936 		return(-1);
13937 	} else
13938 	    neg = curWild->negNsSet->value;
13939 	/*
13940 	* Remove absent and negated.
13941 	*/
13942 	prev = NULL;
13943 	cur = completeWild->nsSet;
13944 	while (cur != NULL) {
13945 	    if (cur->value == NULL) {
13946 		if (prev == NULL)
13947 		    completeWild->nsSet = cur->next;
13948 		else
13949 		    prev->next = cur->next;
13950 		xmlFree(cur);
13951 		break;
13952 	    }
13953 	    prev = cur;
13954 	    cur = cur->next;
13955 	}
13956 	if (neg != NULL) {
13957 	    prev = NULL;
13958 	    cur = completeWild->nsSet;
13959 	    while (cur != NULL) {
13960 		if (cur->value == neg) {
13961 		    if (prev == NULL)
13962 			completeWild->nsSet = cur->next;
13963 		    else
13964 			prev->next = cur->next;
13965 		    xmlFree(cur);
13966 		    break;
13967 		}
13968 		prev = cur;
13969 		cur = cur->next;
13970 	    }
13971 	}
13972 
13973 	return(0);
13974     }
13975     /*
13976     * 4 If both O1 and O2 are sets of (namespace names or `absent`),
13977     * then the intersection of those sets must be the value.
13978     */
13979     if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13980 	int found;
13981 
13982 	cur = completeWild->nsSet;
13983 	prev = NULL;
13984 	while (cur != NULL) {
13985 	    found = 0;
13986 	    curB = curWild->nsSet;
13987 	    while (curB != NULL) {
13988 		if (cur->value == curB->value) {
13989 		    found = 1;
13990 		    break;
13991 		}
13992 		curB = curB->next;
13993 	    }
13994 	    if (!found) {
13995 		if (prev == NULL)
13996 		    completeWild->nsSet = cur->next;
13997 		else
13998 		    prev->next = cur->next;
13999 		tmp = cur->next;
14000 		xmlFree(cur);
14001 		cur = tmp;
14002 		continue;
14003 	    }
14004 	    prev = cur;
14005 	    cur = cur->next;
14006 	}
14007 
14008 	return(0);
14009     }
14010     /* 5 If the two are negations of different namespace names,
14011     * then the intersection is not expressible
14012     */
14013     if ((completeWild->negNsSet != NULL) &&
14014 	(curWild->negNsSet != NULL) &&
14015 	(completeWild->negNsSet->value != curWild->negNsSet->value) &&
14016 	(completeWild->negNsSet->value != NULL) &&
14017 	(curWild->negNsSet->value != NULL)) {
14018 
14019 	xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
14020 	    "The intersection of the wildcard is not expressible.\n",
14021 	    NULL, NULL);
14022 	return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
14023     }
14024     /*
14025     * 6 If the one is a negation of a namespace name and the other
14026     * is a negation of `absent`, then the one which is the negation
14027     * of a namespace name must be the value.
14028     */
14029     if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
14030 	(completeWild->negNsSet->value != curWild->negNsSet->value) &&
14031 	(completeWild->negNsSet->value == NULL)) {
14032 	completeWild->negNsSet->value =  curWild->negNsSet->value;
14033     }
14034     return(0);
14035 }
14036 
14037 /**
14038  * xmlSchemaIsWildcardNsConstraintSubset:
14039  * @ctxt:  the schema parser context
14040  * @sub:  the first wildcard
14041  * @super: the second wildcard
14042  *
14043  * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
14044  *
14045  * Returns 0 if the namespace constraint of @sub is an intensional
14046  * subset of @super, 1 otherwise.
14047  */
14048 static int
xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,xmlSchemaWildcardPtr super)14049 xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
14050 			  xmlSchemaWildcardPtr super)
14051 {
14052     /*
14053     * 1 super must be any.
14054     */
14055     if (super->any)
14056 	return (0);
14057     /*
14058     * 2.1 sub must be a pair of not and a namespace name or `absent`.
14059     * 2.2 super must be a pair of not and the same value.
14060     */
14061     if ((sub->negNsSet != NULL) &&
14062 	(super->negNsSet != NULL) &&
14063 	(sub->negNsSet->value == super->negNsSet->value))
14064 	return (0);
14065     /*
14066     * 3.1 sub must be a set whose members are either namespace names or `absent`.
14067     */
14068     if (sub->nsSet != NULL) {
14069 	/*
14070 	* 3.2.1 super must be the same set or a superset thereof.
14071 	*/
14072 	if (super->nsSet != NULL) {
14073 	    xmlSchemaWildcardNsPtr cur, curB;
14074 	    int found = 0;
14075 
14076 	    cur = sub->nsSet;
14077 	    while (cur != NULL) {
14078 		found = 0;
14079 		curB = super->nsSet;
14080 		while (curB != NULL) {
14081 		    if (cur->value == curB->value) {
14082 			found = 1;
14083 			break;
14084 		    }
14085 		    curB = curB->next;
14086 		}
14087 		if (!found)
14088 		    return (1);
14089 		cur = cur->next;
14090 	    }
14091 	    if (found)
14092 		return (0);
14093 	} else if (super->negNsSet != NULL) {
14094 	    xmlSchemaWildcardNsPtr cur;
14095 	    /*
14096 	    * 3.2.2 super must be a pair of not and a namespace name or
14097 	    * `absent` and that value must not be in sub's set.
14098 	    */
14099 	    cur = sub->nsSet;
14100 	    while (cur != NULL) {
14101 		if (cur->value == super->negNsSet->value)
14102 		    return (1);
14103 		cur = cur->next;
14104 	    }
14105 	    return (0);
14106 	}
14107     }
14108     return (1);
14109 }
14110 
14111 static int
xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse,int * fixed,const xmlChar ** value,xmlSchemaValPtr * val)14112 xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse,
14113 				     int *fixed,
14114 				     const xmlChar **value,
14115 				     xmlSchemaValPtr *val)
14116 {
14117     *fixed = 0;
14118     *value = NULL;
14119     if (val != 0)
14120 	*val = NULL;
14121 
14122     if (attruse->defValue != NULL) {
14123 	*value = attruse->defValue;
14124 	if (val != NULL)
14125 	    *val = attruse->defVal;
14126 	if (attruse->flags & XML_SCHEMA_ATTR_USE_FIXED)
14127 	    *fixed = 1;
14128 	return(1);
14129     } else if ((attruse->attrDecl != NULL) &&
14130 	(attruse->attrDecl->defValue != NULL)) {
14131 	*value = attruse->attrDecl->defValue;
14132 	if (val != NULL)
14133 	    *val = attruse->attrDecl->defVal;
14134 	if (attruse->attrDecl->flags & XML_SCHEMAS_ATTR_FIXED)
14135 	    *fixed = 1;
14136 	return(1);
14137     }
14138     return(0);
14139 }
14140 /**
14141  * xmlSchemaCheckCVCWildcardNamespace:
14142  * @wild:  the wildcard
14143  * @ns:  the namespace
14144  *
14145  * Validation Rule: Wildcard allows Namespace Name
14146  * (cvc-wildcard-namespace)
14147  *
14148  * Returns 0 if the given namespace matches the wildcard,
14149  * 1 otherwise and -1 on API errors.
14150  */
14151 static int
xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,const xmlChar * ns)14152 xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
14153 				   const xmlChar* ns)
14154 {
14155     if (wild == NULL)
14156 	return(-1);
14157 
14158     if (wild->any)
14159 	return(0);
14160     else if (wild->nsSet != NULL) {
14161 	xmlSchemaWildcardNsPtr cur;
14162 
14163 	cur = wild->nsSet;
14164 	while (cur != NULL) {
14165 	    if (xmlStrEqual(cur->value, ns))
14166 		return(0);
14167 	    cur = cur->next;
14168 	}
14169     } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
14170 	(!xmlStrEqual(wild->negNsSet->value, ns)))
14171 	return(0);
14172 
14173     return(1);
14174 }
14175 
14176 #define XML_SCHEMA_ACTION_DERIVE 0
14177 #define XML_SCHEMA_ACTION_REDEFINE 1
14178 
14179 #define WXS_ACTION_STR(a) \
14180 ((a) == XML_SCHEMA_ACTION_DERIVE) ? (const xmlChar *) "base" : (const xmlChar *) "redefined"
14181 
14182 /*
14183 * Schema Component Constraint:
14184 *   Derivation Valid (Restriction, Complex)
14185 *   derivation-ok-restriction (2) - (4)
14186 *
14187 * ATTENTION:
14188 * In XML Schema 1.1 this will be:
14189 * Validation Rule:
14190 *     Checking complex type subsumption (practicalSubsumption) (1, 2 and 3)
14191 *
14192 */
14193 static int
xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt,int action,xmlSchemaBasicItemPtr item,xmlSchemaBasicItemPtr baseItem,xmlSchemaItemListPtr uses,xmlSchemaItemListPtr baseUses,xmlSchemaWildcardPtr wild,xmlSchemaWildcardPtr baseWild)14194 xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt,
14195 				       int action,
14196 				       xmlSchemaBasicItemPtr item,
14197 				       xmlSchemaBasicItemPtr baseItem,
14198 				       xmlSchemaItemListPtr uses,
14199 				       xmlSchemaItemListPtr baseUses,
14200 				       xmlSchemaWildcardPtr wild,
14201 				       xmlSchemaWildcardPtr baseWild)
14202 {
14203     xmlSchemaAttributeUsePtr cur = NULL, bcur;
14204     int i, j, found; /* err = 0; */
14205     const xmlChar *bEffValue;
14206     int effFixed;
14207 
14208     if (uses != NULL) {
14209 	for (i = 0; i < uses->nbItems; i++) {
14210 	    cur = uses->items[i];
14211 	    found = 0;
14212 	    if (baseUses == NULL)
14213 		goto not_found;
14214 	    for (j = 0; j < baseUses->nbItems; j++) {
14215 		bcur = baseUses->items[j];
14216 		if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14217 			WXS_ATTRUSE_DECL_NAME(bcur)) &&
14218 		    (WXS_ATTRUSE_DECL_TNS(cur) ==
14219 			WXS_ATTRUSE_DECL_TNS(bcur)))
14220 		{
14221 		    /*
14222 		    * (2.1) "If there is an attribute use in the {attribute
14223 		    * uses} of the {base type definition} (call this B) whose
14224 		    * {attribute declaration} has the same {name} and {target
14225 		    * namespace}, then  all of the following must be true:"
14226 		    */
14227 		    found = 1;
14228 
14229 		    if ((cur->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
14230 			(bcur->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED))
14231 		    {
14232 			xmlChar *str = NULL;
14233 			/*
14234 			* (2.1.1) "one of the following must be true:"
14235 			* (2.1.1.1) "B's {required} is false."
14236 			* (2.1.1.2) "R's {required} is true."
14237 			*/
14238 			xmlSchemaPAttrUseErr4(pctxt,
14239 			    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
14240 			    WXS_ITEM_NODE(item), item, cur,
14241 			    "The 'optional' attribute use is inconsistent "
14242 			    "with the corresponding 'required' attribute use of "
14243 			    "the %s %s",
14244 			    WXS_ACTION_STR(action),
14245 			    xmlSchemaGetComponentDesignation(&str, baseItem),
14246 			    NULL, NULL);
14247 			FREE_AND_NULL(str);
14248 			/* err = pctxt->err; */
14249 		    } else if (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
14250 			WXS_ATTRUSE_TYPEDEF(cur),
14251 			WXS_ATTRUSE_TYPEDEF(bcur), 0) != 0)
14252 		    {
14253 			xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
14254 
14255 			/*
14256 			* SPEC (2.1.2) "R's {attribute declaration}'s
14257 			* {type definition} must be validly derived from
14258 			* B's {type definition} given the empty set as
14259 			* defined in Type Derivation OK (Simple) ($3.14.6)."
14260 			*/
14261 			xmlSchemaPAttrUseErr4(pctxt,
14262 			    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
14263 			    WXS_ITEM_NODE(item), item, cur,
14264 			    "The attribute declaration's %s "
14265 			    "is not validly derived from "
14266 			    "the corresponding %s of the "
14267 			    "attribute declaration in the %s %s",
14268 			    xmlSchemaGetComponentDesignation(&strA,
14269 				WXS_ATTRUSE_TYPEDEF(cur)),
14270 			    xmlSchemaGetComponentDesignation(&strB,
14271 				WXS_ATTRUSE_TYPEDEF(bcur)),
14272 			    WXS_ACTION_STR(action),
14273 			    xmlSchemaGetComponentDesignation(&strC, baseItem));
14274 			    /* xmlSchemaGetComponentDesignation(&str, baseItem), */
14275 			FREE_AND_NULL(strA);
14276 			FREE_AND_NULL(strB);
14277 			FREE_AND_NULL(strC);
14278 			/* err = pctxt->err; */
14279 		    } else {
14280 			/*
14281 			* 2.1.3 [Definition:]  Let the effective value
14282 			* constraint of an attribute use be its {value
14283 			* constraint}, if present, otherwise its {attribute
14284 			* declaration}'s {value constraint} .
14285 			*/
14286 			xmlSchemaGetEffectiveValueConstraint(bcur,
14287 			    &effFixed, &bEffValue, NULL);
14288 			/*
14289 			* 2.1.3 ... one of the following must be true
14290 			*
14291 			* 2.1.3.1 B's `effective value constraint` is
14292 			* `absent` or default.
14293 			*/
14294 			if ((bEffValue != NULL) &&
14295 			    (effFixed == 1)) {
14296 			    const xmlChar *rEffValue = NULL;
14297 
14298 			    xmlSchemaGetEffectiveValueConstraint(bcur,
14299 				&effFixed, &rEffValue, NULL);
14300 			    /*
14301 			    * 2.1.3.2 R's `effective value constraint` is
14302 			    * fixed with the same string as B's.
14303 			    * MAYBE TODO: Compare the computed values.
14304 			    *       Hmm, it says "same string" so
14305 			    *       string-equality might really be sufficient.
14306 			    */
14307 			    if ((effFixed == 0) ||
14308 				(! WXS_ARE_DEFAULT_STR_EQUAL(rEffValue, bEffValue)))
14309 			    {
14310 				xmlChar *str = NULL;
14311 
14312 				xmlSchemaPAttrUseErr4(pctxt,
14313 				    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
14314 				    WXS_ITEM_NODE(item), item, cur,
14315 				    "The effective value constraint of the "
14316 				    "attribute use is inconsistent with "
14317 				    "its correspondent in the %s %s",
14318 				    WXS_ACTION_STR(action),
14319 				    xmlSchemaGetComponentDesignation(&str,
14320 					baseItem),
14321 				    NULL, NULL);
14322 				FREE_AND_NULL(str);
14323 				/* err = pctxt->err; */
14324 			    }
14325 			}
14326 		    }
14327 		    break;
14328 		}
14329 	    }
14330 not_found:
14331 	    if (!found) {
14332 		/*
14333 		* (2.2) "otherwise the {base type definition} must have an
14334 		* {attribute wildcard} and the {target namespace} of the
14335 		* R's {attribute declaration} must be `valid` with respect
14336 		* to that wildcard, as defined in Wildcard allows Namespace
14337 		* Name ($3.10.4)."
14338 		*/
14339 		if ((baseWild == NULL) ||
14340 		    (xmlSchemaCheckCVCWildcardNamespace(baseWild,
14341 		    (WXS_ATTRUSE_DECL(cur))->targetNamespace) != 0))
14342 		{
14343 		    xmlChar *str = NULL;
14344 
14345 		    xmlSchemaPAttrUseErr4(pctxt,
14346 			XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
14347 			WXS_ITEM_NODE(item), item, cur,
14348 			"Neither a matching attribute use, "
14349 			"nor a matching wildcard exists in the %s %s",
14350 			WXS_ACTION_STR(action),
14351 			xmlSchemaGetComponentDesignation(&str, baseItem),
14352 			NULL, NULL);
14353 		    FREE_AND_NULL(str);
14354 		    /* err = pctxt->err; */
14355 		}
14356 	    }
14357 	}
14358     }
14359     /*
14360     * SPEC derivation-ok-restriction (3):
14361     * (3) "For each attribute use in the {attribute uses} of the {base type
14362     * definition} whose {required} is true, there must be an attribute
14363     * use with an {attribute declaration} with the same {name} and
14364     * {target namespace} as its {attribute declaration} in the {attribute
14365     * uses} of the complex type definition itself whose {required} is true.
14366     */
14367     if (baseUses != NULL) {
14368 	for (j = 0; j < baseUses->nbItems; j++) {
14369 	    bcur = baseUses->items[j];
14370 	    if (bcur->occurs != XML_SCHEMAS_ATTR_USE_REQUIRED)
14371 		continue;
14372 	    found = 0;
14373 	    if (uses != NULL) {
14374 		for (i = 0; i < uses->nbItems; i++) {
14375 		    cur = uses->items[i];
14376 		    if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14377 			WXS_ATTRUSE_DECL_NAME(bcur)) &&
14378 			(WXS_ATTRUSE_DECL_TNS(cur) ==
14379 			WXS_ATTRUSE_DECL_TNS(bcur))) {
14380 			found = 1;
14381 			break;
14382 		    }
14383 		}
14384 	    }
14385 	    if (!found) {
14386 		xmlChar *strA = NULL, *strB = NULL;
14387 
14388 		xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14389 		    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
14390 		    NULL, item,
14391 		    "A matching attribute use for the "
14392 		    "'required' %s of the %s %s is missing",
14393 		    xmlSchemaGetComponentDesignation(&strA, bcur),
14394 		    WXS_ACTION_STR(action),
14395 		    xmlSchemaGetComponentDesignation(&strB, baseItem),
14396 		    NULL);
14397 		FREE_AND_NULL(strA);
14398 		FREE_AND_NULL(strB);
14399 	    }
14400 	}
14401     }
14402     /*
14403     * derivation-ok-restriction (4)
14404     */
14405     if (wild != NULL) {
14406 	/*
14407 	* (4) "If there is an {attribute wildcard}, all of the
14408 	* following must be true:"
14409 	*/
14410 	if (baseWild == NULL) {
14411 	    xmlChar *str = NULL;
14412 
14413 	    /*
14414 	    * (4.1) "The {base type definition} must also have one."
14415 	    */
14416 	    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14417 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
14418 		NULL, item,
14419 		"The %s has an attribute wildcard, "
14420 		"but the %s %s '%s' does not have one",
14421 		WXS_ITEM_TYPE_NAME(item),
14422 		WXS_ACTION_STR(action),
14423 		WXS_ITEM_TYPE_NAME(baseItem),
14424 		xmlSchemaGetComponentQName(&str, baseItem));
14425 	    FREE_AND_NULL(str);
14426 	    return(pctxt->err);
14427 	} else if ((baseWild->any == 0) &&
14428 		xmlSchemaCheckCOSNSSubset(wild, baseWild))
14429 	{
14430 	    xmlChar *str = NULL;
14431 	    /*
14432 	    * (4.2) "The complex type definition's {attribute wildcard}'s
14433 	    * {namespace constraint} must be a subset of the {base type
14434 	    * definition}'s {attribute wildcard}'s {namespace constraint},
14435 	    * as defined by Wildcard Subset ($3.10.6)."
14436 	    */
14437 	    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14438 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
14439 		NULL, item,
14440 		"The attribute wildcard is not a valid "
14441 		"subset of the wildcard in the %s %s '%s'",
14442 		WXS_ACTION_STR(action),
14443 		WXS_ITEM_TYPE_NAME(baseItem),
14444 		xmlSchemaGetComponentQName(&str, baseItem),
14445 		NULL);
14446 	    FREE_AND_NULL(str);
14447 	    return(pctxt->err);
14448 	}
14449 	/* 4.3 Unless the {base type definition} is the `ur-type
14450 	* definition`, the complex type definition's {attribute
14451 	* wildcard}'s {process contents} must be identical to or
14452 	* stronger than the {base type definition}'s {attribute
14453 	* wildcard}'s {process contents}, where strict is stronger
14454 	* than lax is stronger than skip.
14455 	*/
14456 	if ((! WXS_IS_ANYTYPE(baseItem)) &&
14457 	    (wild->processContents < baseWild->processContents)) {
14458 	    xmlChar *str = NULL;
14459 	    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14460 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
14461 		NULL, baseItem,
14462 		"The {process contents} of the attribute wildcard is "
14463 		"weaker than the one in the %s %s '%s'",
14464 		WXS_ACTION_STR(action),
14465 		WXS_ITEM_TYPE_NAME(baseItem),
14466 		xmlSchemaGetComponentQName(&str, baseItem),
14467 		NULL);
14468 	    FREE_AND_NULL(str)
14469 		return(pctxt->err);
14470 	}
14471     }
14472     return(0);
14473 }
14474 
14475 
14476 static int
14477 xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
14478 				  xmlSchemaBasicItemPtr item,
14479 				  xmlSchemaWildcardPtr *completeWild,
14480 				  xmlSchemaItemListPtr list,
14481 				  xmlSchemaItemListPtr prohibs);
14482 /**
14483  * xmlSchemaFixupTypeAttributeUses:
14484  * @ctxt:  the schema parser context
14485  * @type:  the complex type definition
14486  *
14487  *
14488  * Builds the wildcard and the attribute uses on the given complex type.
14489  * Returns -1 if an internal error occurs, 0 otherwise.
14490  *
14491  * ATTENTION TODO: Experimentally this uses pointer comparisons for
14492  * strings, so recheck this if we start to hardcode some schemata, since
14493  * they might not be in the same dict.
14494  * NOTE: It is allowed to "extend" the xs:anyType type.
14495  */
14496 static int
xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)14497 xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt,
14498 				  xmlSchemaTypePtr type)
14499 {
14500     xmlSchemaTypePtr baseType = NULL;
14501     xmlSchemaAttributeUsePtr use;
14502     xmlSchemaItemListPtr uses, baseUses, prohibs = NULL;
14503 
14504     if (type->baseType == NULL) {
14505 	PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14506 	    "no base type");
14507         return (-1);
14508     }
14509     baseType = type->baseType;
14510     if (WXS_IS_TYPE_NOT_FIXED(baseType))
14511 	if (xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt) == -1)
14512 	    return(-1);
14513 
14514     uses = type->attrUses;
14515     baseUses = baseType->attrUses;
14516     /*
14517     * Expand attribute group references. And build the 'complete'
14518     * wildcard, i.e. intersect multiple wildcards.
14519     * Move attribute prohibitions into a separate list.
14520     */
14521     if (uses != NULL) {
14522 	if (WXS_IS_RESTRICTION(type)) {
14523 	    /*
14524 	    * This one will transfer all attr. prohibitions
14525 	    * into pctxt->attrProhibs.
14526 	    */
14527 	    if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14528 		WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14529 		pctxt->attrProhibs) == -1)
14530 	    {
14531 		PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14532 		"failed to expand attributes");
14533 	    }
14534 	    if (pctxt->attrProhibs->nbItems != 0)
14535 		prohibs = pctxt->attrProhibs;
14536 	} else {
14537 	    if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14538 		WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14539 		NULL) == -1)
14540 	    {
14541 		PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14542 		"failed to expand attributes");
14543 	    }
14544 	}
14545     }
14546     /*
14547     * Inherit the attribute uses of the base type.
14548     */
14549     if (baseUses != NULL) {
14550 	int i, j;
14551 	xmlSchemaAttributeUseProhibPtr pro;
14552 
14553 	if (WXS_IS_RESTRICTION(type)) {
14554 	    int usesCount;
14555 	    xmlSchemaAttributeUsePtr tmp;
14556 
14557 	    if (uses != NULL)
14558 		usesCount = uses->nbItems;
14559 	    else
14560 		usesCount = 0;
14561 
14562 	    /* Restriction. */
14563 	    for (i = 0; i < baseUses->nbItems; i++) {
14564 		use = baseUses->items[i];
14565 		if (prohibs) {
14566 		    /*
14567 		    * Filter out prohibited uses.
14568 		    */
14569 		    for (j = 0; j < prohibs->nbItems; j++) {
14570 			pro = prohibs->items[j];
14571 			if ((WXS_ATTRUSE_DECL_NAME(use) == pro->name) &&
14572 			    (WXS_ATTRUSE_DECL_TNS(use) ==
14573 				pro->targetNamespace))
14574 			{
14575 			    goto inherit_next;
14576 			}
14577 		    }
14578 		}
14579 		if (usesCount) {
14580 		    /*
14581 		    * Filter out existing uses.
14582 		    */
14583 		    for (j = 0; j < usesCount; j++) {
14584 			tmp = uses->items[j];
14585 			if ((WXS_ATTRUSE_DECL_NAME(use) ==
14586 				WXS_ATTRUSE_DECL_NAME(tmp)) &&
14587 			    (WXS_ATTRUSE_DECL_TNS(use) ==
14588 				WXS_ATTRUSE_DECL_TNS(tmp)))
14589 			{
14590 			    goto inherit_next;
14591 			}
14592 		    }
14593 		}
14594 		if (uses == NULL) {
14595 		    type->attrUses = xmlSchemaItemListCreate();
14596 		    if (type->attrUses == NULL)
14597 			goto exit_failure;
14598 		    uses = type->attrUses;
14599 		}
14600 		xmlSchemaItemListAddSize(uses, 2, use);
14601 inherit_next: {}
14602 	    }
14603 	} else {
14604 	    /* Extension. */
14605 	    for (i = 0; i < baseUses->nbItems; i++) {
14606 		use = baseUses->items[i];
14607 		if (uses == NULL) {
14608 		    type->attrUses = xmlSchemaItemListCreate();
14609 		    if (type->attrUses == NULL)
14610 			goto exit_failure;
14611 		    uses = type->attrUses;
14612 		}
14613 		xmlSchemaItemListAddSize(uses, baseUses->nbItems, use);
14614 	    }
14615 	}
14616     }
14617     /*
14618     * Shrink attr. uses.
14619     */
14620     if (uses) {
14621 	if (uses->nbItems == 0) {
14622 	    xmlSchemaItemListFree(uses);
14623 	    type->attrUses = NULL;
14624 	}
14625 	/*
14626 	* TODO: We could shrink the size of the array
14627 	* to fit the actual number of items.
14628 	*/
14629     }
14630     /*
14631     * Compute the complete wildcard.
14632     */
14633     if (WXS_IS_EXTENSION(type)) {
14634 	if (baseType->attributeWildcard != NULL) {
14635 	    /*
14636 	    * (3.2.2.1) "If the `base wildcard` is non-`absent`, then
14637 	    * the appropriate case among the following:"
14638 	    */
14639 	    if (type->attributeWildcard != NULL) {
14640 		/*
14641 		* Union the complete wildcard with the base wildcard.
14642 		* SPEC {attribute wildcard}
14643 		* (3.2.2.1.2) "otherwise a wildcard whose {process contents}
14644 		* and {annotation} are those of the `complete wildcard`,
14645 		* and whose {namespace constraint} is the intensional union
14646 		* of the {namespace constraint} of the `complete wildcard`
14647 		* and of the `base wildcard`, as defined in Attribute
14648 		* Wildcard Union ($3.10.6)."
14649 		*/
14650 		if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
14651 		    baseType->attributeWildcard) == -1)
14652 		    goto exit_failure;
14653 	    } else {
14654 		/*
14655 		* (3.2.2.1.1) "If the `complete wildcard` is `absent`,
14656 		* then the `base wildcard`."
14657 		*/
14658 		type->attributeWildcard = baseType->attributeWildcard;
14659 	    }
14660 	} else {
14661 	    /*
14662 	    * (3.2.2.2) "otherwise (the `base wildcard` is `absent`) the
14663 	    * `complete wildcard`"
14664 	    * NOOP
14665 	    */
14666 	}
14667     } else {
14668 	/*
14669 	* SPEC {attribute wildcard}
14670 	* (3.1) "If the <restriction> alternative is chosen, then the
14671 	* `complete wildcard`;"
14672 	* NOOP
14673 	*/
14674     }
14675 
14676     return (0);
14677 
14678 exit_failure:
14679     return(-1);
14680 }
14681 
14682 /**
14683  * xmlSchemaTypeFinalContains:
14684  * @schema:  the schema
14685  * @type:  the type definition
14686  * @final: the final
14687  *
14688  * Evaluates if a type definition contains the given "final".
14689  * This does take "finalDefault" into account as well.
14690  *
14691  * Returns 1 if the type does contain the given "final",
14692  * 0 otherwise.
14693  */
14694 static int
xmlSchemaTypeFinalContains(xmlSchemaTypePtr type,int final)14695 xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
14696 {
14697     if (type == NULL)
14698 	return (0);
14699     if (type->flags & final)
14700 	return (1);
14701     else
14702 	return (0);
14703 }
14704 
14705 /**
14706  * xmlSchemaGetUnionSimpleTypeMemberTypes:
14707  * @type:  the Union Simple Type
14708  *
14709  * Returns a list of member types of @type if existing,
14710  * returns NULL otherwise.
14711  */
14712 static xmlSchemaTypeLinkPtr
xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)14713 xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
14714 {
14715     while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
14716 	if (type->memberTypes != NULL)
14717 	    return (type->memberTypes);
14718 	else
14719 	    type = type->baseType;
14720     }
14721     return (NULL);
14722 }
14723 
14724 #if 0
14725 /**
14726  * xmlSchemaGetParticleTotalRangeMin:
14727  * @particle: the particle
14728  *
14729  * Schema Component Constraint: Effective Total Range
14730  * (all and sequence) + (choice)
14731  *
14732  * Returns the minimum Effective Total Range.
14733  */
14734 static int
14735 xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
14736 {
14737     if ((particle->children == NULL) ||
14738 	(particle->minOccurs == 0))
14739 	return (0);
14740     if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14741 	int min = -1, cur;
14742 	xmlSchemaParticlePtr part =
14743 	    (xmlSchemaParticlePtr) particle->children->children;
14744 
14745 	if (part == NULL)
14746 	    return (0);
14747 	while (part != NULL) {
14748 	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14749 		(part->children->type == XML_SCHEMA_TYPE_ANY))
14750 		cur = part->minOccurs;
14751 	    else
14752 		cur = xmlSchemaGetParticleTotalRangeMin(part);
14753 	    if (cur == 0)
14754 		return (0);
14755 	    if ((min > cur) || (min == -1))
14756 		min = cur;
14757 	    part = (xmlSchemaParticlePtr) part->next;
14758 	}
14759 	return (particle->minOccurs * min);
14760     } else {
14761 	/* <all> and <sequence> */
14762 	int sum = 0;
14763 	xmlSchemaParticlePtr part =
14764 	    (xmlSchemaParticlePtr) particle->children->children;
14765 
14766 	if (part == NULL)
14767 	    return (0);
14768 	do {
14769 	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14770 		(part->children->type == XML_SCHEMA_TYPE_ANY))
14771 		sum += part->minOccurs;
14772 	    else
14773 		sum += xmlSchemaGetParticleTotalRangeMin(part);
14774 	    part = (xmlSchemaParticlePtr) part->next;
14775 	} while (part != NULL);
14776 	return (particle->minOccurs * sum);
14777     }
14778 }
14779 
14780 /**
14781  * xmlSchemaGetParticleTotalRangeMax:
14782  * @particle: the particle
14783  *
14784  * Schema Component Constraint: Effective Total Range
14785  * (all and sequence) + (choice)
14786  *
14787  * Returns the maximum Effective Total Range.
14788  */
14789 static int
14790 xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
14791 {
14792     if ((particle->children == NULL) ||
14793 	(particle->children->children == NULL))
14794 	return (0);
14795     if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14796 	int max = -1, cur;
14797 	xmlSchemaParticlePtr part =
14798 	    (xmlSchemaParticlePtr) particle->children->children;
14799 
14800 	for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14801 	    if (part->children == NULL)
14802 		continue;
14803 	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14804 		(part->children->type == XML_SCHEMA_TYPE_ANY))
14805 		cur = part->maxOccurs;
14806 	    else
14807 		cur = xmlSchemaGetParticleTotalRangeMax(part);
14808 	    if (cur == UNBOUNDED)
14809 		return (UNBOUNDED);
14810 	    if ((max < cur) || (max == -1))
14811 		max = cur;
14812 	}
14813 	/* TODO: Handle overflows? */
14814 	return (particle->maxOccurs * max);
14815     } else {
14816 	/* <all> and <sequence> */
14817 	int sum = 0, cur;
14818 	xmlSchemaParticlePtr part =
14819 	    (xmlSchemaParticlePtr) particle->children->children;
14820 
14821 	for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14822 	    if (part->children == NULL)
14823 		continue;
14824 	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14825 		(part->children->type == XML_SCHEMA_TYPE_ANY))
14826 		cur = part->maxOccurs;
14827 	    else
14828 		cur = xmlSchemaGetParticleTotalRangeMax(part);
14829 	    if (cur == UNBOUNDED)
14830 		return (UNBOUNDED);
14831 	    if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
14832 		return (UNBOUNDED);
14833 	    sum += cur;
14834 	}
14835 	/* TODO: Handle overflows? */
14836 	return (particle->maxOccurs * sum);
14837     }
14838 }
14839 #endif
14840 
14841 /**
14842  * xmlSchemaGetParticleEmptiable:
14843  * @particle: the particle
14844  *
14845  * Returns 1 if emptiable, 0 otherwise.
14846  */
14847 static int
xmlSchemaGetParticleEmptiable(xmlSchemaParticlePtr particle)14848 xmlSchemaGetParticleEmptiable(xmlSchemaParticlePtr particle)
14849 {
14850     xmlSchemaParticlePtr part;
14851     int emptiable;
14852 
14853     if ((particle->children == NULL) || (particle->minOccurs == 0))
14854 	return (1);
14855 
14856     part = (xmlSchemaParticlePtr) particle->children->children;
14857     if (part == NULL)
14858         return (1);
14859 
14860     while (part != NULL) {
14861         if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14862             (part->children->type == XML_SCHEMA_TYPE_ANY))
14863             emptiable = (part->minOccurs == 0);
14864         else
14865             emptiable = xmlSchemaGetParticleEmptiable(part);
14866         if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14867             if (emptiable)
14868                 return (1);
14869         } else {
14870 	    /* <all> and <sequence> */
14871             if (!emptiable)
14872                 return (0);
14873         }
14874         part = (xmlSchemaParticlePtr) part->next;
14875     }
14876 
14877     if (particle->children->type == XML_SCHEMA_TYPE_CHOICE)
14878         return (0);
14879     else
14880         return (1);
14881 }
14882 
14883 /**
14884  * xmlSchemaIsParticleEmptiable:
14885  * @particle: the particle
14886  *
14887  * Schema Component Constraint: Particle Emptiable
14888  * Checks whether the given particle is emptiable.
14889  *
14890  * Returns 1 if emptiable, 0 otherwise.
14891  */
14892 static int
xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)14893 xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
14894 {
14895     /*
14896     * SPEC (1) "Its {min occurs} is 0."
14897     */
14898     if ((particle == NULL) || (particle->minOccurs == 0) ||
14899 	(particle->children == NULL))
14900 	return (1);
14901     /*
14902     * SPEC (2) "Its {term} is a group and the minimum part of the
14903     * effective total range of that group, [...] is 0."
14904     */
14905     if (WXS_IS_MODEL_GROUP(particle->children))
14906 	return (xmlSchemaGetParticleEmptiable(particle));
14907     return (0);
14908 }
14909 
14910 /**
14911  * xmlSchemaCheckCOSSTDerivedOK:
14912  * @actxt: a context
14913  * @type:  the derived simple type definition
14914  * @baseType:  the base type definition
14915  * @subset: the subset of ('restriction', etc.)
14916  *
14917  * Schema Component Constraint:
14918  * Type Derivation OK (Simple) (cos-st-derived-OK)
14919  *
14920  * Checks whether @type can be validly
14921  * derived from @baseType.
14922  *
14923  * Returns 0 on success, an positive error code otherwise.
14924  */
14925 static int
xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,xmlSchemaTypePtr type,xmlSchemaTypePtr baseType,int subset)14926 xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
14927 			     xmlSchemaTypePtr type,
14928 			     xmlSchemaTypePtr baseType,
14929 			     int subset)
14930 {
14931     /*
14932     * 1 They are the same type definition.
14933     * TODO: The identity check might have to be more complex than this.
14934     */
14935     if (type == baseType)
14936 	return (0);
14937     /*
14938     * 2.1 restriction is not in the subset, or in the {final}
14939     * of its own {base type definition};
14940     *
14941     * NOTE that this will be used also via "xsi:type".
14942     *
14943     * TODO: Revise this, it looks strange. How can the "type"
14944     * not be fixed or *in* fixing?
14945     */
14946     if (WXS_IS_TYPE_NOT_FIXED(type))
14947 	if (xmlSchemaTypeFixup(type, actxt) == -1)
14948 	    return(-1);
14949     if (WXS_IS_TYPE_NOT_FIXED(baseType))
14950 	if (xmlSchemaTypeFixup(baseType, actxt) == -1)
14951 	    return(-1);
14952     if ((subset & SUBSET_RESTRICTION) ||
14953 	(xmlSchemaTypeFinalContains(type->baseType,
14954 	    XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
14955 	return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
14956     }
14957     /* 2.2 */
14958     if (type->baseType == baseType) {
14959 	/*
14960 	* 2.2.1 D's `base type definition` is B.
14961 	*/
14962 	return (0);
14963     }
14964     /*
14965     * 2.2.2 D's `base type definition` is not the `ur-type definition`
14966     * and is validly derived from B given the subset, as defined by this
14967     * constraint.
14968     */
14969     if ((! WXS_IS_ANYTYPE(type->baseType)) &&
14970 	(xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
14971 	    baseType, subset) == 0)) {
14972 	return (0);
14973     }
14974     /*
14975     * 2.2.3 D's {variety} is list or union and B is the `simple ur-type
14976     * definition`.
14977     */
14978     if (WXS_IS_ANY_SIMPLE_TYPE(baseType) &&
14979 	(WXS_IS_LIST(type) || WXS_IS_UNION(type))) {
14980 	return (0);
14981     }
14982     /*
14983     * 2.2.4 B's {variety} is union and D is validly derived from a type
14984     * definition in B's {member type definitions} given the subset, as
14985     * defined by this constraint.
14986     *
14987     * NOTE: This seems not to involve built-in types, since there is no
14988     * built-in Union Simple Type.
14989     */
14990     if (WXS_IS_UNION(baseType)) {
14991 	xmlSchemaTypeLinkPtr cur;
14992 
14993 	cur = baseType->memberTypes;
14994 	while (cur != NULL) {
14995 	    if (WXS_IS_TYPE_NOT_FIXED(cur->type))
14996 		if (xmlSchemaTypeFixup(cur->type, actxt) == -1)
14997 		    return(-1);
14998 	    if (xmlSchemaCheckCOSSTDerivedOK(actxt,
14999 		    type, cur->type, subset) == 0)
15000 	    {
15001 		/*
15002 		* It just has to be validly derived from at least one
15003 		* member-type.
15004 		*/
15005 		return (0);
15006 	    }
15007 	    cur = cur->next;
15008 	}
15009     }
15010     return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
15011 }
15012 
15013 /**
15014  * xmlSchemaCheckTypeDefCircularInternal:
15015  * @pctxt:  the schema parser context
15016  * @ctxtType:  the type definition
15017  * @ancestor: an ancestor of @ctxtType
15018  *
15019  * Checks st-props-correct (2) + ct-props-correct (3).
15020  * Circular type definitions are not allowed.
15021  *
15022  * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
15023  * circular, 0 otherwise.
15024  */
15025 static int
xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr ctxtType,xmlSchemaTypePtr ancestor)15026 xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
15027 			   xmlSchemaTypePtr ctxtType,
15028 			   xmlSchemaTypePtr ancestor)
15029 {
15030     int ret;
15031 
15032     if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
15033 	return (0);
15034 
15035     if (ctxtType == ancestor) {
15036 	xmlSchemaPCustomErr(pctxt,
15037 	    XML_SCHEMAP_ST_PROPS_CORRECT_2,
15038 	    WXS_BASIC_CAST ctxtType, WXS_ITEM_NODE(ctxtType),
15039 	    "The definition is circular", NULL);
15040 	return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
15041     }
15042     if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
15043 	/*
15044 	* Avoid infinite recursion on circular types not yet checked.
15045 	*/
15046 	return (0);
15047     }
15048     ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
15049     ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
15050 	ancestor->baseType);
15051     ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
15052     return (ret);
15053 }
15054 
15055 /**
15056  * xmlSchemaCheckTypeDefCircular:
15057  * @item:  the complex/simple type definition
15058  * @ctxt:  the parser context
15059  * @name:  the name
15060  *
15061  * Checks for circular type definitions.
15062  */
15063 static void
xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,xmlSchemaParserCtxtPtr ctxt)15064 xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
15065 			      xmlSchemaParserCtxtPtr ctxt)
15066 {
15067     if ((item == NULL) ||
15068 	(item->type == XML_SCHEMA_TYPE_BASIC) ||
15069 	(item->baseType == NULL))
15070 	return;
15071     xmlSchemaCheckTypeDefCircularInternal(ctxt, item,
15072 	item->baseType);
15073 }
15074 
15075 /*
15076 * Simple Type Definition Representation OK (src-simple-type) 4
15077 *
15078 * "4 Circular union type definition is disallowed. That is, if the
15079 * <union> alternative is chosen, there must not be any entries in the
15080 * memberTypes [attribute] at any depth which resolve to the component
15081 * corresponding to the <simpleType>."
15082 *
15083 * Note that this should work on the *representation* of a component,
15084 * thus assumes any union types in the member types not being yet
15085 * substituted. At this stage we need the variety of the types
15086 * to be already computed.
15087 */
15088 static int
xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr ctxType,xmlSchemaTypeLinkPtr members)15089 xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,
15090 					xmlSchemaTypePtr ctxType,
15091 					xmlSchemaTypeLinkPtr members)
15092 {
15093     xmlSchemaTypeLinkPtr member;
15094     xmlSchemaTypePtr memberType;
15095 
15096     member = members;
15097     while (member != NULL) {
15098 	memberType = member->type;
15099 	while ((memberType != NULL) &&
15100 	    (memberType->type != XML_SCHEMA_TYPE_BASIC)) {
15101 	    if (memberType == ctxType) {
15102 		xmlSchemaPCustomErr(pctxt,
15103 		    XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
15104 		    WXS_BASIC_CAST ctxType, NULL,
15105 		    "The union type definition is circular", NULL);
15106 		return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
15107 	    }
15108 	    if ((WXS_IS_UNION(memberType)) &&
15109 		((memberType->flags & XML_SCHEMAS_TYPE_MARKED) == 0))
15110 	    {
15111 		int res;
15112 		memberType->flags |= XML_SCHEMAS_TYPE_MARKED;
15113 		res = xmlSchemaCheckUnionTypeDefCircularRecur(pctxt,
15114 		    ctxType,
15115 		    xmlSchemaGetUnionSimpleTypeMemberTypes(memberType));
15116 		memberType->flags ^= XML_SCHEMAS_TYPE_MARKED;
15117 		if (res != 0)
15118 		    return(res);
15119 	    }
15120 	    memberType = memberType->baseType;
15121 	}
15122 	member = member->next;
15123     }
15124     return(0);
15125 }
15126 
15127 static int
xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)15128 xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,
15129 				   xmlSchemaTypePtr type)
15130 {
15131     if (! WXS_IS_UNION(type))
15132 	return(0);
15133     return(xmlSchemaCheckUnionTypeDefCircularRecur(pctxt, type,
15134 	type->memberTypes));
15135 }
15136 
15137 /**
15138  * xmlSchemaResolveTypeReferences:
15139  * @item:  the complex/simple type definition
15140  * @ctxt:  the parser context
15141  * @name:  the name
15142  *
15143  * Resolves type definition references
15144  */
15145 static void
xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,xmlSchemaParserCtxtPtr ctxt)15146 xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,
15147 			 xmlSchemaParserCtxtPtr ctxt)
15148 {
15149     if (typeDef == NULL)
15150 	return;
15151 
15152     /*
15153     * Resolve the base type.
15154     */
15155     if (typeDef->baseType == NULL) {
15156 	typeDef->baseType = xmlSchemaGetType(ctxt->schema,
15157 	    typeDef->base, typeDef->baseNs);
15158 	if (typeDef->baseType == NULL) {
15159 	    xmlSchemaPResCompAttrErr(ctxt,
15160 		XML_SCHEMAP_SRC_RESOLVE,
15161 		WXS_BASIC_CAST typeDef, typeDef->node,
15162 		"base", typeDef->base, typeDef->baseNs,
15163 		XML_SCHEMA_TYPE_SIMPLE, NULL);
15164 	    return;
15165 	}
15166     }
15167     if (WXS_IS_SIMPLE(typeDef)) {
15168 	if (WXS_IS_UNION(typeDef)) {
15169 	    /*
15170 	    * Resolve the memberTypes.
15171 	    */
15172 	    xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
15173 	    return;
15174 	} else if (WXS_IS_LIST(typeDef)) {
15175 	    /*
15176 	    * Resolve the itemType.
15177 	    */
15178 	    if ((typeDef->subtypes == NULL) && (typeDef->base != NULL)) {
15179 
15180 		typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
15181 		    typeDef->base, typeDef->baseNs);
15182 
15183 		if ((typeDef->subtypes == NULL) ||
15184 		    (! WXS_IS_SIMPLE(typeDef->subtypes)))
15185 		{
15186 		    typeDef->subtypes = NULL;
15187 		    xmlSchemaPResCompAttrErr(ctxt,
15188 			XML_SCHEMAP_SRC_RESOLVE,
15189 			WXS_BASIC_CAST typeDef, typeDef->node,
15190 			"itemType", typeDef->base, typeDef->baseNs,
15191 			XML_SCHEMA_TYPE_SIMPLE, NULL);
15192 		}
15193 	    }
15194 	    return;
15195 	}
15196     }
15197     /*
15198     * The ball of letters below means, that if we have a particle
15199     * which has a QName-helper component as its {term}, we want
15200     * to resolve it...
15201     */
15202     else if ((WXS_TYPE_CONTENTTYPE(typeDef) != NULL) &&
15203 	((WXS_TYPE_CONTENTTYPE(typeDef))->type ==
15204 	    XML_SCHEMA_TYPE_PARTICLE) &&
15205 	(WXS_TYPE_PARTICLE_TERM(typeDef) != NULL) &&
15206 	((WXS_TYPE_PARTICLE_TERM(typeDef))->type ==
15207 	    XML_SCHEMA_EXTRA_QNAMEREF))
15208     {
15209 	xmlSchemaQNameRefPtr ref =
15210 	    WXS_QNAME_CAST WXS_TYPE_PARTICLE_TERM(typeDef);
15211 	xmlSchemaModelGroupDefPtr groupDef;
15212 
15213 	/*
15214 	* URGENT TODO: Test this.
15215 	*/
15216 	WXS_TYPE_PARTICLE_TERM(typeDef) = NULL;
15217 	/*
15218 	* Resolve the MG definition reference.
15219 	*/
15220 	groupDef =
15221 	    WXS_MODEL_GROUPDEF_CAST xmlSchemaGetNamedComponent(ctxt->schema,
15222 		ref->itemType, ref->name, ref->targetNamespace);
15223 	if (groupDef == NULL) {
15224 	    xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
15225 		NULL, WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)),
15226 		"ref", ref->name, ref->targetNamespace, ref->itemType,
15227 		NULL);
15228 	    /* Remove the particle. */
15229 	    WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15230 	} else if (WXS_MODELGROUPDEF_MODEL(groupDef) == NULL)
15231 	    /* Remove the particle. */
15232 	    WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15233 	else {
15234 	    /*
15235 	    * Assign the MG definition's {model group} to the
15236 	    * particle's {term}.
15237 	    */
15238 	    WXS_TYPE_PARTICLE_TERM(typeDef) = WXS_MODELGROUPDEF_MODEL(groupDef);
15239 
15240 	    if (WXS_MODELGROUPDEF_MODEL(groupDef)->type == XML_SCHEMA_TYPE_ALL) {
15241 		/*
15242 		* SPEC cos-all-limited (1.2)
15243 		* "1.2 the {term} property of a particle with
15244 		* {max occurs}=1 which is part of a pair which constitutes
15245 		* the {content type} of a complex type definition."
15246 		*/
15247 		if ((WXS_TYPE_PARTICLE(typeDef))->maxOccurs != 1) {
15248 		    xmlSchemaCustomErr(ACTXT_CAST ctxt,
15249 			/* TODO: error code */
15250 			XML_SCHEMAP_COS_ALL_LIMITED,
15251 			WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)), NULL,
15252 			"The particle's {max occurs} must be 1, since the "
15253 			"reference resolves to an 'all' model group",
15254 			NULL, NULL);
15255 		}
15256 	    }
15257 	}
15258     }
15259 }
15260 
15261 
15262 
15263 /**
15264  * xmlSchemaCheckSTPropsCorrect:
15265  * @ctxt:  the schema parser context
15266  * @type:  the simple type definition
15267  *
15268  * Checks st-props-correct.
15269  *
15270  * Returns 0 if the properties are correct,
15271  * if not, a positive error code and -1 on internal
15272  * errors.
15273  */
15274 static int
xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)15275 xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
15276 			     xmlSchemaTypePtr type)
15277 {
15278     xmlSchemaTypePtr baseType = type->baseType;
15279     xmlChar *str = NULL;
15280 
15281     /* STATE: error funcs converted. */
15282     /*
15283     * Schema Component Constraint: Simple Type Definition Properties Correct
15284     *
15285     * NOTE: This is somehow redundant, since we actually built a simple type
15286     * to have all the needed information; this acts as an self test.
15287     */
15288     /* Base type: If the datatype has been `derived` by `restriction`
15289     * then the Simple Type Definition component from which it is `derived`,
15290     * otherwise the Simple Type Definition for anySimpleType ($4.1.6).
15291     */
15292     if (baseType == NULL) {
15293 	/*
15294 	* TODO: Think about: "modulo the impact of Missing
15295 	* Sub-components ($5.3)."
15296 	*/
15297 	xmlSchemaPCustomErr(ctxt,
15298 	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15299 	    WXS_BASIC_CAST type, NULL,
15300 	    "No base type existent", NULL);
15301 	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15302 
15303     }
15304     if (! WXS_IS_SIMPLE(baseType)) {
15305 	xmlSchemaPCustomErr(ctxt,
15306 	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15307 	    WXS_BASIC_CAST type, NULL,
15308 	    "The base type '%s' is not a simple type",
15309 	    xmlSchemaGetComponentQName(&str, baseType));
15310 	FREE_AND_NULL(str)
15311 	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15312     }
15313     if ((WXS_IS_LIST(type) || WXS_IS_UNION(type)) &&
15314 	(WXS_IS_RESTRICTION(type) == 0) &&
15315 	((! WXS_IS_ANY_SIMPLE_TYPE(baseType)) &&
15316          (baseType->type != XML_SCHEMA_TYPE_SIMPLE))) {
15317 	xmlSchemaPCustomErr(ctxt,
15318 	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15319 	    WXS_BASIC_CAST type, NULL,
15320 	    "A type, derived by list or union, must have "
15321 	    "the simple ur-type definition as base type, not '%s'",
15322 	    xmlSchemaGetComponentQName(&str, baseType));
15323 	FREE_AND_NULL(str)
15324 	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15325     }
15326     /*
15327     * Variety: One of {atomic, list, union}.
15328     */
15329     if ((! WXS_IS_ATOMIC(type)) && (! WXS_IS_UNION(type)) &&
15330 	(! WXS_IS_LIST(type))) {
15331 	xmlSchemaPCustomErr(ctxt,
15332 	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15333 	    WXS_BASIC_CAST type, NULL,
15334 	    "The variety is absent", NULL);
15335 	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15336     }
15337     /* TODO: Finish this. Hmm, is this finished? */
15338 
15339     /*
15340     * 3 The {final} of the {base type definition} must not contain restriction.
15341     */
15342     if (xmlSchemaTypeFinalContains(baseType,
15343 	XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15344 	xmlSchemaPCustomErr(ctxt,
15345 	    XML_SCHEMAP_ST_PROPS_CORRECT_3,
15346 	    WXS_BASIC_CAST type, NULL,
15347 	    "The 'final' of its base type '%s' must not contain "
15348 	    "'restriction'",
15349 	    xmlSchemaGetComponentQName(&str, baseType));
15350 	FREE_AND_NULL(str)
15351 	return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
15352     }
15353 
15354     /*
15355     * 2 All simple type definitions must be derived ultimately from the `simple
15356     * ur-type definition` (so circular definitions are disallowed). That is, it
15357     * must be possible to reach a built-in primitive datatype or the `simple
15358     * ur-type definition` by repeatedly following the {base type definition}.
15359     *
15360     * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
15361     */
15362     return (0);
15363 }
15364 
15365 /**
15366  * xmlSchemaCheckCOSSTRestricts:
15367  * @ctxt:  the schema parser context
15368  * @type:  the simple type definition
15369  *
15370  * Schema Component Constraint:
15371  * Derivation Valid (Restriction, Simple) (cos-st-restricts)
15372 
15373  * Checks if the given @type (simpleType) is derived validly by restriction.
15374  * STATUS:
15375  *
15376  * Returns -1 on internal errors, 0 if the type is validly derived,
15377  * a positive error code otherwise.
15378  */
15379 static int
xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)15380 xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
15381 			     xmlSchemaTypePtr type)
15382 {
15383     xmlChar *str = NULL;
15384 
15385     if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
15386 	PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15387 	    "given type is not a user-derived simpleType");
15388 	return (-1);
15389     }
15390 
15391     if (WXS_IS_ATOMIC(type)) {
15392 	xmlSchemaTypePtr primitive;
15393 	/*
15394 	* 1.1 The {base type definition} must be an atomic simple
15395 	* type definition or a built-in primitive datatype.
15396 	*/
15397 	if (! WXS_IS_ATOMIC(type->baseType)) {
15398 	    xmlSchemaPCustomErr(pctxt,
15399 		XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
15400 		WXS_BASIC_CAST type, NULL,
15401 		"The base type '%s' is not an atomic simple type",
15402 		xmlSchemaGetComponentQName(&str, type->baseType));
15403 	    FREE_AND_NULL(str)
15404 	    return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
15405 	}
15406 	/* 1.2 The {final} of the {base type definition} must not contain
15407 	* restriction.
15408 	*/
15409 	/* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
15410 	if (xmlSchemaTypeFinalContains(type->baseType,
15411 	    XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15412 	    xmlSchemaPCustomErr(pctxt,
15413 		XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
15414 		WXS_BASIC_CAST type, NULL,
15415 		"The final of its base type '%s' must not contain 'restriction'",
15416 		xmlSchemaGetComponentQName(&str, type->baseType));
15417 	    FREE_AND_NULL(str)
15418 	    return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
15419 	}
15420 
15421 	/*
15422 	* 1.3.1 DF must be an allowed constraining facet for the {primitive
15423 	* type definition}, as specified in the appropriate subsection of 3.2
15424 	* Primitive datatypes.
15425 	*/
15426 	if (type->facets != NULL) {
15427 	    xmlSchemaFacetPtr facet;
15428 	    int ok = 1;
15429 
15430 	    primitive = xmlSchemaGetPrimitiveType(type);
15431 	    if (primitive == NULL) {
15432 		PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15433 		    "failed to get primitive type");
15434 		return (-1);
15435 	    }
15436 	    facet = type->facets;
15437 	    do {
15438 		if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
15439 		    ok = 0;
15440 		    xmlSchemaPIllegalFacetAtomicErr(pctxt,
15441 			XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
15442 			type, primitive, facet);
15443 		}
15444 		facet = facet->next;
15445 	    } while (facet != NULL);
15446 	    if (ok == 0)
15447 		return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
15448 	}
15449 	/*
15450 	* SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
15451 	* of the {base type definition} (call this BF),then the DF's {value}
15452 	* must be a valid restriction of BF's {value} as defined in
15453 	* [XML Schemas: Datatypes]."
15454 	*
15455 	* NOTE (1.3.2) Facet derivation constraints are currently handled in
15456 	* xmlSchemaDeriveAndValidateFacets()
15457 	*/
15458     } else if (WXS_IS_LIST(type)) {
15459 	xmlSchemaTypePtr itemType = NULL;
15460 
15461 	itemType = type->subtypes;
15462 	if ((itemType == NULL) || (! WXS_IS_SIMPLE(itemType))) {
15463 	    PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15464 		"failed to evaluate the item type");
15465 	    return (-1);
15466 	}
15467 	if (WXS_IS_TYPE_NOT_FIXED(itemType))
15468 	    xmlSchemaTypeFixup(itemType, ACTXT_CAST pctxt);
15469 	/*
15470 	* 2.1 The {item type definition} must have a {variety} of atomic or
15471 	* union (in which case all the {member type definitions}
15472 	* must be atomic).
15473 	*/
15474 	if ((! WXS_IS_ATOMIC(itemType)) &&
15475 	    (! WXS_IS_UNION(itemType))) {
15476 	    xmlSchemaPCustomErr(pctxt,
15477 		XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15478 		WXS_BASIC_CAST type, NULL,
15479 		"The item type '%s' does not have a variety of atomic or union",
15480 		xmlSchemaGetComponentQName(&str, itemType));
15481 	    FREE_AND_NULL(str)
15482 	    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15483 	} else if (WXS_IS_UNION(itemType)) {
15484 	    xmlSchemaTypeLinkPtr member;
15485 
15486 	    member = itemType->memberTypes;
15487 	    while (member != NULL) {
15488 		if (! WXS_IS_ATOMIC(member->type)) {
15489 		    xmlSchemaPCustomErr(pctxt,
15490 			XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15491 			WXS_BASIC_CAST type, NULL,
15492 			"The item type is a union type, but the "
15493 			"member type '%s' of this item type is not atomic",
15494 			xmlSchemaGetComponentQName(&str, member->type));
15495 		    FREE_AND_NULL(str)
15496 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15497 		}
15498 		member = member->next;
15499 	    }
15500 	}
15501 
15502 	if (WXS_IS_ANY_SIMPLE_TYPE(type->baseType)) {
15503 	    xmlSchemaFacetPtr facet;
15504 	    /*
15505 	    * This is the case if we have: <simpleType><list ..
15506 	    */
15507 	    /*
15508 	    * 2.3.1
15509 	    * 2.3.1.1 The {final} of the {item type definition} must not
15510 	    * contain list.
15511 	    */
15512 	    if (xmlSchemaTypeFinalContains(itemType,
15513 		XML_SCHEMAS_TYPE_FINAL_LIST)) {
15514 		xmlSchemaPCustomErr(pctxt,
15515 		    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
15516 		    WXS_BASIC_CAST type, NULL,
15517 		    "The final of its item type '%s' must not contain 'list'",
15518 		    xmlSchemaGetComponentQName(&str, itemType));
15519 		FREE_AND_NULL(str)
15520 		return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
15521 	    }
15522 	    /*
15523 	    * 2.3.1.2 The {facets} must only contain the whiteSpace
15524 	    * facet component.
15525 	    * OPTIMIZE TODO: the S4S already disallows any facet
15526 	    * to be specified.
15527 	    */
15528 	    if (type->facets != NULL) {
15529 		facet = type->facets;
15530 		do {
15531 		    if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
15532 			xmlSchemaPIllegalFacetListUnionErr(pctxt,
15533 			    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
15534 			    type, facet);
15535 			return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
15536 		    }
15537 		    facet = facet->next;
15538 		} while (facet != NULL);
15539 	    }
15540 	    /*
15541 	    * MAYBE TODO: (Hmm, not really) Datatypes states:
15542 	    * A `list` datatype can be `derived` from an `atomic` datatype
15543 	    * whose `lexical space` allows space (such as string or anyURI)or
15544 	    * a `union` datatype any of whose {member type definitions}'s
15545 	    * `lexical space` allows space.
15546 	    */
15547 	} else {
15548 	    /*
15549 	    * This is the case if we have: <simpleType><restriction ...
15550 	    * I.e. the variety of "list" is inherited.
15551 	    */
15552 	    /*
15553 	    * 2.3.2
15554 	    * 2.3.2.1 The {base type definition} must have a {variety} of list.
15555 	    */
15556 	    if (! WXS_IS_LIST(type->baseType)) {
15557 		xmlSchemaPCustomErr(pctxt,
15558 		    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
15559 		    WXS_BASIC_CAST type, NULL,
15560 		    "The base type '%s' must be a list type",
15561 		    xmlSchemaGetComponentQName(&str, type->baseType));
15562 		FREE_AND_NULL(str)
15563 		return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
15564 	    }
15565 	    /*
15566 	    * 2.3.2.2 The {final} of the {base type definition} must not
15567 	    * contain restriction.
15568 	    */
15569 	    if (xmlSchemaTypeFinalContains(type->baseType,
15570 		XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15571 		xmlSchemaPCustomErr(pctxt,
15572 		    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
15573 		    WXS_BASIC_CAST type, NULL,
15574 		    "The 'final' of the base type '%s' must not contain 'restriction'",
15575 		    xmlSchemaGetComponentQName(&str, type->baseType));
15576 		FREE_AND_NULL(str)
15577 		return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
15578 	    }
15579 	    /*
15580 	    * 2.3.2.3 The {item type definition} must be validly derived
15581 	    * from the {base type definition}'s {item type definition} given
15582 	    * the empty set, as defined in Type Derivation OK (Simple) ($3.14.6).
15583 	    */
15584 	    {
15585 		xmlSchemaTypePtr baseItemType;
15586 
15587 		baseItemType = type->baseType->subtypes;
15588 		if ((baseItemType == NULL) || (! WXS_IS_SIMPLE(baseItemType))) {
15589 		    PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15590 			"failed to eval the item type of a base type");
15591 		    return (-1);
15592 		}
15593 		if ((itemType != baseItemType) &&
15594 		    (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt, itemType,
15595 			baseItemType, 0) != 0)) {
15596 		    xmlChar *strBIT = NULL, *strBT = NULL;
15597 		    xmlSchemaPCustomErrExt(pctxt,
15598 			XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
15599 			WXS_BASIC_CAST type, NULL,
15600 			"The item type '%s' is not validly derived from "
15601 			"the item type '%s' of the base type '%s'",
15602 			xmlSchemaGetComponentQName(&str, itemType),
15603 			xmlSchemaGetComponentQName(&strBIT, baseItemType),
15604 			xmlSchemaGetComponentQName(&strBT, type->baseType));
15605 
15606 		    FREE_AND_NULL(str)
15607 		    FREE_AND_NULL(strBIT)
15608 		    FREE_AND_NULL(strBT)
15609 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
15610 		}
15611 	    }
15612 
15613 	    if (type->facets != NULL) {
15614 		xmlSchemaFacetPtr facet;
15615 		int ok = 1;
15616 		/*
15617 		* 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
15618 		* and enumeration facet components are allowed among the {facets}.
15619 		*/
15620 		facet = type->facets;
15621 		do {
15622 		    switch (facet->type) {
15623 			case XML_SCHEMA_FACET_LENGTH:
15624 			case XML_SCHEMA_FACET_MINLENGTH:
15625 			case XML_SCHEMA_FACET_MAXLENGTH:
15626 			case XML_SCHEMA_FACET_WHITESPACE:
15627 			    /*
15628 			    * TODO: 2.5.1.2 List datatypes
15629 			    * The value of `whiteSpace` is fixed to the value collapse.
15630 			    */
15631 			case XML_SCHEMA_FACET_PATTERN:
15632 			case XML_SCHEMA_FACET_ENUMERATION:
15633 			    break;
15634 			default: {
15635 			    xmlSchemaPIllegalFacetListUnionErr(pctxt,
15636 				XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
15637 				type, facet);
15638 			    /*
15639 			    * We could return, but it's nicer to report all
15640 			    * invalid facets.
15641 			    */
15642 			    ok = 0;
15643 			}
15644 		    }
15645 		    facet = facet->next;
15646 		} while (facet != NULL);
15647 		if (ok == 0)
15648 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
15649 		/*
15650 		* SPEC (2.3.2.5) (same as 1.3.2)
15651 		*
15652 		* NOTE (2.3.2.5) This is currently done in
15653 		* xmlSchemaDeriveAndValidateFacets()
15654 		*/
15655 	    }
15656 	}
15657     } else if (WXS_IS_UNION(type)) {
15658 	/*
15659 	* 3.1 The {member type definitions} must all have {variety} of
15660 	* atomic or list.
15661 	*/
15662 	xmlSchemaTypeLinkPtr member;
15663 
15664 	member = type->memberTypes;
15665 	while (member != NULL) {
15666 	    if (WXS_IS_TYPE_NOT_FIXED(member->type))
15667 		xmlSchemaTypeFixup(member->type, ACTXT_CAST pctxt);
15668 
15669 	    if ((! WXS_IS_ATOMIC(member->type)) &&
15670 		(! WXS_IS_LIST(member->type))) {
15671 		xmlSchemaPCustomErr(pctxt,
15672 		    XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
15673 		    WXS_BASIC_CAST type, NULL,
15674 		    "The member type '%s' is neither an atomic, nor a list type",
15675 		    xmlSchemaGetComponentQName(&str, member->type));
15676 		FREE_AND_NULL(str)
15677 		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
15678 	    }
15679 	    member = member->next;
15680 	}
15681 	/*
15682 	* 3.3.1 If the {base type definition} is the `simple ur-type
15683 	* definition`
15684 	*/
15685 	if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
15686 	    /*
15687 	    * 3.3.1.1 All of the {member type definitions} must have a
15688 	    * {final} which does not contain union.
15689 	    */
15690 	    member = type->memberTypes;
15691 	    while (member != NULL) {
15692 		if (xmlSchemaTypeFinalContains(member->type,
15693 		    XML_SCHEMAS_TYPE_FINAL_UNION)) {
15694 		    xmlSchemaPCustomErr(pctxt,
15695 			XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
15696 			WXS_BASIC_CAST type, NULL,
15697 			"The 'final' of member type '%s' contains 'union'",
15698 			xmlSchemaGetComponentQName(&str, member->type));
15699 		    FREE_AND_NULL(str)
15700 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
15701 		}
15702 		member = member->next;
15703 	    }
15704 	    /*
15705 	    * 3.3.1.2 The {facets} must be empty.
15706 	    */
15707 	    if (type->facetSet != NULL) {
15708 		xmlSchemaPCustomErr(pctxt,
15709 		    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
15710 		    WXS_BASIC_CAST type, NULL,
15711 		    "No facets allowed", NULL);
15712 		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
15713 	    }
15714 	} else {
15715 	    /*
15716 	    * 3.3.2.1 The {base type definition} must have a {variety} of union.
15717 	    * I.e. the variety of "list" is inherited.
15718 	    */
15719 	    if (! WXS_IS_UNION(type->baseType)) {
15720 		xmlSchemaPCustomErr(pctxt,
15721 		    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
15722 		    WXS_BASIC_CAST type, NULL,
15723 		    "The base type '%s' is not a union type",
15724 		    xmlSchemaGetComponentQName(&str, type->baseType));
15725 		FREE_AND_NULL(str)
15726 		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
15727 	    }
15728 	    /*
15729 	    * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
15730 	    */
15731 	    if (xmlSchemaTypeFinalContains(type->baseType,
15732 		XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15733 		xmlSchemaPCustomErr(pctxt,
15734 		    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
15735 		    WXS_BASIC_CAST type, NULL,
15736 		    "The 'final' of its base type '%s' must not contain 'restriction'",
15737 		    xmlSchemaGetComponentQName(&str, type->baseType));
15738 		FREE_AND_NULL(str)
15739 		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
15740 	    }
15741 	    /*
15742 	    * 3.3.2.3 The {member type definitions}, in order, must be validly
15743 	    * derived from the corresponding type definitions in the {base
15744 	    * type definition}'s {member type definitions} given the empty set,
15745 	    * as defined in Type Derivation OK (Simple) ($3.14.6).
15746 	    */
15747 	    {
15748 		xmlSchemaTypeLinkPtr baseMember;
15749 
15750 		/*
15751 		* OPTIMIZE: if the type is restricting, it has no local defined
15752 		* member types and inherits the member types of the base type;
15753 		* thus a check for equality can be skipped.
15754 		*/
15755 		/*
15756 		* Even worse: I cannot see a scenario where a restricting
15757 		* union simple type can have other member types as the member
15758 		* types of it's base type. This check seems not necessary with
15759 		* respect to the derivation process in libxml2.
15760 		* But necessary if constructing types with an API.
15761 		*/
15762 		if (type->memberTypes != NULL) {
15763 		    member = type->memberTypes;
15764 		    baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
15765 		    if ((member == NULL) && (baseMember != NULL)) {
15766 			PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15767 			    "different number of member types in base");
15768 		    }
15769 		    while (member != NULL) {
15770 			if (baseMember == NULL) {
15771 			    PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15772 			    "different number of member types in base");
15773 			} else if ((member->type != baseMember->type) &&
15774 			    (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
15775 				member->type, baseMember->type, 0) != 0)) {
15776 			    xmlChar *strBMT = NULL, *strBT = NULL;
15777 
15778 			    xmlSchemaPCustomErrExt(pctxt,
15779 				XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
15780 				WXS_BASIC_CAST type, NULL,
15781 				"The member type %s is not validly "
15782 				"derived from its corresponding member "
15783 				"type %s of the base type %s",
15784 				xmlSchemaGetComponentQName(&str, member->type),
15785 				xmlSchemaGetComponentQName(&strBMT, baseMember->type),
15786 				xmlSchemaGetComponentQName(&strBT, type->baseType));
15787 			    FREE_AND_NULL(str)
15788 			    FREE_AND_NULL(strBMT)
15789 			    FREE_AND_NULL(strBT)
15790 			    return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
15791 			}
15792 			member = member->next;
15793                         if (baseMember != NULL)
15794                             baseMember = baseMember->next;
15795 		    }
15796 		}
15797 	    }
15798 	    /*
15799 	    * 3.3.2.4 Only pattern and enumeration facet components are
15800 	    * allowed among the {facets}.
15801 	    */
15802 	    if (type->facets != NULL) {
15803 		xmlSchemaFacetPtr facet;
15804 		int ok = 1;
15805 
15806 		facet = type->facets;
15807 		do {
15808 		    if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
15809 			(facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
15810 			xmlSchemaPIllegalFacetListUnionErr(pctxt,
15811 				XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
15812 				type, facet);
15813 			ok = 0;
15814 		    }
15815 		    facet = facet->next;
15816 		} while (facet != NULL);
15817 		if (ok == 0)
15818 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
15819 
15820 	    }
15821 	    /*
15822 	    * SPEC (3.3.2.5) (same as 1.3.2)
15823 	    *
15824 	    * NOTE (3.3.2.5) This is currently done in
15825 	    * xmlSchemaDeriveAndValidateFacets()
15826 	    */
15827 	}
15828     }
15829 
15830     return (0);
15831 }
15832 
15833 /**
15834  * xmlSchemaCheckSRCSimpleType:
15835  * @ctxt:  the schema parser context
15836  * @type:  the simple type definition
15837  *
15838  * Checks crc-simple-type constraints.
15839  *
15840  * Returns 0 if the constraints are satisfied,
15841  * if not a positive error code and -1 on internal
15842  * errors.
15843  */
15844 #if 0
15845 static int
15846 xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
15847 			    xmlSchemaTypePtr type)
15848 {
15849     /*
15850     * src-simple-type.1 The corresponding simple type definition, if any,
15851     * must satisfy the conditions set out in Constraints on Simple Type
15852     * Definition Schema Components ($3.14.6).
15853     */
15854     if (WXS_IS_RESTRICTION(type)) {
15855 	/*
15856 	* src-simple-type.2 "If the <restriction> alternative is chosen,
15857 	* either it must have a base [attribute] or a <simpleType> among its
15858 	* [children], but not both."
15859 	* NOTE: This is checked in the parse function of <restriction>.
15860 	*/
15861 	/*
15862 	*
15863 	*/
15864     } else if (WXS_IS_LIST(type)) {
15865 	/* src-simple-type.3 "If the <list> alternative is chosen, either it must have
15866 	* an itemType [attribute] or a <simpleType> among its [children],
15867 	* but not both."
15868 	*
15869 	* NOTE: This is checked in the parse function of <list>.
15870 	*/
15871     } else if (WXS_IS_UNION(type)) {
15872 	/*
15873 	* src-simple-type.4 is checked in xmlSchemaCheckUnionTypeDefCircular().
15874 	*/
15875     }
15876     return (0);
15877 }
15878 #endif
15879 
15880 static int
xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)15881 xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
15882 {
15883    if (ctxt->vctxt == NULL) {
15884 	ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
15885 	if (ctxt->vctxt == NULL) {
15886 	    xmlSchemaPErr(ctxt, NULL,
15887 		XML_SCHEMAP_INTERNAL,
15888 		"Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
15889 		"failed to create a temp. validation context.\n",
15890 		NULL, NULL);
15891 	    return (-1);
15892 	}
15893 	/* TODO: Pass user data. */
15894 	xmlSchemaSetValidErrors(ctxt->vctxt,
15895 	    ctxt->error, ctxt->warning, ctxt->errCtxt);
15896 	xmlSchemaSetValidStructuredErrors(ctxt->vctxt,
15897 	    ctxt->serror, ctxt->errCtxt);
15898     }
15899     return (0);
15900 }
15901 
15902 static int
15903 xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
15904 			     xmlNodePtr node,
15905 			     xmlSchemaTypePtr type,
15906 			     const xmlChar *value,
15907 			     xmlSchemaValPtr *retVal,
15908 			     int fireErrors,
15909 			     int normalize,
15910 			     int isNormalized);
15911 
15912 /**
15913  * xmlSchemaParseCheckCOSValidDefault:
15914  * @pctxt:  the schema parser context
15915  * @type:  the simple type definition
15916  * @value: the default value
15917  * @node: an optional node (the holder of the value)
15918  *
15919  * Schema Component Constraint: Element Default Valid (Immediate)
15920  * (cos-valid-default)
15921  * This will be used by the parser only. For the validator there's
15922  * an other version.
15923  *
15924  * Returns 0 if the constraints are satisfied,
15925  * if not, a positive error code and -1 on internal
15926  * errors.
15927  */
15928 static int
xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,xmlNodePtr node,xmlSchemaTypePtr type,const xmlChar * value,xmlSchemaValPtr * val)15929 xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
15930 				   xmlNodePtr node,
15931 				   xmlSchemaTypePtr type,
15932 				   const xmlChar *value,
15933 				   xmlSchemaValPtr *val)
15934 {
15935     int ret = 0;
15936 
15937     /*
15938     * cos-valid-default:
15939     * Schema Component Constraint: Element Default Valid (Immediate)
15940     * For a string to be a valid default with respect to a type
15941     * definition the appropriate case among the following must be true:
15942     */
15943     if WXS_IS_COMPLEX(type) {
15944 	/*
15945 	* Complex type.
15946 	*
15947 	* SPEC (2.1) "its {content type} must be a simple type definition
15948 	* or mixed."
15949 	* SPEC (2.2.2) "If the {content type} is mixed, then the {content
15950 	* type}'s particle must be `emptiable` as defined by
15951 	* Particle Emptiable ($3.9.6)."
15952 	*/
15953 	if ((! WXS_HAS_SIMPLE_CONTENT(type)) &&
15954 	    ((! WXS_HAS_MIXED_CONTENT(type)) || (! WXS_EMPTIABLE(type)))) {
15955 	    /* NOTE that this covers (2.2.2) as well. */
15956 	    xmlSchemaPCustomErr(pctxt,
15957 		XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
15958 		WXS_BASIC_CAST type, type->node,
15959 		"For a string to be a valid default, the type definition "
15960 		"must be a simple type or a complex type with mixed content "
15961 		"and a particle emptiable", NULL);
15962 	    return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
15963 	}
15964     }
15965     /*
15966     * 1 If the type definition is a simple type definition, then the string
15967     * must be `valid` with respect to that definition as defined by String
15968     * Valid ($3.14.4).
15969     *
15970     * AND
15971     *
15972     * 2.2.1 If the {content type} is a simple type definition, then the
15973     * string must be `valid` with respect to that simple type definition
15974     * as defined by String Valid ($3.14.4).
15975     */
15976     if (WXS_IS_SIMPLE(type))
15977 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15978 	    type, value, val, 1, 1, 0);
15979     else if (WXS_HAS_SIMPLE_CONTENT(type))
15980 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15981 	    type->contentTypeDef, value, val, 1, 1, 0);
15982     else
15983 	return (ret);
15984 
15985     if (ret < 0) {
15986 	PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
15987 	    "calling xmlSchemaVCheckCVCSimpleType()");
15988     }
15989 
15990     return (ret);
15991 }
15992 
15993 /**
15994  * xmlSchemaCheckCTPropsCorrect:
15995  * @ctxt:  the schema parser context
15996  * @type:  the complex type definition
15997  *
15998  *.(4.6) Constraints on Complex Type Definition Schema Components
15999  * Schema Component Constraint:
16000  * Complex Type Definition Properties Correct (ct-props-correct)
16001  * STATUS: (seems) complete
16002  *
16003  * Returns 0 if the constraints are satisfied, a positive
16004  * error code if not and -1 if an internal error occurred.
16005  */
16006 static int
xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)16007 xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
16008 			     xmlSchemaTypePtr type)
16009 {
16010     /*
16011     * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
16012     *
16013     * SPEC (1) "The values of the properties of a complex type definition must
16014     * be as described in the property tableau in The Complex Type Definition
16015     * Schema Component ($3.4.1), modulo the impact of Missing
16016     * Sub-components ($5.3)."
16017     */
16018     if ((type->baseType != NULL) &&
16019 	(WXS_IS_SIMPLE(type->baseType)) &&
16020 	(WXS_IS_EXTENSION(type) == 0)) {
16021 	/*
16022 	* SPEC (2) "If the {base type definition} is a simple type definition,
16023 	* the {derivation method} must be extension."
16024 	*/
16025 	xmlSchemaCustomErr(ACTXT_CAST pctxt,
16026 	    XML_SCHEMAP_SRC_CT_1,
16027 	    NULL, WXS_BASIC_CAST type,
16028 	    "If the base type is a simple type, the derivation method must be "
16029 	    "'extension'", NULL, NULL);
16030 	return (XML_SCHEMAP_SRC_CT_1);
16031     }
16032     /*
16033     * SPEC (3) "Circular definitions are disallowed, except for the `ur-type
16034     * definition`. That is, it must be possible to reach the `ur-type
16035     * definition` by repeatedly following the {base type definition}."
16036     *
16037     * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
16038     */
16039     /*
16040     * NOTE that (4) and (5) need the following:
16041     *   - attribute uses need to be already inherited (apply attr. prohibitions)
16042     *   - attribute group references need to be expanded already
16043     *   - simple types need to be typefixed already
16044     */
16045     if (type->attrUses &&
16046 	(((xmlSchemaItemListPtr) type->attrUses)->nbItems > 1))
16047     {
16048 	xmlSchemaItemListPtr uses = (xmlSchemaItemListPtr) type->attrUses;
16049 	xmlSchemaAttributeUsePtr use, tmp;
16050 	int i, j, hasId = 0;
16051 
16052 	for (i = uses->nbItems -1; i >= 0; i--) {
16053 	    use = uses->items[i];
16054 
16055 	    /*
16056 	    * SPEC ct-props-correct
16057 	    * (4) "Two distinct attribute declarations in the
16058 	    * {attribute uses} must not have identical {name}s and
16059 	    * {target namespace}s."
16060 	    */
16061 	    if (i > 0) {
16062 		for (j = i -1; j >= 0; j--) {
16063 		    tmp = uses->items[j];
16064 		    if ((WXS_ATTRUSE_DECL_NAME(use) ==
16065 			WXS_ATTRUSE_DECL_NAME(tmp)) &&
16066 			(WXS_ATTRUSE_DECL_TNS(use) ==
16067 			WXS_ATTRUSE_DECL_TNS(tmp)))
16068 		    {
16069 			xmlChar *str = NULL;
16070 
16071 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
16072 			    XML_SCHEMAP_AG_PROPS_CORRECT,
16073 			    NULL, WXS_BASIC_CAST type,
16074 			    "Duplicate %s",
16075 			    xmlSchemaGetComponentDesignation(&str, use),
16076 			    NULL);
16077 			FREE_AND_NULL(str);
16078 			/*
16079 			* Remove the duplicate.
16080 			*/
16081 			if (xmlSchemaItemListRemove(uses, i) == -1)
16082 			    goto exit_failure;
16083 			goto next_use;
16084 		    }
16085 		}
16086 	    }
16087 	    /*
16088 	    * SPEC ct-props-correct
16089 	    * (5) "Two distinct attribute declarations in the
16090 	    * {attribute uses} must not have {type definition}s which
16091 	    * are or are derived from ID."
16092 	    */
16093 	    if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
16094 		if (xmlSchemaIsDerivedFromBuiltInType(
16095 		    WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
16096 		{
16097 		    if (hasId) {
16098 			xmlChar *str = NULL;
16099 
16100 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
16101 			    XML_SCHEMAP_AG_PROPS_CORRECT,
16102 			    NULL, WXS_BASIC_CAST type,
16103 			    "There must not exist more than one attribute "
16104 			    "declaration of type 'xs:ID' "
16105 			    "(or derived from 'xs:ID'). The %s violates this "
16106 			    "constraint",
16107 			    xmlSchemaGetComponentDesignation(&str, use),
16108 			    NULL);
16109 			FREE_AND_NULL(str);
16110 			if (xmlSchemaItemListRemove(uses, i) == -1)
16111 			    goto exit_failure;
16112 		    }
16113 
16114 		    hasId = 1;
16115 		}
16116 	    }
16117 next_use: {}
16118 	}
16119     }
16120     return (0);
16121 exit_failure:
16122     return(-1);
16123 }
16124 
16125 static int
xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,xmlSchemaTypePtr typeB)16126 xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
16127 		       xmlSchemaTypePtr typeB)
16128 {
16129     /*
16130     * TODO: This should implement component-identity
16131     * in the future.
16132     */
16133     if ((typeA == NULL) || (typeB == NULL))
16134 	return (0);
16135     return (typeA == typeB);
16136 }
16137 
16138 /**
16139  * xmlSchemaCheckCOSCTDerivedOK:
16140  * @ctxt:  the schema parser context
16141  * @type:  the to-be derived complex type definition
16142  * @baseType:  the base complex type definition
16143  * @set: the given set
16144  *
16145  * Schema Component Constraint:
16146  * Type Derivation OK (Complex) (cos-ct-derived-ok)
16147  *
16148  * STATUS: completed
16149  *
16150  * Returns 0 if the constraints are satisfied, or 1
16151  * if not.
16152  */
16153 static int
xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,xmlSchemaTypePtr type,xmlSchemaTypePtr baseType,int set)16154 xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16155 			     xmlSchemaTypePtr type,
16156 			     xmlSchemaTypePtr baseType,
16157 			     int set)
16158 {
16159     int equal = xmlSchemaAreEqualTypes(type, baseType);
16160     /* TODO: Error codes. */
16161     /*
16162     * SPEC "For a complex type definition (call it D, for derived)
16163     * to be validly derived from a type definition (call this
16164     * B, for base) given a subset of {extension, restriction}
16165     * all of the following must be true:"
16166     */
16167     if (! equal) {
16168 	/*
16169 	* SPEC (1) "If B and D are not the same type definition, then the
16170 	* {derivation method} of D must not be in the subset."
16171 	*/
16172 	if (((set & SUBSET_EXTENSION) && (WXS_IS_EXTENSION(type))) ||
16173 	    ((set & SUBSET_RESTRICTION) && (WXS_IS_RESTRICTION(type))))
16174 	    return (1);
16175     } else {
16176 	/*
16177 	* SPEC (2.1) "B and D must be the same type definition."
16178 	*/
16179 	return (0);
16180     }
16181     /*
16182     * SPEC (2.2) "B must be D's {base type definition}."
16183     */
16184     if (type->baseType == baseType)
16185 	return (0);
16186     /*
16187     * SPEC (2.3.1) "D's {base type definition} must not be the `ur-type
16188     * definition`."
16189     */
16190     if (WXS_IS_ANYTYPE(type->baseType))
16191 	return (1);
16192 
16193     if (WXS_IS_COMPLEX(type->baseType)) {
16194 	/*
16195 	* SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
16196 	* must be validly derived from B given the subset as defined by this
16197 	* constraint."
16198 	*/
16199 	return (xmlSchemaCheckCOSCTDerivedOK(actxt, type->baseType,
16200 	    baseType, set));
16201     } else {
16202 	/*
16203 	* SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
16204 	* must be validly derived from B given the subset as defined in Type
16205 	* Derivation OK (Simple) ($3.14.6).
16206 	*/
16207 	return (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
16208 	    baseType, set));
16209     }
16210 }
16211 
16212 /**
16213  * xmlSchemaCheckCOSDerivedOK:
16214  * @type:  the derived simple type definition
16215  * @baseType:  the base type definition
16216  *
16217  * Calls:
16218  * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
16219  *
16220  * Checks whether @type can be validly derived from @baseType.
16221  *
16222  * Returns 0 on success, an positive error code otherwise.
16223  */
16224 static int
xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt,xmlSchemaTypePtr type,xmlSchemaTypePtr baseType,int set)16225 xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16226 			   xmlSchemaTypePtr type,
16227 			   xmlSchemaTypePtr baseType,
16228 			   int set)
16229 {
16230     if (WXS_IS_SIMPLE(type))
16231 	return (xmlSchemaCheckCOSSTDerivedOK(actxt, type, baseType, set));
16232     else
16233 	return (xmlSchemaCheckCOSCTDerivedOK(actxt, type, baseType, set));
16234 }
16235 
16236 /**
16237  * xmlSchemaCheckCOSCTExtends:
16238  * @ctxt:  the schema parser context
16239  * @type:  the complex type definition
16240  *
16241  * (3.4.6) Constraints on Complex Type Definition Schema Components
16242  * Schema Component Constraint:
16243  * Derivation Valid (Extension) (cos-ct-extends)
16244  *
16245  * STATUS:
16246  *   missing:
16247  *     (1.5)
16248  *     (1.4.3.2.2.2) "Particle Valid (Extension)"
16249  *
16250  * Returns 0 if the constraints are satisfied, a positive
16251  * error code if not and -1 if an internal error occurred.
16252  */
16253 static int
xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)16254 xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
16255 			   xmlSchemaTypePtr type)
16256 {
16257     xmlSchemaTypePtr base = type->baseType;
16258     /*
16259     * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
16260     * temporarily only.
16261     */
16262     /*
16263     * SPEC (1) "If the {base type definition} is a complex type definition,
16264     * then all of the following must be true:"
16265     */
16266     if (WXS_IS_COMPLEX(base)) {
16267 	/*
16268 	* SPEC (1.1) "The {final} of the {base type definition} must not
16269 	* contain extension."
16270 	*/
16271 	if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16272 	    xmlSchemaPCustomErr(ctxt,
16273 		XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16274 		WXS_BASIC_CAST type, NULL,
16275 		"The 'final' of the base type definition "
16276 		"contains 'extension'", NULL);
16277 	    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16278 	}
16279 
16280 	/*
16281 	* ATTENTION: The constrains (1.2) and (1.3) are not applied,
16282 	* since they are automatically satisfied through the
16283 	* inheriting mechanism.
16284 	* Note that even if redefining components, the inheriting mechanism
16285 	* is used.
16286 	*/
16287 #if 0
16288 	/*
16289 	* SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
16290 	* uses}
16291 	* of the complex type definition itself, that is, for every attribute
16292 	* use in the {attribute uses} of the {base type definition}, there
16293 	* must be an attribute use in the {attribute uses} of the complex
16294 	* type definition itself whose {attribute declaration} has the same
16295 	* {name}, {target namespace} and {type definition} as its attribute
16296 	* declaration"
16297 	*/
16298 	if (base->attrUses != NULL) {
16299 	    int i, j, found;
16300 	    xmlSchemaAttributeUsePtr use, buse;
16301 
16302 	    for (i = 0; i < (WXS_LIST_CAST base->attrUses)->nbItems; i ++) {
16303 		buse = (WXS_LIST_CAST base->attrUses)->items[i];
16304 		found = 0;
16305 		if (type->attrUses != NULL) {
16306 		    use = (WXS_LIST_CAST type->attrUses)->items[j];
16307 		    for (j = 0; j < (WXS_LIST_CAST type->attrUses)->nbItems; j ++)
16308 		    {
16309 			if ((WXS_ATTRUSE_DECL_NAME(use) ==
16310 				WXS_ATTRUSE_DECL_NAME(buse)) &&
16311 			    (WXS_ATTRUSE_DECL_TNS(use) ==
16312 				WXS_ATTRUSE_DECL_TNS(buse)) &&
16313 			    (WXS_ATTRUSE_TYPEDEF(use) ==
16314 				WXS_ATTRUSE_TYPEDEF(buse))
16315 			{
16316 			    found = 1;
16317 			    break;
16318 			}
16319 		    }
16320 		}
16321 		if (! found) {
16322 		    xmlChar *str = NULL;
16323 
16324 		    xmlSchemaCustomErr(ACTXT_CAST ctxt,
16325 			XML_SCHEMAP_COS_CT_EXTENDS_1_2,
16326 			NULL, WXS_BASIC_CAST type,
16327 			/*
16328 			* TODO: The report does not indicate that also the
16329 			* type needs to be the same.
16330 			*/
16331 			"This type is missing a matching correspondent "
16332 			"for its {base type}'s %s in its {attribute uses}",
16333 			xmlSchemaGetComponentDesignation(&str,
16334 			    buse->children),
16335 			NULL);
16336 		    FREE_AND_NULL(str)
16337 		}
16338 	    }
16339 	}
16340 	/*
16341 	* SPEC (1.3) "If it has an {attribute wildcard}, the complex type
16342 	* definition must also have one, and the base type definition's
16343 	* {attribute  wildcard}'s {namespace constraint} must be a subset
16344 	* of the complex  type definition's {attribute wildcard}'s {namespace
16345 	* constraint}, as defined by Wildcard Subset ($3.10.6)."
16346 	*/
16347 
16348 	/*
16349 	* MAYBE TODO: Enable if ever needed. But this will be needed only
16350 	* if created the type via a schema construction API.
16351 	*/
16352 	if (base->attributeWildcard != NULL) {
16353 	    if (type->attributeWildcard == NULL) {
16354 		xmlChar *str = NULL;
16355 
16356 		xmlSchemaCustomErr(ACTXT_CAST pctxt,
16357 		    XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16358 		    NULL, type,
16359 		    "The base %s has an attribute wildcard, "
16360 		    "but this type is missing an attribute wildcard",
16361 		    xmlSchemaGetComponentDesignation(&str, base));
16362 		FREE_AND_NULL(str)
16363 
16364 	    } else if (xmlSchemaCheckCOSNSSubset(
16365 		base->attributeWildcard, type->attributeWildcard))
16366 	    {
16367 		xmlChar *str = NULL;
16368 
16369 		xmlSchemaCustomErr(ACTXT_CAST pctxt,
16370 		    XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16371 		    NULL, type,
16372 		    "The attribute wildcard is not a valid "
16373 		    "superset of the one in the base %s",
16374 		    xmlSchemaGetComponentDesignation(&str, base));
16375 		FREE_AND_NULL(str)
16376 	    }
16377 	}
16378 #endif
16379 	/*
16380 	* SPEC (1.4) "One of the following must be true:"
16381 	*/
16382 	if ((type->contentTypeDef != NULL) &&
16383 	    (type->contentTypeDef == base->contentTypeDef)) {
16384 	    /*
16385 	    * SPEC (1.4.1) "The {content type} of the {base type definition}
16386 	    * and the {content type} of the complex type definition itself
16387 	    * must be the same simple type definition"
16388 	    * PASS
16389 	    */
16390 	} else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
16391 	    (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
16392 	    /*
16393 	    * SPEC (1.4.2) "The {content type} of both the {base type
16394 	    * definition} and the complex type definition itself must
16395 	    * be empty."
16396 	    * PASS
16397 	    */
16398 	} else {
16399 	    /*
16400 	    * SPEC (1.4.3) "All of the following must be true:"
16401 	    */
16402 	    if (type->subtypes == NULL) {
16403 		/*
16404 		* SPEC 1.4.3.1 The {content type} of the complex type
16405 		* definition itself must specify a particle.
16406 		*/
16407 		xmlSchemaPCustomErr(ctxt,
16408 		    XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16409 		    WXS_BASIC_CAST type, NULL,
16410 		    "The content type must specify a particle", NULL);
16411 		return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16412 	    }
16413 	    /*
16414 	    * SPEC (1.4.3.2) "One of the following must be true:"
16415 	    */
16416 	    if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16417 		/*
16418 		* SPEC (1.4.3.2.1) "The {content type} of the {base type
16419 		* definition} must be empty.
16420 		* PASS
16421 		*/
16422 	    } else {
16423 		/*
16424 		* SPEC (1.4.3.2.2) "All of the following must be true:"
16425 		*/
16426 		if ((type->contentType != base->contentType) ||
16427 		    ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
16428 		    (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
16429 		    /*
16430 		    * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
16431 		    * or both must be element-only."
16432 		    */
16433 		    xmlSchemaPCustomErr(ctxt,
16434 			XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16435 			WXS_BASIC_CAST type, NULL,
16436 			"The content type of both, the type and its base "
16437 			"type, must either 'mixed' or 'element-only'", NULL);
16438 		    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16439 		}
16440 		/*
16441 		* URGENT TODO SPEC (1.4.3.2.2.2) "The particle of the
16442 		* complex type definition must be a `valid extension`
16443 		* of the {base type definition}'s particle, as defined
16444 		* in Particle Valid (Extension) ($3.9.6)."
16445 		*
16446 		* NOTE that we won't check "Particle Valid (Extension)",
16447 		* since it is ensured by the derivation process in
16448 		* xmlSchemaTypeFixup(). We need to implement this when heading
16449 		* for a construction API
16450 		* TODO: !! This is needed to be checked if redefining a type !!
16451 		*/
16452 	    }
16453 	    /*
16454 	    * URGENT TODO (1.5)
16455 	    */
16456 	}
16457     } else {
16458 	/*
16459 	* SPEC (2) "If the {base type definition} is a simple type definition,
16460 	* then all of the following must be true:"
16461 	*/
16462 	if (type->contentTypeDef != base) {
16463 	    /*
16464 	    * SPEC (2.1) "The {content type} must be the same simple type
16465 	    * definition."
16466 	    */
16467 	    xmlSchemaPCustomErr(ctxt,
16468 		XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16469 		WXS_BASIC_CAST type, NULL,
16470 		"The content type must be the simple base type", NULL);
16471 	    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16472 	}
16473 	if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16474 	    /*
16475 	    * SPEC (2.2) "The {final} of the {base type definition} must not
16476 	    * contain extension"
16477 	    * NOTE that this is the same as (1.1).
16478 	    */
16479 	    xmlSchemaPCustomErr(ctxt,
16480 		XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16481 		WXS_BASIC_CAST type, NULL,
16482 		"The 'final' of the base type definition "
16483 		"contains 'extension'", NULL);
16484 	    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16485 	}
16486     }
16487     return (0);
16488 }
16489 
16490 /**
16491  * xmlSchemaCheckDerivationOKRestriction:
16492  * @ctxt:  the schema parser context
16493  * @type:  the complex type definition
16494  *
16495  * (3.4.6) Constraints on Complex Type Definition Schema Components
16496  * Schema Component Constraint:
16497  * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
16498  *
16499  * STATUS:
16500  *   missing:
16501  *     (5.4.2) ???
16502  *
16503  * ATTENTION:
16504  * In XML Schema 1.1 this will be:
16505  * Validation Rule: Checking complex type subsumption
16506  *
16507  * Returns 0 if the constraints are satisfied, a positive
16508  * error code if not and -1 if an internal error occurred.
16509  */
16510 static int
xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)16511 xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
16512 				      xmlSchemaTypePtr type)
16513 {
16514     xmlSchemaTypePtr base;
16515 
16516     /*
16517     * TODO: Correct the error code; XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1 is used
16518     * temporarily only.
16519     */
16520     base = type->baseType;
16521     if (! WXS_IS_COMPLEX(base)) {
16522 	xmlSchemaCustomErr(ACTXT_CAST ctxt,
16523 	    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16524 	    type->node, WXS_BASIC_CAST type,
16525 	    "The base type must be a complex type", NULL, NULL);
16526 	return(ctxt->err);
16527     }
16528     if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
16529 	/*
16530 	* SPEC (1) "The {base type definition} must be a complex type
16531 	* definition whose {final} does not contain restriction."
16532 	*/
16533 	xmlSchemaCustomErr(ACTXT_CAST ctxt,
16534 	    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16535 	    type->node, WXS_BASIC_CAST type,
16536 	    "The 'final' of the base type definition "
16537 	    "contains 'restriction'", NULL, NULL);
16538 	return (ctxt->err);
16539     }
16540     /*
16541     * SPEC (2), (3) and (4)
16542     * Those are handled in a separate function, since the
16543     * same constraints are needed for redefinition of
16544     * attribute groups as well.
16545     */
16546     if (xmlSchemaCheckDerivationOKRestriction2to4(ctxt,
16547 	XML_SCHEMA_ACTION_DERIVE,
16548 	WXS_BASIC_CAST type, WXS_BASIC_CAST base,
16549 	type->attrUses, base->attrUses,
16550 	type->attributeWildcard,
16551 	base->attributeWildcard) == -1)
16552     {
16553 	return(-1);
16554     }
16555     /*
16556     * SPEC (5) "One of the following must be true:"
16557     */
16558     if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
16559 	/*
16560 	* SPEC (5.1) "The {base type definition} must be the
16561 	* `ur-type definition`."
16562 	* PASS
16563 	*/
16564     } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16565 	    (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16566 	/*
16567 	* SPEC (5.2.1) "The {content type} of the complex type definition
16568 	* must be a simple type definition"
16569 	*
16570 	* SPEC (5.2.2) "One of the following must be true:"
16571 	*/
16572 	if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16573 	    (base->contentType == XML_SCHEMA_CONTENT_BASIC))
16574 	{
16575 	    int err;
16576 	    /*
16577 	    * SPEC (5.2.2.1) "The {content type} of the {base type
16578 	    * definition} must be a simple type definition from which
16579 	    * the {content type} is validly derived given the empty
16580 	    * set as defined in Type Derivation OK (Simple) ($3.14.6)."
16581 	    *
16582 	    * ATTENTION TODO: This seems not needed if the type implicitly
16583 	    * derived from the base type.
16584 	    *
16585 	    */
16586 	    err = xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST ctxt,
16587 		type->contentTypeDef, base->contentTypeDef, 0);
16588 	    if (err != 0) {
16589 		xmlChar *strA = NULL, *strB = NULL;
16590 
16591 		if (err == -1)
16592 		    return(-1);
16593 		xmlSchemaCustomErr(ACTXT_CAST ctxt,
16594 		    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16595 		    NULL, WXS_BASIC_CAST type,
16596 		    "The {content type} %s is not validly derived from the "
16597 		    "base type's {content type} %s",
16598 		    xmlSchemaGetComponentDesignation(&strA,
16599 			type->contentTypeDef),
16600 		    xmlSchemaGetComponentDesignation(&strB,
16601 			base->contentTypeDef));
16602 		FREE_AND_NULL(strA);
16603 		FREE_AND_NULL(strB);
16604 		return(ctxt->err);
16605 	    }
16606 	} else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16607 	    (xmlSchemaIsParticleEmptiable(
16608 		(xmlSchemaParticlePtr) base->subtypes))) {
16609 	    /*
16610 	    * SPEC (5.2.2.2) "The {base type definition} must be mixed
16611 	    * and have a particle which is `emptiable` as defined in
16612 	    * Particle Emptiable ($3.9.6)."
16613 	    * PASS
16614 	    */
16615 	} else {
16616 	    xmlSchemaPCustomErr(ctxt,
16617 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16618 		WXS_BASIC_CAST type, NULL,
16619 		"The content type of the base type must be either "
16620 		"a simple type or 'mixed' and an emptiable particle", NULL);
16621 	    return (ctxt->err);
16622 	}
16623     } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16624 	/*
16625 	* SPEC (5.3.1) "The {content type} of the complex type itself must
16626 	* be empty"
16627 	*/
16628 	if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16629 	    /*
16630 	    * SPEC (5.3.2.1) "The {content type} of the {base type
16631 	    * definition} must also be empty."
16632 	    * PASS
16633 	    */
16634 	} else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16635 	    (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
16636 	    xmlSchemaIsParticleEmptiable(
16637 		(xmlSchemaParticlePtr) base->subtypes)) {
16638 	    /*
16639 	    * SPEC (5.3.2.2) "The {content type} of the {base type
16640 	    * definition} must be elementOnly or mixed and have a particle
16641 	    * which is `emptiable` as defined in Particle Emptiable ($3.9.6)."
16642 	    * PASS
16643 	    */
16644 	} else {
16645 	    xmlSchemaPCustomErr(ctxt,
16646 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16647 		WXS_BASIC_CAST type, NULL,
16648 		"The content type of the base type must be either "
16649 		"empty or 'mixed' (or 'elements-only') and an emptiable "
16650 		"particle", NULL);
16651 	    return (ctxt->err);
16652 	}
16653     } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16654 	WXS_HAS_MIXED_CONTENT(type)) {
16655 	/*
16656 	* SPEC (5.4.1.1) "The {content type} of the complex type definition
16657 	* itself must be element-only"
16658 	*/
16659 	if (WXS_HAS_MIXED_CONTENT(type) && (! WXS_HAS_MIXED_CONTENT(base))) {
16660 	    /*
16661 	    * SPEC (5.4.1.2) "The {content type} of the complex type
16662 	    * definition itself and of the {base type definition} must be
16663 	    * mixed"
16664 	    */
16665 	    xmlSchemaPCustomErr(ctxt,
16666 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16667 		WXS_BASIC_CAST type, NULL,
16668 		"If the content type is 'mixed', then the content type of the "
16669 		"base type must also be 'mixed'", NULL);
16670 	    return (ctxt->err);
16671 	}
16672 	/*
16673 	* SPEC (5.4.2) "The particle of the complex type definition itself
16674 	* must be a `valid restriction` of the particle of the {content
16675 	* type} of the {base type definition} as defined in Particle Valid
16676 	* (Restriction) ($3.9.6).
16677 	*
16678 	* URGENT TODO: (5.4.2)
16679 	*/
16680     } else {
16681 	xmlSchemaPCustomErr(ctxt,
16682 	    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16683 	    WXS_BASIC_CAST type, NULL,
16684 	    "The type is not a valid restriction of its base type", NULL);
16685 	return (ctxt->err);
16686     }
16687     return (0);
16688 }
16689 
16690 /**
16691  * xmlSchemaCheckCTComponent:
16692  * @ctxt:  the schema parser context
16693  * @type:  the complex type definition
16694  *
16695  * (3.4.6) Constraints on Complex Type Definition Schema Components
16696  *
16697  * Returns 0 if the constraints are satisfied, a positive
16698  * error code if not and -1 if an internal error occurred.
16699  */
16700 static int
xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)16701 xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
16702 			  xmlSchemaTypePtr type)
16703 {
16704     int ret;
16705     /*
16706     * Complex Type Definition Properties Correct
16707     */
16708     ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
16709     if (ret != 0)
16710 	return (ret);
16711     if (WXS_IS_EXTENSION(type))
16712 	ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
16713     else
16714 	ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
16715     return (ret);
16716 }
16717 
16718 /**
16719  * xmlSchemaCheckSRCCT:
16720  * @ctxt:  the schema parser context
16721  * @type:  the complex type definition
16722  *
16723  * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
16724  * Schema Representation Constraint:
16725  * Complex Type Definition Representation OK (src-ct)
16726  *
16727  * Returns 0 if the constraints are satisfied, a positive
16728  * error code if not and -1 if an internal error occurred.
16729  */
16730 static int
xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)16731 xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
16732 		    xmlSchemaTypePtr type)
16733 {
16734     xmlSchemaTypePtr base;
16735     int ret = 0;
16736 
16737     /*
16738     * TODO: Adjust the error codes here, as I used
16739     * XML_SCHEMAP_SRC_CT_1 only yet.
16740     */
16741     base = type->baseType;
16742     if (! WXS_HAS_SIMPLE_CONTENT(type)) {
16743 	/*
16744 	* 1 If the <complexContent> alternative is chosen, the type definition
16745 	* `resolved` to by the `actual value` of the base [attribute]
16746 	* must be a complex type definition;
16747 	*/
16748 	if (! WXS_IS_COMPLEX(base)) {
16749 	    xmlChar *str = NULL;
16750 	    xmlSchemaPCustomErr(ctxt,
16751 		XML_SCHEMAP_SRC_CT_1,
16752 		WXS_BASIC_CAST type, type->node,
16753 		"If using <complexContent>, the base type is expected to be "
16754 		"a complex type. The base type '%s' is a simple type",
16755 		xmlSchemaFormatQName(&str, base->targetNamespace,
16756 		base->name));
16757 	    FREE_AND_NULL(str)
16758 	    return (XML_SCHEMAP_SRC_CT_1);
16759 	}
16760     } else {
16761 	/*
16762 	* SPEC
16763 	* 2 If the <simpleContent> alternative is chosen, all of the
16764 	* following must be true:
16765 	* 2.1 The type definition `resolved` to by the `actual value` of the
16766 	* base [attribute] must be one of the following:
16767 	*/
16768 	if (WXS_IS_SIMPLE(base)) {
16769 	    if (WXS_IS_EXTENSION(type) == 0) {
16770 		xmlChar *str = NULL;
16771 		/*
16772 		* 2.1.3 only if the <extension> alternative is also
16773 		* chosen, a simple type definition.
16774 		*/
16775 		/* TODO: Change error code to ..._SRC_CT_2_1_3. */
16776 		xmlSchemaPCustomErr(ctxt,
16777 		    XML_SCHEMAP_SRC_CT_1,
16778 		    WXS_BASIC_CAST type, NULL,
16779 		    "If using <simpleContent> and <restriction>, the base "
16780 		    "type must be a complex type. The base type '%s' is "
16781 		    "a simple type",
16782 		    xmlSchemaFormatQName(&str, base->targetNamespace,
16783 			base->name));
16784 		FREE_AND_NULL(str)
16785 		return (XML_SCHEMAP_SRC_CT_1);
16786 	    }
16787 	} else {
16788 	    /* Base type is a complex type. */
16789 	    if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16790 		(base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16791 		/*
16792 		* 2.1.1 a complex type definition whose {content type} is a
16793 		* simple type definition;
16794 		* PASS
16795 		*/
16796 		if (base->contentTypeDef == NULL) {
16797 		    xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
16798 			WXS_BASIC_CAST type, NULL,
16799 			"Internal error: xmlSchemaCheckSRCCT, "
16800 			"'%s', base type has no content type",
16801 			type->name);
16802 		    return (-1);
16803 		}
16804 	    } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16805 		(WXS_IS_RESTRICTION(type))) {
16806 
16807 		/*
16808 		* 2.1.2 only if the <restriction> alternative is also
16809 		* chosen, a complex type definition whose {content type}
16810 		* is mixed and a particle emptiable.
16811 		*/
16812 		if (! xmlSchemaIsParticleEmptiable(
16813 		    (xmlSchemaParticlePtr) base->subtypes)) {
16814 		    ret = XML_SCHEMAP_SRC_CT_1;
16815 		} else
16816 		    /*
16817 		    * Attention: at this point the <simpleType> child is in
16818 		    * ->contentTypeDef (put there during parsing).
16819 		    */
16820 		    if (type->contentTypeDef == NULL) {
16821 		    xmlChar *str = NULL;
16822 		    /*
16823 		    * 2.2 If clause 2.1.2 above is satisfied, then there
16824 		    * must be a <simpleType> among the [children] of
16825 		    * <restriction>.
16826 		    */
16827 		    /* TODO: Change error code to ..._SRC_CT_2_2. */
16828 		    xmlSchemaPCustomErr(ctxt,
16829 			XML_SCHEMAP_SRC_CT_1,
16830 			WXS_BASIC_CAST type, NULL,
16831 			"A <simpleType> is expected among the children "
16832 			"of <restriction>, if <simpleContent> is used and "
16833 			"the base type '%s' is a complex type",
16834 			xmlSchemaFormatQName(&str, base->targetNamespace,
16835 			base->name));
16836 		    FREE_AND_NULL(str)
16837 		    return (XML_SCHEMAP_SRC_CT_1);
16838 		}
16839 	    } else {
16840 		ret = XML_SCHEMAP_SRC_CT_1;
16841 	    }
16842 	}
16843 	if (ret > 0) {
16844 	    xmlChar *str = NULL;
16845 	    if (WXS_IS_RESTRICTION(type)) {
16846 		xmlSchemaPCustomErr(ctxt,
16847 		    XML_SCHEMAP_SRC_CT_1,
16848 		    WXS_BASIC_CAST type, NULL,
16849 		    "If <simpleContent> and <restriction> is used, the "
16850 		    "base type must be a simple type or a complex type with "
16851 		    "mixed content and particle emptiable. The base type "
16852 		    "'%s' is none of those",
16853 		    xmlSchemaFormatQName(&str, base->targetNamespace,
16854 		    base->name));
16855 	    } else {
16856 		xmlSchemaPCustomErr(ctxt,
16857 		    XML_SCHEMAP_SRC_CT_1,
16858 		    WXS_BASIC_CAST type, NULL,
16859 		    "If <simpleContent> and <extension> is used, the "
16860 		    "base type must be a simple type. The base type '%s' "
16861 		    "is a complex type",
16862 		    xmlSchemaFormatQName(&str, base->targetNamespace,
16863 		    base->name));
16864 	    }
16865 	    FREE_AND_NULL(str)
16866 	}
16867     }
16868     /*
16869     * SPEC (3) "The corresponding complex type definition component must
16870     * satisfy the conditions set out in Constraints on Complex Type
16871     * Definition Schema Components ($3.4.6);"
16872     * NOTE (3) will be done in xmlSchemaTypeFixup().
16873     */
16874     /*
16875     * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
16876     * above for {attribute wildcard} is satisfied, the intensional
16877     * intersection must be expressible, as defined in Attribute Wildcard
16878     * Intersection ($3.10.6).
16879     * NOTE (4) is done in xmlSchemaFixupTypeAttributeUses().
16880     */
16881     return (ret);
16882 }
16883 
16884 #ifdef ENABLE_PARTICLE_RESTRICTION
16885 /**
16886  * xmlSchemaCheckParticleRangeOK:
16887  * @ctxt:  the schema parser context
16888  * @type:  the complex type definition
16889  *
16890  * (3.9.6) Constraints on Particle Schema Components
16891  * Schema Component Constraint:
16892  * Occurrence Range OK (range-ok)
16893  *
16894  * STATUS: complete
16895  *
16896  * Returns 0 if the constraints are satisfied, a positive
16897  * error code if not and -1 if an internal error occurred.
16898  */
16899 static int
xmlSchemaCheckParticleRangeOK(int rmin,int rmax,int bmin,int bmax)16900 xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
16901 			      int bmin, int bmax)
16902 {
16903     if (rmin < bmin)
16904 	return (1);
16905     if ((bmax != UNBOUNDED) &&
16906 	(rmax > bmax))
16907 	return (1);
16908     return (0);
16909 }
16910 
16911 /**
16912  * xmlSchemaCheckRCaseNameAndTypeOK:
16913  * @ctxt:  the schema parser context
16914  * @r: the restricting element declaration particle
16915  * @b: the base element declaration particle
16916  *
16917  * (3.9.6) Constraints on Particle Schema Components
16918  * Schema Component Constraint:
16919  * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
16920  * (rcase-NameAndTypeOK)
16921  *
16922  * STATUS:
16923  *   MISSING (3.2.3)
16924  *   CLARIFY: (3.2.2)
16925  *
16926  * Returns 0 if the constraints are satisfied, a positive
16927  * error code if not and -1 if an internal error occurred.
16928  */
16929 static int
xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)16930 xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
16931 				 xmlSchemaParticlePtr r,
16932 				 xmlSchemaParticlePtr b)
16933 {
16934     xmlSchemaElementPtr elemR, elemB;
16935 
16936     /* TODO: Error codes (rcase-NameAndTypeOK). */
16937     elemR = (xmlSchemaElementPtr) r->children;
16938     elemB = (xmlSchemaElementPtr) b->children;
16939     /*
16940     * SPEC (1) "The declarations' {name}s and {target namespace}s are
16941     * the same."
16942     */
16943     if ((elemR != elemB) &&
16944 	((! xmlStrEqual(elemR->name, elemB->name)) ||
16945 	(! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
16946 	return (1);
16947     /*
16948     * SPEC (2) "R's occurrence range is a valid restriction of B's
16949     * occurrence range as defined by Occurrence Range OK ($3.9.6)."
16950     */
16951     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16952 	    b->minOccurs, b->maxOccurs) != 0)
16953 	return (1);
16954     /*
16955     * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
16956     * {scope} are global."
16957     */
16958     if (elemR == elemB)
16959 	return (0);
16960     /*
16961     * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
16962     */
16963     if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
16964 	(elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
16965 	 return (1);
16966     /*
16967     * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
16968     * or is not fixed, or R's declaration's {value constraint} is fixed
16969     * with the same value."
16970     */
16971     if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
16972 	((elemR->value == NULL) ||
16973 	 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
16974 	 /* TODO: Equality of the initial value or normalized or canonical? */
16975 	 (! xmlStrEqual(elemR->value, elemB->value))))
16976 	 return (1);
16977     /*
16978     * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
16979     * definitions} is a subset of B's declaration's {identity-constraint
16980     * definitions}, if any."
16981     */
16982     if (elemB->idcs != NULL) {
16983 	/* TODO */
16984     }
16985     /*
16986     * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
16987     * superset of B's declaration's {disallowed substitutions}."
16988     */
16989     if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
16990 	 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
16991 	((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
16992 	 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
16993 	((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
16994 	 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
16995 	 return (1);
16996     /*
16997     * SPEC (3.2.5) "R's {type definition} is validly derived given
16998     * {extension, list, union} from B's {type definition}"
16999     *
17000     * BADSPEC TODO: What's the point of adding "list" and "union" to the
17001     * set, if the corresponding constraints handle "restriction" and
17002     * "extension" only?
17003     *
17004     */
17005     {
17006 	int set = 0;
17007 
17008 	set |= SUBSET_EXTENSION;
17009 	set |= SUBSET_LIST;
17010 	set |= SUBSET_UNION;
17011 	if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST ctxt, elemR->subtypes,
17012 	    elemB->subtypes, set) != 0)
17013 	    return (1);
17014     }
17015     return (0);
17016 }
17017 
17018 /**
17019  * xmlSchemaCheckRCaseNSCompat:
17020  * @ctxt:  the schema parser context
17021  * @r: the restricting element declaration particle
17022  * @b: the base wildcard particle
17023  *
17024  * (3.9.6) Constraints on Particle Schema Components
17025  * Schema Component Constraint:
17026  * Particle Derivation OK (Elt:Any -- NSCompat)
17027  * (rcase-NSCompat)
17028  *
17029  * STATUS: complete
17030  *
17031  * Returns 0 if the constraints are satisfied, a positive
17032  * error code if not and -1 if an internal error occurred.
17033  */
17034 static int
xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)17035 xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
17036 			    xmlSchemaParticlePtr r,
17037 			    xmlSchemaParticlePtr b)
17038 {
17039     /* TODO:Error codes (rcase-NSCompat). */
17040     /*
17041     * SPEC "For an element declaration particle to be a `valid restriction`
17042     * of a wildcard particle all of the following must be true:"
17043     *
17044     * SPEC (1) "The element declaration's {target namespace} is `valid`
17045     * with respect to the wildcard's {namespace constraint} as defined by
17046     * Wildcard allows Namespace Name ($3.10.4)."
17047     */
17048     if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
17049 	((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
17050 	return (1);
17051     /*
17052     * SPEC (2) "R's occurrence range is a valid restriction of B's
17053     * occurrence range as defined by Occurrence Range OK ($3.9.6)."
17054     */
17055     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17056 	    b->minOccurs, b->maxOccurs) != 0)
17057 	return (1);
17058 
17059     return (0);
17060 }
17061 
17062 /**
17063  * xmlSchemaCheckRCaseRecurseAsIfGroup:
17064  * @ctxt:  the schema parser context
17065  * @r: the restricting element declaration particle
17066  * @b: the base model group particle
17067  *
17068  * (3.9.6) Constraints on Particle Schema Components
17069  * Schema Component Constraint:
17070  * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
17071  * (rcase-RecurseAsIfGroup)
17072  *
17073  * STATUS: TODO
17074  *
17075  * Returns 0 if the constraints are satisfied, a positive
17076  * error code if not and -1 if an internal error occurred.
17077  */
17078 static int
xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)17079 xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
17080 				    xmlSchemaParticlePtr r,
17081 				    xmlSchemaParticlePtr b)
17082 {
17083     /* TODO: Error codes (rcase-RecurseAsIfGroup). */
17084     TODO
17085     return (0);
17086 }
17087 
17088 /**
17089  * xmlSchemaCheckRCaseNSSubset:
17090  * @ctxt:  the schema parser context
17091  * @r: the restricting wildcard particle
17092  * @b: the base wildcard particle
17093  *
17094  * (3.9.6) Constraints on Particle Schema Components
17095  * Schema Component Constraint:
17096  * Particle Derivation OK (Any:Any -- NSSubset)
17097  * (rcase-NSSubset)
17098  *
17099  * STATUS: complete
17100  *
17101  * Returns 0 if the constraints are satisfied, a positive
17102  * error code if not and -1 if an internal error occurred.
17103  */
17104 static int
xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b,int isAnyTypeBase)17105 xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
17106 				    xmlSchemaParticlePtr r,
17107 				    xmlSchemaParticlePtr b,
17108 				    int isAnyTypeBase)
17109 {
17110     /* TODO: Error codes (rcase-NSSubset). */
17111     /*
17112     * SPEC (1) "R's occurrence range is a valid restriction of B's
17113     * occurrence range as defined by Occurrence Range OK ($3.9.6)."
17114     */
17115     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17116 	    b->minOccurs, b->maxOccurs))
17117 	return (1);
17118     /*
17119     * SPEC (2) "R's {namespace constraint} must be an intensional subset
17120     * of B's {namespace constraint} as defined by Wildcard Subset ($3.10.6)."
17121     */
17122     if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
17123 	(xmlSchemaWildcardPtr) b->children))
17124 	return (1);
17125     /*
17126     * SPEC (3) "Unless B is the content model wildcard of the `ur-type
17127     * definition`, R's {process contents} must be identical to or stronger
17128     * than B's {process contents}, where strict is stronger than lax is
17129     * stronger than skip."
17130     */
17131     if (! isAnyTypeBase) {
17132 	if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
17133 	    ((xmlSchemaWildcardPtr) b->children)->processContents)
17134 	    return (1);
17135     }
17136 
17137     return (0);
17138 }
17139 
17140 /**
17141  * xmlSchemaCheckCOSParticleRestrict:
17142  * @ctxt:  the schema parser context
17143  * @type:  the complex type definition
17144  *
17145  * (3.9.6) Constraints on Particle Schema Components
17146  * Schema Component Constraint:
17147  * Particle Valid (Restriction) (cos-particle-restrict)
17148  *
17149  * STATUS: TODO
17150  *
17151  * Returns 0 if the constraints are satisfied, a positive
17152  * error code if not and -1 if an internal error occurred.
17153  */
17154 static int
xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)17155 xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
17156 				  xmlSchemaParticlePtr r,
17157 				  xmlSchemaParticlePtr b)
17158 {
17159     int ret = 0;
17160 
17161     /*part = WXS_TYPE_PARTICLE(type);
17162     basePart = WXS_TYPE_PARTICLE(base);
17163     */
17164 
17165     TODO
17166 
17167     /*
17168     * SPEC (1) "They are the same particle."
17169     */
17170     if (r == b)
17171 	return (0);
17172 
17173 
17174     return (0);
17175 }
17176 
17177 #if 0
17178 /**
17179  * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
17180  * @ctxt:  the schema parser context
17181  * @r: the model group particle
17182  * @b: the base wildcard particle
17183  *
17184  * (3.9.6) Constraints on Particle Schema Components
17185  * Schema Component Constraint:
17186  * Particle Derivation OK (All/Choice/Sequence:Any --
17187  *                         NSRecurseCheckCardinality)
17188  * (rcase-NSRecurseCheckCardinality)
17189  *
17190  * STATUS: TODO: subst-groups
17191  *
17192  * Returns 0 if the constraints are satisfied, a positive
17193  * error code if not and -1 if an internal error occurred.
17194  */
17195 static int
17196 xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
17197 					     xmlSchemaParticlePtr r,
17198 					     xmlSchemaParticlePtr b)
17199 {
17200     xmlSchemaParticlePtr part;
17201     /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
17202     if ((r->children == NULL) || (r->children->children == NULL))
17203 	return (-1);
17204     /*
17205     * SPEC "For a group particle to be a `valid restriction` of a
17206     * wildcard particle..."
17207     *
17208     * SPEC (1) "Every member of the {particles} of the group is a `valid
17209     * restriction` of the wildcard as defined by
17210     * Particle Valid (Restriction) ($3.9.6)."
17211     */
17212     part = (xmlSchemaParticlePtr) r->children->children;
17213     do {
17214 	if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
17215 	    return (1);
17216 	part = (xmlSchemaParticlePtr) part->next;
17217     } while (part != NULL);
17218     /*
17219     * SPEC (2) "The effective total range of the group [...] is a
17220     * valid restriction of B's occurrence range as defined by
17221     * Occurrence Range OK ($3.9.6)."
17222     */
17223     if (xmlSchemaCheckParticleRangeOK(
17224 	    xmlSchemaGetParticleTotalRangeMin(r),
17225 	    xmlSchemaGetParticleTotalRangeMax(r),
17226 	    b->minOccurs, b->maxOccurs) != 0)
17227 	return (1);
17228     return (0);
17229 }
17230 #endif
17231 
17232 /**
17233  * xmlSchemaCheckRCaseRecurse:
17234  * @ctxt:  the schema parser context
17235  * @r: the <all> or <sequence> model group particle
17236  * @b: the base <all> or <sequence> model group particle
17237  *
17238  * (3.9.6) Constraints on Particle Schema Components
17239  * Schema Component Constraint:
17240  * Particle Derivation OK (All:All,Sequence:Sequence --
17241                            Recurse)
17242  * (rcase-Recurse)
17243  *
17244  * STATUS:  ?
17245  * TODO: subst-groups
17246  *
17247  * Returns 0 if the constraints are satisfied, a positive
17248  * error code if not and -1 if an internal error occurred.
17249  */
17250 static int
xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)17251 xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
17252 			   xmlSchemaParticlePtr r,
17253 			   xmlSchemaParticlePtr b)
17254 {
17255     /* xmlSchemaParticlePtr part; */
17256     /* TODO: Error codes (rcase-Recurse). */
17257     if ((r->children == NULL) || (b->children == NULL) ||
17258 	(r->children->type != b->children->type))
17259 	return (-1);
17260     /*
17261     * SPEC "For an all or sequence group particle to be a `valid
17262     * restriction` of another group particle with the same {compositor}..."
17263     *
17264     * SPEC (1) "R's occurrence range is a valid restriction of B's
17265     * occurrence range as defined by Occurrence Range OK ($3.9.6)."
17266     */
17267     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17268 	    b->minOccurs, b->maxOccurs))
17269 	return (1);
17270 
17271 
17272     return (0);
17273 }
17274 
17275 #endif
17276 
17277 #define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
17278     xmlSchemaPCustomErrExt(pctxt,      \
17279 	XML_SCHEMAP_INVALID_FACET_VALUE, \
17280 	WXS_BASIC_CAST fac1, fac1->node, \
17281 	"It is an error for both '%s' and '%s' to be specified on the "\
17282 	"same type definition", \
17283 	BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
17284 	BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
17285 
17286 #define FACET_RESTR_ERR(fac1, msg) \
17287     xmlSchemaPCustomErr(pctxt,      \
17288 	XML_SCHEMAP_INVALID_FACET_VALUE, \
17289 	WXS_BASIC_CAST fac1, fac1->node, \
17290 	msg, NULL);
17291 
17292 #define FACET_RESTR_FIXED_ERR(fac) \
17293     xmlSchemaPCustomErr(pctxt, \
17294 	XML_SCHEMAP_INVALID_FACET_VALUE, \
17295 	WXS_BASIC_CAST fac, fac->node, \
17296 	"The base type's facet is 'fixed', thus the value must not " \
17297 	"differ", NULL);
17298 
17299 static void
xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,xmlSchemaFacetPtr facet1,xmlSchemaFacetPtr facet2,int lessGreater,int orEqual,int ofBase)17300 xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
17301 			xmlSchemaFacetPtr facet1,
17302 			xmlSchemaFacetPtr facet2,
17303 			int lessGreater,
17304 			int orEqual,
17305 			int ofBase)
17306 {
17307     xmlChar *msg = NULL;
17308 
17309     msg = xmlStrdup(BAD_CAST "'");
17310     msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
17311     msg = xmlStrcat(msg, BAD_CAST "' has to be");
17312     if (lessGreater == 0)
17313 	msg = xmlStrcat(msg, BAD_CAST " equal to");
17314     if (lessGreater == 1)
17315 	msg = xmlStrcat(msg, BAD_CAST " greater than");
17316     else
17317 	msg = xmlStrcat(msg, BAD_CAST " less than");
17318 
17319     if (orEqual)
17320 	msg = xmlStrcat(msg, BAD_CAST " or equal to");
17321     msg = xmlStrcat(msg, BAD_CAST " '");
17322     msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
17323     if (ofBase)
17324 	msg = xmlStrcat(msg, BAD_CAST "' of the base type");
17325     else
17326 	msg = xmlStrcat(msg, BAD_CAST "'");
17327 
17328     xmlSchemaPCustomErr(pctxt,
17329 	XML_SCHEMAP_INVALID_FACET_VALUE,
17330 	WXS_BASIC_CAST facet1, NULL,
17331 	(const char *) msg, NULL);
17332 
17333     if (msg != NULL)
17334 	xmlFree(msg);
17335 }
17336 
17337 /*
17338 * xmlSchemaDeriveAndValidateFacets:
17339 *
17340 * Schema Component Constraint: Simple Type Restriction (Facets)
17341 * (st-restrict-facets)
17342 */
17343 static int
xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)17344 xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
17345 				 xmlSchemaTypePtr type)
17346 {
17347     xmlSchemaTypePtr base = type->baseType;
17348     xmlSchemaFacetLinkPtr link, cur, last = NULL;
17349     xmlSchemaFacetPtr facet, bfacet,
17350 	flength = NULL, ftotdig = NULL, ffracdig = NULL,
17351 	fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
17352 	fmininc = NULL, fmaxinc = NULL,
17353 	fminexc = NULL, fmaxexc = NULL,
17354 	bflength = NULL, bftotdig = NULL, bffracdig = NULL,
17355 	bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
17356 	bfmininc = NULL, bfmaxinc = NULL,
17357 	bfminexc = NULL, bfmaxexc = NULL;
17358     int res; /* err = 0, fixedErr; */
17359 
17360     /*
17361     * SPEC st-restrict-facets 1:
17362     * "The {variety} of R is the same as that of B."
17363     */
17364     /*
17365     * SPEC st-restrict-facets 2:
17366     * "If {variety} is atomic, the {primitive type definition}
17367     * of R is the same as that of B."
17368     *
17369     * NOTE: we leave 1 & 2 out for now, since this will be
17370     * satisfied by the derivation process.
17371     * CONSTRUCTION TODO: Maybe needed if using a construction API.
17372     */
17373     /*
17374     * SPEC st-restrict-facets 3:
17375     * "The {facets} of R are the union of S and the {facets}
17376     * of B, eliminating duplicates. To eliminate duplicates,
17377     * when a facet of the same kind occurs in both S and the
17378     * {facets} of B, the one in the {facets} of B is not
17379     * included, with the exception of enumeration and pattern
17380     * facets, for which multiple occurrences with distinct values
17381     * are allowed."
17382     */
17383 
17384     if ((type->facetSet == NULL) && (base->facetSet == NULL))
17385 	return (0);
17386 
17387     last = type->facetSet;
17388     if (last != NULL)
17389 	while (last->next != NULL)
17390 	    last = last->next;
17391 
17392     for (cur = type->facetSet; cur != NULL; cur = cur->next) {
17393 	facet = cur->facet;
17394 	switch (facet->type) {
17395 	    case XML_SCHEMA_FACET_LENGTH:
17396 		flength = facet; break;
17397 	    case XML_SCHEMA_FACET_MINLENGTH:
17398 		fminlen = facet; break;
17399 	    case XML_SCHEMA_FACET_MININCLUSIVE:
17400 		fmininc = facet; break;
17401 	    case XML_SCHEMA_FACET_MINEXCLUSIVE:
17402 		fminexc = facet; break;
17403 	    case XML_SCHEMA_FACET_MAXLENGTH:
17404 		fmaxlen = facet; break;
17405 	    case XML_SCHEMA_FACET_MAXINCLUSIVE:
17406 		fmaxinc = facet; break;
17407 	    case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17408 		fmaxexc = facet; break;
17409 	    case XML_SCHEMA_FACET_TOTALDIGITS:
17410 		ftotdig = facet; break;
17411 	    case XML_SCHEMA_FACET_FRACTIONDIGITS:
17412 		ffracdig = facet; break;
17413 	    default:
17414 		break;
17415 	}
17416     }
17417     for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17418 	facet = cur->facet;
17419 	switch (facet->type) {
17420 	    case XML_SCHEMA_FACET_LENGTH:
17421 		bflength = facet; break;
17422 	    case XML_SCHEMA_FACET_MINLENGTH:
17423 		bfminlen = facet; break;
17424 	    case XML_SCHEMA_FACET_MININCLUSIVE:
17425 		bfmininc = facet; break;
17426 	    case XML_SCHEMA_FACET_MINEXCLUSIVE:
17427 		bfminexc = facet; break;
17428 	    case XML_SCHEMA_FACET_MAXLENGTH:
17429 		bfmaxlen = facet; break;
17430 	    case XML_SCHEMA_FACET_MAXINCLUSIVE:
17431 		bfmaxinc = facet; break;
17432 	    case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17433 		bfmaxexc = facet; break;
17434 	    case XML_SCHEMA_FACET_TOTALDIGITS:
17435 		bftotdig = facet; break;
17436 	    case XML_SCHEMA_FACET_FRACTIONDIGITS:
17437 		bffracdig = facet; break;
17438 	    default:
17439 		break;
17440 	}
17441     }
17442     /*
17443     * length and minLength or maxLength (2.2) + (3.2)
17444     */
17445     if (flength && (fminlen || fmaxlen)) {
17446 	FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
17447 	    "either of 'minLength' or 'maxLength' to be specified on "
17448 	    "the same type definition")
17449     }
17450     /*
17451     * Mutual exclusions in the same derivation step.
17452     */
17453     if ((fmaxinc) && (fmaxexc)) {
17454 	/*
17455 	* SCC "maxInclusive and maxExclusive"
17456 	*/
17457 	FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
17458     }
17459     if ((fmininc) && (fminexc)) {
17460 	/*
17461 	* SCC "minInclusive and minExclusive"
17462 	*/
17463 	FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
17464     }
17465 
17466     if (flength && bflength) {
17467 	/*
17468 	* SCC "length valid restriction"
17469 	* The values have to be equal.
17470 	*/
17471 	res = xmlSchemaCompareValues(flength->val, bflength->val);
17472 	if (res == -2)
17473 	    goto internal_error;
17474 	if (res != 0)
17475 	    xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
17476 	if ((res != 0) && (bflength->fixed)) {
17477 	    FACET_RESTR_FIXED_ERR(flength)
17478 	}
17479 
17480     }
17481     if (fminlen && bfminlen) {
17482 	/*
17483 	* SCC "minLength valid restriction"
17484 	* minLength >= BASE minLength
17485 	*/
17486 	res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
17487 	if (res == -2)
17488 	    goto internal_error;
17489 	if (res == -1)
17490 	    xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
17491 	if ((res != 0) && (bfminlen->fixed)) {
17492 	    FACET_RESTR_FIXED_ERR(fminlen)
17493 	}
17494     }
17495     if (fmaxlen && bfmaxlen) {
17496 	/*
17497 	* SCC "maxLength valid restriction"
17498 	* maxLength <= BASE minLength
17499 	*/
17500 	res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
17501 	if (res == -2)
17502 	    goto internal_error;
17503 	if (res == 1)
17504 	    xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
17505 	if ((res != 0) && (bfmaxlen->fixed)) {
17506 	    FACET_RESTR_FIXED_ERR(fmaxlen)
17507 	}
17508     }
17509     /*
17510     * SCC "length and minLength or maxLength"
17511     */
17512     if (! flength)
17513 	flength = bflength;
17514     if (flength) {
17515 	if (! fminlen)
17516 	    fminlen = bfminlen;
17517 	if (fminlen) {
17518 	    /* (1.1) length >= minLength */
17519 	    res = xmlSchemaCompareValues(flength->val, fminlen->val);
17520 	    if (res == -2)
17521 		goto internal_error;
17522 	    if (res == -1)
17523 		xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
17524 	}
17525 	if (! fmaxlen)
17526 	    fmaxlen = bfmaxlen;
17527 	if (fmaxlen) {
17528 	    /* (2.1) length <= maxLength */
17529 	    res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
17530 	    if (res == -2)
17531 		goto internal_error;
17532 	    if (res == 1)
17533 		xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
17534 	}
17535     }
17536     if (fmaxinc) {
17537 	/*
17538 	* "maxInclusive"
17539 	*/
17540 	if (fmininc) {
17541 	    /* SCC "maxInclusive >= minInclusive" */
17542 	    res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
17543 	    if (res == -2)
17544 		goto internal_error;
17545 	    if (res == -1) {
17546 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
17547 	    }
17548 	}
17549 	/*
17550 	* SCC "maxInclusive valid restriction"
17551 	*/
17552 	if (bfmaxinc) {
17553 	    /* maxInclusive <= BASE maxInclusive */
17554 	    res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
17555 	    if (res == -2)
17556 		goto internal_error;
17557 	    if (res == 1)
17558 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
17559 	    if ((res != 0) && (bfmaxinc->fixed)) {
17560 		FACET_RESTR_FIXED_ERR(fmaxinc)
17561 	    }
17562 	}
17563 	if (bfmaxexc) {
17564 	    /* maxInclusive < BASE maxExclusive */
17565 	    res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
17566 	    if (res == -2)
17567 		goto internal_error;
17568 	    if (res != -1) {
17569 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
17570 	    }
17571 	}
17572 	if (bfmininc) {
17573 	    /* maxInclusive >= BASE minInclusive */
17574 	    res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
17575 	    if (res == -2)
17576 		goto internal_error;
17577 	    if (res == -1) {
17578 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
17579 	    }
17580 	}
17581 	if (bfminexc) {
17582 	    /* maxInclusive > BASE minExclusive */
17583 	    res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
17584 	    if (res == -2)
17585 		goto internal_error;
17586 	    if (res != 1) {
17587 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
17588 	    }
17589 	}
17590     }
17591     if (fmaxexc) {
17592 	/*
17593 	* "maxExclusive >= minExclusive"
17594 	*/
17595 	if (fminexc) {
17596 	    res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
17597 	    if (res == -2)
17598 		goto internal_error;
17599 	    if (res == -1) {
17600 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
17601 	    }
17602 	}
17603 	/*
17604 	* "maxExclusive valid restriction"
17605 	*/
17606 	if (bfmaxexc) {
17607 	    /* maxExclusive <= BASE maxExclusive */
17608 	    res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
17609 	    if (res == -2)
17610 		goto internal_error;
17611 	    if (res == 1) {
17612 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
17613 	    }
17614 	    if ((res != 0) && (bfmaxexc->fixed)) {
17615 		FACET_RESTR_FIXED_ERR(fmaxexc)
17616 	    }
17617 	}
17618 	if (bfmaxinc) {
17619 	    /* maxExclusive <= BASE maxInclusive */
17620 	    res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
17621 	    if (res == -2)
17622 		goto internal_error;
17623 	    if (res == 1) {
17624 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
17625 	    }
17626 	}
17627 	if (bfmininc) {
17628 	    /* maxExclusive > BASE minInclusive */
17629 	    res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
17630 	    if (res == -2)
17631 		goto internal_error;
17632 	    if (res != 1) {
17633 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
17634 	    }
17635 	}
17636 	if (bfminexc) {
17637 	    /* maxExclusive > BASE minExclusive */
17638 	    res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
17639 	    if (res == -2)
17640 		goto internal_error;
17641 	    if (res != 1) {
17642 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
17643 	    }
17644 	}
17645     }
17646     if (fminexc) {
17647 	/*
17648 	* "minExclusive < maxInclusive"
17649 	*/
17650 	if (fmaxinc) {
17651 	    res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
17652 	    if (res == -2)
17653 		goto internal_error;
17654 	    if (res != -1) {
17655 		xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
17656 	    }
17657 	}
17658 	/*
17659 	* "minExclusive valid restriction"
17660 	*/
17661 	if (bfminexc) {
17662 	    /* minExclusive >= BASE minExclusive */
17663 	    res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
17664 	    if (res == -2)
17665 		goto internal_error;
17666 	    if (res == -1) {
17667 		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
17668 	    }
17669 	    if ((res != 0) && (bfminexc->fixed)) {
17670 		FACET_RESTR_FIXED_ERR(fminexc)
17671 	    }
17672 	}
17673 	if (bfmaxinc) {
17674 	    /* minExclusive <= BASE maxInclusive */
17675 	    res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
17676 	    if (res == -2)
17677 		goto internal_error;
17678 	    if (res == 1) {
17679 		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
17680 	    }
17681 	}
17682 	if (bfmininc) {
17683 	    /* minExclusive >= BASE minInclusive */
17684 	    res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
17685 	    if (res == -2)
17686 		goto internal_error;
17687 	    if (res == -1) {
17688 		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
17689 	    }
17690 	}
17691 	if (bfmaxexc) {
17692 	    /* minExclusive < BASE maxExclusive */
17693 	    res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
17694 	    if (res == -2)
17695 		goto internal_error;
17696 	    if (res != -1) {
17697 		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
17698 	    }
17699 	}
17700     }
17701     if (fmininc) {
17702 	/*
17703 	* "minInclusive < maxExclusive"
17704 	*/
17705 	if (fmaxexc) {
17706 	    res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
17707 	    if (res == -2)
17708 		goto internal_error;
17709 	    if (res != -1) {
17710 		xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
17711 	    }
17712 	}
17713 	/*
17714 	* "minExclusive valid restriction"
17715 	*/
17716 	if (bfmininc) {
17717 	    /* minInclusive >= BASE minInclusive */
17718 	    res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
17719 	    if (res == -2)
17720 		goto internal_error;
17721 	    if (res == -1) {
17722 		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
17723 	    }
17724 	    if ((res != 0) && (bfmininc->fixed)) {
17725 		FACET_RESTR_FIXED_ERR(fmininc)
17726 	    }
17727 	}
17728 	if (bfmaxinc) {
17729 	    /* minInclusive <= BASE maxInclusive */
17730 	    res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
17731 	    if (res == -2)
17732 		goto internal_error;
17733 	    if (res == 1) {
17734 		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
17735 	    }
17736 	}
17737 	if (bfminexc) {
17738 	    /* minInclusive > BASE minExclusive */
17739 	    res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
17740 	    if (res == -2)
17741 		goto internal_error;
17742 	    if (res != 1)
17743 		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
17744 	}
17745 	if (bfmaxexc) {
17746 	    /* minInclusive < BASE maxExclusive */
17747 	    res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
17748 	    if (res == -2)
17749 		goto internal_error;
17750 	    if (res != -1)
17751 		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
17752 	}
17753     }
17754     if (ftotdig && bftotdig) {
17755 	/*
17756 	* SCC " totalDigits valid restriction"
17757 	* totalDigits <= BASE totalDigits
17758 	*/
17759 	res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
17760 	if (res == -2)
17761 	    goto internal_error;
17762 	if (res == 1)
17763 	    xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
17764 	    -1, 1, 1);
17765 	if ((res != 0) && (bftotdig->fixed)) {
17766 	    FACET_RESTR_FIXED_ERR(ftotdig)
17767 	}
17768     }
17769     if (ffracdig && bffracdig) {
17770 	/*
17771 	* SCC  "fractionDigits valid restriction"
17772 	* fractionDigits <= BASE fractionDigits
17773 	*/
17774 	res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
17775 	if (res == -2)
17776 	    goto internal_error;
17777 	if (res == 1)
17778 	    xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
17779 	    -1, 1, 1);
17780 	if ((res != 0) && (bffracdig->fixed)) {
17781 	    FACET_RESTR_FIXED_ERR(ffracdig)
17782 	}
17783     }
17784     /*
17785     * SCC "fractionDigits less than or equal to totalDigits"
17786     */
17787     if (! ftotdig)
17788 	ftotdig = bftotdig;
17789     if (! ffracdig)
17790 	ffracdig = bffracdig;
17791     if (ftotdig && ffracdig) {
17792 	res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
17793 	if (res == -2)
17794 	    goto internal_error;
17795 	if (res == 1)
17796 	    xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
17797 		-1, 1, 0);
17798     }
17799     /*
17800     * *Enumerations* won' be added here, since only the first set
17801     * of enumerations in the ancestor-or-self axis is used
17802     * for validation, plus we need to use the base type of those
17803     * enumerations for whitespace.
17804     *
17805     * *Patterns*: won't be add here, since they are ORed at
17806     * type level and ANDed at ancestor level. This will
17807     * happen during validation by walking the base axis
17808     * of the type.
17809     */
17810     for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17811 	bfacet = cur->facet;
17812 	/*
17813 	* Special handling of enumerations and patterns.
17814 	* TODO: hmm, they should not appear in the set, so remove this.
17815 	*/
17816 	if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
17817 	    (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
17818 	    continue;
17819 	/*
17820 	* Search for a duplicate facet in the current type.
17821 	*/
17822 	link = type->facetSet;
17823 	/* err = 0; */
17824 	/* fixedErr = 0; */
17825 	while (link != NULL) {
17826 	    facet = link->facet;
17827 	    if (facet->type == bfacet->type) {
17828 		switch (facet->type) {
17829 		    case XML_SCHEMA_FACET_WHITESPACE:
17830 			/*
17831 			* The whitespace must be stronger.
17832 			*/
17833 			if (facet->whitespace < bfacet->whitespace) {
17834 			    FACET_RESTR_ERR(facet,
17835 				"The 'whitespace' value has to be equal to "
17836 				"or stronger than the 'whitespace' value of "
17837 				"the base type")
17838 			}
17839 			if ((bfacet->fixed) &&
17840 			    (facet->whitespace != bfacet->whitespace)) {
17841 			    FACET_RESTR_FIXED_ERR(facet)
17842 			}
17843 			break;
17844 		    default:
17845 			break;
17846 		}
17847 		/* Duplicate found. */
17848 		break;
17849 	    }
17850 	    link = link->next;
17851 	}
17852 	/*
17853 	* If no duplicate was found: add the base types's facet
17854 	* to the set.
17855 	*/
17856 	if (link == NULL) {
17857 	    link = (xmlSchemaFacetLinkPtr)
17858 		xmlMalloc(sizeof(xmlSchemaFacetLink));
17859 	    if (link == NULL) {
17860 		xmlSchemaPErrMemory(pctxt,
17861 		    "deriving facets, creating a facet link", NULL);
17862 		return (-1);
17863 	    }
17864 	    link->facet = cur->facet;
17865 	    link->next = NULL;
17866 	    if (last == NULL)
17867 		type->facetSet = link;
17868 	    else
17869 		last->next = link;
17870 	    last = link;
17871 	}
17872 
17873     }
17874 
17875     return (0);
17876 internal_error:
17877     PERROR_INT("xmlSchemaDeriveAndValidateFacets",
17878 	"an error occurred");
17879     return (-1);
17880 }
17881 
17882 static int
xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)17883 xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
17884 					     xmlSchemaTypePtr type)
17885 {
17886     xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
17887     /*
17888     * The actual value is then formed by replacing any union type
17889     * definition in the `explicit members` with the members of their
17890     * {member type definitions}, in order.
17891     *
17892     * TODO: There's a bug entry at
17893     * "http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0287.html"
17894     * which indicates that we'll keep the union types the future.
17895     */
17896     link = type->memberTypes;
17897     while (link != NULL) {
17898 
17899 	if (WXS_IS_TYPE_NOT_FIXED(link->type))
17900 	    xmlSchemaTypeFixup(link->type, ACTXT_CAST pctxt);
17901 
17902 	if (WXS_IS_UNION(link->type)) {
17903 	    subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
17904 	    if (subLink != NULL) {
17905 		link->type = subLink->type;
17906 		if (subLink->next != NULL) {
17907 		    lastLink = link->next;
17908 		    subLink = subLink->next;
17909 		    prevLink = link;
17910 		    while (subLink != NULL) {
17911 			newLink = (xmlSchemaTypeLinkPtr)
17912 			    xmlMalloc(sizeof(xmlSchemaTypeLink));
17913 			if (newLink == NULL) {
17914 			    xmlSchemaPErrMemory(pctxt, "allocating a type link",
17915 				NULL);
17916 			    return (-1);
17917 			}
17918 			newLink->type = subLink->type;
17919 			prevLink->next = newLink;
17920 			prevLink = newLink;
17921 			newLink->next = lastLink;
17922 
17923 			subLink = subLink->next;
17924 		    }
17925 		}
17926 	    }
17927 	}
17928 	link = link->next;
17929     }
17930     return (0);
17931 }
17932 
17933 static void
xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)17934 xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
17935 {
17936     int has = 0, needVal = 0, normVal = 0;
17937 
17938     has	= (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
17939     if (has) {
17940 	needVal = (type->baseType->flags &
17941 	    XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
17942 	normVal = (type->baseType->flags &
17943 	    XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
17944     }
17945     if (type->facets != NULL) {
17946 	xmlSchemaFacetPtr fac;
17947 
17948 	for (fac = type->facets; fac != NULL; fac = fac->next) {
17949 	    switch (fac->type) {
17950 		case XML_SCHEMA_FACET_WHITESPACE:
17951 		    break;
17952 		case XML_SCHEMA_FACET_PATTERN:
17953 		    normVal = 1;
17954 		    has = 1;
17955 		    break;
17956 		case XML_SCHEMA_FACET_ENUMERATION:
17957 		    needVal = 1;
17958 		    normVal = 1;
17959 		    has = 1;
17960 		    break;
17961 		default:
17962 		    has = 1;
17963 		    break;
17964 	    }
17965 	}
17966     }
17967     if (normVal)
17968 	type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
17969     if (needVal)
17970 	type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17971     if (has)
17972 	type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
17973 
17974     if (has && (! needVal) && WXS_IS_ATOMIC(type)) {
17975 	xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
17976 	/*
17977 	* OPTIMIZE VAL TODO: Some facets need a computed value.
17978 	*/
17979 	if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
17980 	    (prim->builtInType != XML_SCHEMAS_STRING)) {
17981 	    type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17982 	}
17983     }
17984 }
17985 
17986 static int
xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)17987 xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
17988 {
17989 
17990 
17991     /*
17992     * Evaluate the whitespace-facet value.
17993     */
17994     if (WXS_IS_LIST(type)) {
17995 	type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17996 	return (0);
17997     } else if (WXS_IS_UNION(type))
17998 	return (0);
17999 
18000     if (type->facetSet != NULL) {
18001 	xmlSchemaFacetLinkPtr lin;
18002 
18003 	for (lin = type->facetSet; lin != NULL; lin = lin->next) {
18004 	    if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
18005 		switch (lin->facet->whitespace) {
18006 		case XML_SCHEMAS_FACET_PRESERVE:
18007 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
18008 		    break;
18009 		case XML_SCHEMAS_FACET_REPLACE:
18010 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
18011 		    break;
18012 		case XML_SCHEMAS_FACET_COLLAPSE:
18013 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
18014 		    break;
18015 		default:
18016 		    return (-1);
18017 		}
18018 		return (0);
18019 	    }
18020 	}
18021     }
18022     /*
18023     * For all `atomic` datatypes other than string (and types `derived`
18024     * by `restriction` from it) the value of whiteSpace is fixed to
18025     * collapse
18026     */
18027     {
18028 	xmlSchemaTypePtr anc;
18029 
18030 	for (anc = type->baseType; anc != NULL &&
18031 		anc->builtInType != XML_SCHEMAS_ANYTYPE;
18032 		anc = anc->baseType) {
18033 
18034 	    if (anc->type == XML_SCHEMA_TYPE_BASIC) {
18035 		if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
18036 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
18037 
18038 		} else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
18039 		    (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
18040 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
18041 
18042 		} else
18043 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
18044 		break;
18045 	    }
18046 	}
18047     }
18048     return (0);
18049 }
18050 
18051 static int
xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)18052 xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,
18053 			  xmlSchemaTypePtr type)
18054 {
18055     if (type->type != XML_SCHEMA_TYPE_SIMPLE)
18056 	return(0);
18057     if (! WXS_IS_TYPE_NOT_FIXED_1(type))
18058 	return(0);
18059     type->flags |= XML_SCHEMAS_TYPE_FIXUP_1;
18060 
18061     if (WXS_IS_LIST(type)) {
18062 	/*
18063 	* Corresponds to <simpleType><list>...
18064 	*/
18065 	if (type->subtypes == NULL) {
18066 	    /*
18067 	    * This one is really needed, so get out.
18068 	    */
18069 	    PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
18070 		"list type has no item-type assigned");
18071 	    return(-1);
18072 	}
18073     } else if (WXS_IS_UNION(type)) {
18074 	/*
18075 	* Corresponds to <simpleType><union>...
18076 	*/
18077 	if (type->memberTypes == NULL) {
18078 	    /*
18079 	    * This one is really needed, so get out.
18080 	    */
18081 	    PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
18082 		"union type has no member-types assigned");
18083 	    return(-1);
18084 	}
18085     } else {
18086 	/*
18087 	* Corresponds to <simpleType><restriction>...
18088 	*/
18089 	if (type->baseType == NULL) {
18090 	    PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
18091 		"type has no base-type assigned");
18092 	    return(-1);
18093 	}
18094 	if (WXS_IS_TYPE_NOT_FIXED_1(type->baseType))
18095 	    if (xmlSchemaFixupSimpleTypeStageOne(pctxt, type->baseType) == -1)
18096 		return(-1);
18097 	/*
18098 	* Variety
18099 	* If the <restriction> alternative is chosen, then the
18100 	* {variety} of the {base type definition}.
18101 	*/
18102 	if (WXS_IS_ATOMIC(type->baseType))
18103 	    type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
18104 	else if (WXS_IS_LIST(type->baseType)) {
18105 	    type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
18106 	    /*
18107 	    * Inherit the itemType.
18108 	    */
18109 	    type->subtypes = type->baseType->subtypes;
18110 	} else if (WXS_IS_UNION(type->baseType)) {
18111 	    type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
18112 	    /*
18113 	    * NOTE that we won't assign the memberTypes of the base,
18114 	    * since this will make trouble when freeing them; we will
18115 	    * use a lookup function to access them instead.
18116 	    */
18117 	}
18118     }
18119     return(0);
18120 }
18121 
18122 #ifdef DEBUG_TYPE
18123 static void
xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)18124 xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt,
18125 		       xmlSchemaTypePtr type)
18126 {
18127     if (type->node != NULL) {
18128         xmlGenericError(xmlGenericErrorContext,
18129                         "Type of %s : %s:%d :", name,
18130                         type->node->doc->URL,
18131                         xmlGetLineNo(type->node));
18132     } else {
18133         xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
18134     }
18135     if ((WXS_IS_SIMPLE(type)) || (WXS_IS_COMPLEX(type))) {
18136 	switch (type->contentType) {
18137 	    case XML_SCHEMA_CONTENT_SIMPLE:
18138 		xmlGenericError(xmlGenericErrorContext, "simple\n");
18139 		break;
18140 	    case XML_SCHEMA_CONTENT_ELEMENTS:
18141 		xmlGenericError(xmlGenericErrorContext, "elements\n");
18142 		break;
18143 	    case XML_SCHEMA_CONTENT_UNKNOWN:
18144 		xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
18145 		break;
18146 	    case XML_SCHEMA_CONTENT_EMPTY:
18147 		xmlGenericError(xmlGenericErrorContext, "empty\n");
18148 		break;
18149 	    case XML_SCHEMA_CONTENT_MIXED:
18150 		if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
18151 		    type->subtypes))
18152 		    xmlGenericError(xmlGenericErrorContext,
18153 			"mixed as emptiable particle\n");
18154 		else
18155 		    xmlGenericError(xmlGenericErrorContext, "mixed\n");
18156 		break;
18157 		/* Removed, since not used. */
18158 		/*
18159 		case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
18160 		xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
18161 		break;
18162 		*/
18163 	    case XML_SCHEMA_CONTENT_BASIC:
18164 		xmlGenericError(xmlGenericErrorContext, "basic\n");
18165 		break;
18166 	    default:
18167 		xmlGenericError(xmlGenericErrorContext,
18168 		    "not registered !!!\n");
18169 		break;
18170 	}
18171     }
18172 }
18173 #endif
18174 
18175 /*
18176 * 3.14.6 Constraints on Simple Type Definition Schema Components
18177 */
18178 static int
xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)18179 xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,
18180 				 xmlSchemaTypePtr type)
18181 {
18182     int res, olderrs = pctxt->nberrors;
18183 
18184     if (type->type != XML_SCHEMA_TYPE_SIMPLE)
18185 	return(-1);
18186 
18187     if (! WXS_IS_TYPE_NOT_FIXED(type))
18188 	return(0);
18189 
18190     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18191     type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
18192 
18193     if (type->baseType == NULL) {
18194 	PERROR_INT("xmlSchemaFixupSimpleTypeStageTwo",
18195 	    "missing baseType");
18196 	goto exit_failure;
18197     }
18198     if (WXS_IS_TYPE_NOT_FIXED(type->baseType))
18199 	xmlSchemaTypeFixup(type->baseType, ACTXT_CAST pctxt);
18200     /*
18201     * If a member type of a union is a union itself, we need to substitute
18202     * that member type for its member types.
18203     * NOTE that this might change in WXS 1.1; i.e. we will keep the union
18204     * types in WXS 1.1.
18205     */
18206     if ((type->memberTypes != NULL) &&
18207 	(xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1))
18208 	return(-1);
18209     /*
18210     * SPEC src-simple-type 1
18211     * "The corresponding simple type definition, if any, must satisfy
18212     * the conditions set out in Constraints on Simple Type Definition
18213     * Schema Components ($3.14.6)."
18214     */
18215     /*
18216     * Schema Component Constraint: Simple Type Definition Properties Correct
18217     * (st-props-correct)
18218     */
18219     res = xmlSchemaCheckSTPropsCorrect(pctxt, type);
18220     HFAILURE HERROR
18221     /*
18222     * Schema Component Constraint: Derivation Valid (Restriction, Simple)
18223     * (cos-st-restricts)
18224     */
18225     res = xmlSchemaCheckCOSSTRestricts(pctxt, type);
18226     HFAILURE HERROR
18227     /*
18228     * TODO: Removed the error report, since it got annoying to get an
18229     * extra error report, if anything failed until now.
18230     * Enable this if needed.
18231     *
18232     * xmlSchemaPErr(ctxt, type->node,
18233     *    XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
18234     *    "Simple type '%s' does not satisfy the constraints "
18235     *    "on simple type definitions.\n",
18236     *    type->name, NULL);
18237     */
18238     /*
18239     * Schema Component Constraint: Simple Type Restriction (Facets)
18240     * (st-restrict-facets)
18241     */
18242     res = xmlSchemaCheckFacetValues(type, pctxt);
18243     HFAILURE HERROR
18244     if ((type->facetSet != NULL) ||
18245 	(type->baseType->facetSet != NULL)) {
18246 	res = xmlSchemaDeriveAndValidateFacets(pctxt, type);
18247 	HFAILURE HERROR
18248     }
18249     /*
18250     * Whitespace value.
18251     */
18252     res = xmlSchemaTypeFixupWhitespace(type);
18253     HFAILURE HERROR
18254     xmlSchemaTypeFixupOptimFacets(type);
18255 
18256 exit_error:
18257 #ifdef DEBUG_TYPE
18258     xmlSchemaDebugFixedType(pctxt, type);
18259 #endif
18260     if (olderrs != pctxt->nberrors)
18261 	return(pctxt->err);
18262     return(0);
18263 
18264 exit_failure:
18265 #ifdef DEBUG_TYPE
18266     xmlSchemaDebugFixedType(pctxt, type);
18267 #endif
18268     return(-1);
18269 }
18270 
18271 static int
xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)18272 xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,
18273 			  xmlSchemaTypePtr type)
18274 {
18275     int res = 0, olderrs = pctxt->nberrors;
18276     xmlSchemaTypePtr baseType = type->baseType;
18277 
18278     if (! WXS_IS_TYPE_NOT_FIXED(type))
18279 	return(0);
18280     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18281     if (baseType == NULL) {
18282 	PERROR_INT("xmlSchemaFixupComplexType",
18283 	    "missing baseType");
18284 	goto exit_failure;
18285     }
18286     /*
18287     * Fixup the base type.
18288     */
18289     if (WXS_IS_TYPE_NOT_FIXED(baseType))
18290 	xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt);
18291     if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
18292 	/*
18293 	* Skip fixup if the base type is invalid.
18294 	* TODO: Generate a warning!
18295 	*/
18296 	return(0);
18297     }
18298     /*
18299     * This basically checks if the base type can be derived.
18300     */
18301     res = xmlSchemaCheckSRCCT(pctxt, type);
18302     HFAILURE HERROR
18303     /*
18304     * Fixup the content type.
18305     */
18306     if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
18307 	/*
18308 	* Corresponds to <complexType><simpleContent>...
18309 	*/
18310 	if ((WXS_IS_COMPLEX(baseType)) &&
18311 	    (baseType->contentTypeDef != NULL) &&
18312 	    (WXS_IS_RESTRICTION(type))) {
18313 	    xmlSchemaTypePtr contentBase, content;
18314 #ifdef ENABLE_NAMED_LOCALS
18315 	    char buf[30];
18316 	    const xmlChar *tmpname;
18317 #endif
18318 	    /*
18319 	    * SPEC (1) If <restriction> + base type is <complexType>,
18320 	    * "whose own {content type} is a simple type..."
18321 	    */
18322 	    if (type->contentTypeDef != NULL) {
18323 		/*
18324 		* SPEC (1.1) "the simple type definition corresponding to the
18325 		* <simpleType> among the [children] of <restriction> if there
18326 		* is one;"
18327 		* Note that this "<simpleType> among the [children]" was put
18328 		* into ->contentTypeDef during parsing.
18329 		*/
18330 		contentBase = type->contentTypeDef;
18331 		type->contentTypeDef = NULL;
18332 	    } else {
18333 		/*
18334 		* (1.2) "...otherwise (<restriction> has no <simpleType>
18335 		* among its [children]), the simple type definition which
18336 		* is the {content type} of the ... base type."
18337 		*/
18338 		contentBase = baseType->contentTypeDef;
18339 	    }
18340 	    /*
18341 	    * SPEC
18342 	    * "... a simple type definition which restricts the simple
18343 	    * type definition identified in clause 1.1 or clause 1.2
18344 	    * with a set of facet components"
18345 	    *
18346 	    * Create the anonymous simple type, which will be the content
18347 	    * type of the complex type.
18348 	    */
18349 #ifdef ENABLE_NAMED_LOCALS
18350 	    snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
18351 	    tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
18352 	    content = xmlSchemaAddType(pctxt, pctxt->schema,
18353 		XML_SCHEMA_TYPE_SIMPLE, tmpname, type->targetNamespace,
18354 		type->node, 0);
18355 #else
18356 	    content = xmlSchemaAddType(pctxt, pctxt->schema,
18357 		XML_SCHEMA_TYPE_SIMPLE, NULL, type->targetNamespace,
18358 		type->node, 0);
18359 #endif
18360 	    if (content == NULL)
18361 		goto exit_failure;
18362 	    /*
18363 	    * We will use the same node as for the <complexType>
18364 	    * to have it somehow anchored in the schema doc.
18365 	    */
18366 	    content->type = XML_SCHEMA_TYPE_SIMPLE;
18367 	    content->baseType = contentBase;
18368 	    /*
18369 	    * Move the facets, previously anchored on the
18370 	    * complexType during parsing.
18371 	    */
18372 	    content->facets = type->facets;
18373 	    type->facets = NULL;
18374 	    content->facetSet = type->facetSet;
18375 	    type->facetSet = NULL;
18376 
18377 	    type->contentTypeDef = content;
18378 	    if (WXS_IS_TYPE_NOT_FIXED(contentBase))
18379 		xmlSchemaTypeFixup(contentBase, ACTXT_CAST pctxt);
18380 	    /*
18381 	    * Fixup the newly created type. We don't need to check
18382 	    * for circularity here.
18383 	    */
18384 	    res = xmlSchemaFixupSimpleTypeStageOne(pctxt, content);
18385 	    HFAILURE HERROR
18386 	    res = xmlSchemaFixupSimpleTypeStageTwo(pctxt, content);
18387 	    HFAILURE HERROR
18388 
18389 	} else if ((WXS_IS_COMPLEX(baseType)) &&
18390 	    (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
18391 	    (WXS_IS_RESTRICTION(type))) {
18392 	    /*
18393 	    * SPEC (2) If <restriction> + base is a mixed <complexType> with
18394 	    * an emptiable particle, then a simple type definition which
18395 	    * restricts the <restriction>'s <simpleType> child.
18396 	    */
18397 	    if ((type->contentTypeDef == NULL) ||
18398 		(type->contentTypeDef->baseType == NULL)) {
18399 		/*
18400 		* TODO: Check if this ever happens.
18401 		*/
18402 		xmlSchemaPCustomErr(pctxt,
18403 		    XML_SCHEMAP_INTERNAL,
18404 		    WXS_BASIC_CAST type, NULL,
18405 		    "Internal error: xmlSchemaTypeFixup, "
18406 		    "complex type '%s': the <simpleContent><restriction> "
18407 		    "is missing a <simpleType> child, but was not caught "
18408 		    "by xmlSchemaCheckSRCCT()", type->name);
18409 		goto exit_failure;
18410 	    }
18411 	} else if ((WXS_IS_COMPLEX(baseType)) && WXS_IS_EXTENSION(type)) {
18412 	    /*
18413 	    * SPEC (3) If <extension> + base is <complexType> with
18414 	    * <simpleType> content, "...then the {content type} of that
18415 	    * complex type definition"
18416 	    */
18417 	    if (baseType->contentTypeDef == NULL) {
18418 		/*
18419 		* TODO: Check if this ever happens. xmlSchemaCheckSRCCT
18420 		* should have caught this already.
18421 		*/
18422 		xmlSchemaPCustomErr(pctxt,
18423 		    XML_SCHEMAP_INTERNAL,
18424 		    WXS_BASIC_CAST type, NULL,
18425 		    "Internal error: xmlSchemaTypeFixup, "
18426 		    "complex type '%s': the <extension>ed base type is "
18427 		    "a complex type with no simple content type",
18428 		    type->name);
18429 		goto exit_failure;
18430 	    }
18431 	    type->contentTypeDef = baseType->contentTypeDef;
18432 	} else if ((WXS_IS_SIMPLE(baseType)) && WXS_IS_EXTENSION(type)) {
18433 	    /*
18434 	    * SPEC (4) <extension> + base is <simpleType>
18435 	    * "... then that simple type definition"
18436 	    */
18437 	    type->contentTypeDef = baseType;
18438 	} else {
18439 	    /*
18440 	    * TODO: Check if this ever happens.
18441 	    */
18442 	    xmlSchemaPCustomErr(pctxt,
18443 		XML_SCHEMAP_INTERNAL,
18444 		WXS_BASIC_CAST type, NULL,
18445 		"Internal error: xmlSchemaTypeFixup, "
18446 		"complex type '%s' with <simpleContent>: unhandled "
18447 		"derivation case", type->name);
18448 	    goto exit_failure;
18449 	}
18450     } else {
18451 	int dummySequence = 0;
18452 	xmlSchemaParticlePtr particle =
18453 	    (xmlSchemaParticlePtr) type->subtypes;
18454 	/*
18455 	* Corresponds to <complexType><complexContent>...
18456 	*
18457 	* NOTE that the effective mixed was already set during parsing of
18458 	* <complexType> and <complexContent>; its flag value is
18459 	* XML_SCHEMAS_TYPE_MIXED.
18460 	*
18461 	* Compute the "effective content":
18462 	* (2.1.1) + (2.1.2) + (2.1.3)
18463 	*/
18464 	if ((particle == NULL) ||
18465 	    ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
18466 	    ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
18467 	    (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
18468 	    ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
18469 	    (particle->minOccurs == 0))) &&
18470 	    ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
18471 	    if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
18472 		/*
18473 		* SPEC (2.1.4) "If the `effective mixed` is true, then
18474 		* a particle whose properties are as follows:..."
18475 		*
18476 		* Empty sequence model group with
18477 		* minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
18478 		* NOTE that we sill assign it the <complexType> node to
18479 		* somehow anchor it in the doc.
18480 		*/
18481 		if ((particle == NULL) ||
18482 		    (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
18483 		    /*
18484 		    * Create the particle.
18485 		    */
18486 		    particle = xmlSchemaAddParticle(pctxt,
18487 			type->node, 1, 1);
18488 		    if (particle == NULL)
18489 			goto exit_failure;
18490 		    /*
18491 		    * Create the model group.
18492 		    */ /* URGENT TODO: avoid adding to pending items. */
18493 		    particle->children = (xmlSchemaTreeItemPtr)
18494 			xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18495 			XML_SCHEMA_TYPE_SEQUENCE, type->node);
18496 		    if (particle->children == NULL)
18497 			goto exit_failure;
18498 
18499 		    type->subtypes = (xmlSchemaTypePtr) particle;
18500 		}
18501 		dummySequence = 1;
18502 		type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18503 	    } else {
18504 		/*
18505 		* SPEC (2.1.5) "otherwise empty"
18506 		*/
18507 		type->contentType = XML_SCHEMA_CONTENT_EMPTY;
18508 	    }
18509 	} else {
18510 	    /*
18511 	    * SPEC (2.2) "otherwise the particle corresponding to the
18512 	    * <all>, <choice>, <group> or <sequence> among the
18513 	    * [children]."
18514 	    */
18515 	    type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18516 	}
18517 	/*
18518 	* Compute the "content type".
18519 	*/
18520 	if (WXS_IS_RESTRICTION(type)) {
18521 	    /*
18522 	    * SPEC (3.1) "If <restriction>..."
18523 	    * (3.1.1) + (3.1.2) */
18524 	    if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
18525 		if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18526 		    type->contentType = XML_SCHEMA_CONTENT_MIXED;
18527 	    }
18528 	} else {
18529 	    /*
18530 	    * SPEC (3.2) "If <extension>..."
18531 	    */
18532 	    if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18533 		/*
18534 		* SPEC (3.2.1)
18535 		* "If the `effective content` is empty, then the
18536 		*  {content type} of the [...] base ..."
18537 		*/
18538 		type->contentType = baseType->contentType;
18539 		type->subtypes = baseType->subtypes;
18540 		/*
18541 		* Fixes bug #347316:
18542 		* This is the case when the base type has a simple
18543 		* type definition as content.
18544 		*/
18545 		type->contentTypeDef = baseType->contentTypeDef;
18546 		/*
18547 		* NOTE that the effective mixed is ignored here.
18548 		*/
18549 	    } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18550 		/*
18551 		* SPEC (3.2.2)
18552 		*/
18553 		if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18554 		    type->contentType = XML_SCHEMA_CONTENT_MIXED;
18555 	    } else {
18556 		/*
18557 		* SPEC (3.2.3)
18558 		*/
18559 		if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18560 		    type->contentType = XML_SCHEMA_CONTENT_MIXED;
18561 		    /*
18562 		    * "A model group whose {compositor} is sequence and whose
18563 		    * {particles} are..."
18564 		    */
18565 		if ((WXS_TYPE_PARTICLE(type) != NULL) &&
18566 		    (WXS_TYPE_PARTICLE_TERM(type) != NULL) &&
18567 		    ((WXS_TYPE_PARTICLE_TERM(type))->type ==
18568 			XML_SCHEMA_TYPE_ALL))
18569 		{
18570 		    /*
18571 		    * SPEC cos-all-limited (1)
18572 		    */
18573 		    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18574 			/* TODO: error code */
18575 			XML_SCHEMAP_COS_ALL_LIMITED,
18576 			WXS_ITEM_NODE(type), NULL,
18577 			"The type has an 'all' model group in its "
18578 			"{content type} and thus cannot be derived from "
18579 			"a non-empty type, since this would produce a "
18580 			"'sequence' model group containing the 'all' "
18581 			"model group; 'all' model groups are not "
18582 			"allowed to appear inside other model groups",
18583 			NULL, NULL);
18584 
18585 		} else if ((WXS_TYPE_PARTICLE(baseType) != NULL) &&
18586 		    (WXS_TYPE_PARTICLE_TERM(baseType) != NULL) &&
18587 		    ((WXS_TYPE_PARTICLE_TERM(baseType))->type ==
18588 			XML_SCHEMA_TYPE_ALL))
18589 		{
18590 		    /*
18591 		    * SPEC cos-all-limited (1)
18592 		    */
18593 		    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18594 			/* TODO: error code */
18595 			XML_SCHEMAP_COS_ALL_LIMITED,
18596 			WXS_ITEM_NODE(type), NULL,
18597 			"A type cannot be derived by extension from a type "
18598 			"which has an 'all' model group in its "
18599 			"{content type}, since this would produce a "
18600 			"'sequence' model group containing the 'all' "
18601 			"model group; 'all' model groups are not "
18602 			"allowed to appear inside other model groups",
18603 			NULL, NULL);
18604 
18605 		} else if (! dummySequence) {
18606 		    xmlSchemaTreeItemPtr effectiveContent =
18607 			(xmlSchemaTreeItemPtr) type->subtypes;
18608 		    /*
18609 		    * Create the particle.
18610 		    */
18611 		    particle = xmlSchemaAddParticle(pctxt,
18612 			type->node, 1, 1);
18613 		    if (particle == NULL)
18614 			goto exit_failure;
18615 		    /*
18616 		    * Create the "sequence" model group.
18617 		    */
18618 		    particle->children = (xmlSchemaTreeItemPtr)
18619 			xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18620 			XML_SCHEMA_TYPE_SEQUENCE, type->node);
18621 		    if (particle->children == NULL)
18622 			goto exit_failure;
18623 		    WXS_TYPE_CONTENTTYPE(type) = (xmlSchemaTypePtr) particle;
18624 		    /*
18625 		    * SPEC "the particle of the {content type} of
18626 		    * the ... base ..."
18627 		    * Create a duplicate of the base type's particle
18628 		    * and assign its "term" to it.
18629 		    */
18630 		    particle->children->children =
18631 			(xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
18632 			type->node,
18633 			((xmlSchemaParticlePtr) baseType->subtypes)->minOccurs,
18634 			((xmlSchemaParticlePtr) baseType->subtypes)->maxOccurs);
18635 		    if (particle->children->children == NULL)
18636 			goto exit_failure;
18637 		    particle = (xmlSchemaParticlePtr)
18638 			particle->children->children;
18639 		    particle->children =
18640 			((xmlSchemaParticlePtr) baseType->subtypes)->children;
18641 		    /*
18642 		    * SPEC "followed by the `effective content`."
18643 		    */
18644 		    particle->next = effectiveContent;
18645 		    /*
18646 		    * This all will result in:
18647 		    * new-particle
18648 		    *   --> new-sequence(
18649 		    *         new-particle
18650 		    *           --> base-model,
18651 		    *         this-particle
18652 		    *	        --> this-model
18653 		    *	    )
18654 		    */
18655 		} else {
18656 		    /*
18657 		    * This is the case when there is already an empty
18658 		    * <sequence> with minOccurs==maxOccurs==1.
18659 		    * Just add the base types's content type.
18660 		    * NOTE that, although we miss to add an intermediate
18661 		    * <sequence>, this should produce no difference to
18662 		    * neither the regex compilation of the content model,
18663 		    * nor to the complex type constraints.
18664 		    */
18665 		    particle->children->children =
18666 			(xmlSchemaTreeItemPtr) baseType->subtypes;
18667 		}
18668 	    }
18669 	}
18670     }
18671     /*
18672     * Now fixup attribute uses:
18673     *   - expand attr. group references
18674     *     - intersect attribute wildcards
18675     *   - inherit attribute uses of the base type
18676     *   - inherit or union attr. wildcards if extending
18677     *   - apply attr. use prohibitions if restricting
18678     */
18679     res = xmlSchemaFixupTypeAttributeUses(pctxt, type);
18680     HFAILURE HERROR
18681     /*
18682     * Apply the complex type component constraints; this will not
18683     * check attributes, since this is done in
18684     * xmlSchemaFixupTypeAttributeUses().
18685     */
18686     res = xmlSchemaCheckCTComponent(pctxt, type);
18687     HFAILURE HERROR
18688 
18689 #ifdef DEBUG_TYPE
18690     xmlSchemaDebugFixedType(pctxt, type);
18691 #endif
18692     if (olderrs != pctxt->nberrors)
18693 	return(pctxt->err);
18694     else
18695 	return(0);
18696 
18697 exit_error:
18698     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18699 #ifdef DEBUG_TYPE
18700     xmlSchemaDebugFixedType(pctxt, type);
18701 #endif
18702     return(pctxt->err);
18703 
18704 exit_failure:
18705     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18706 #ifdef DEBUG_TYPE
18707     xmlSchemaDebugFixedType(pctxt, type);
18708 #endif
18709     return(-1);
18710 }
18711 
18712 
18713 /**
18714  * xmlSchemaTypeFixup:
18715  * @typeDecl:  the schema type definition
18716  * @ctxt:  the schema parser context
18717  *
18718  * Fixes the content model of the type.
18719  * URGENT TODO: We need an int result!
18720  */
18721 static int
xmlSchemaTypeFixup(xmlSchemaTypePtr type,xmlSchemaAbstractCtxtPtr actxt)18722 xmlSchemaTypeFixup(xmlSchemaTypePtr type,
18723                    xmlSchemaAbstractCtxtPtr actxt)
18724 {
18725     if (type == NULL)
18726         return(0);
18727     if (actxt->type != XML_SCHEMA_CTXT_PARSER) {
18728 	AERROR_INT("xmlSchemaTypeFixup",
18729 	    "this function needs a parser context");
18730 	return(-1);
18731     }
18732     if (! WXS_IS_TYPE_NOT_FIXED(type))
18733 	return(0);
18734     if (type->type == XML_SCHEMA_TYPE_COMPLEX)
18735 	return(xmlSchemaFixupComplexType(PCTXT_CAST actxt, type));
18736     else if (type->type == XML_SCHEMA_TYPE_SIMPLE)
18737 	return(xmlSchemaFixupSimpleTypeStageTwo(PCTXT_CAST actxt, type));
18738     return(0);
18739 }
18740 
18741 /**
18742  * xmlSchemaCheckFacet:
18743  * @facet:  the facet
18744  * @typeDecl:  the schema type definition
18745  * @pctxt:  the schema parser context or NULL
18746  * @name: the optional name of the type
18747  *
18748  * Checks and computes the values of facets.
18749  *
18750  * Returns 0 if valid, a positive error code if not valid and
18751  *         -1 in case of an internal or API error.
18752  */
18753 int
xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,xmlSchemaTypePtr typeDecl,xmlSchemaParserCtxtPtr pctxt,const xmlChar * name ATTRIBUTE_UNUSED)18754 xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
18755                     xmlSchemaTypePtr typeDecl,
18756                     xmlSchemaParserCtxtPtr pctxt,
18757 		    const xmlChar * name ATTRIBUTE_UNUSED)
18758 {
18759     int ret = 0, ctxtGiven;
18760 
18761     if ((facet == NULL) || (typeDecl == NULL))
18762         return(-1);
18763     /*
18764     * TODO: will the parser context be given if used from
18765     * the relaxNG module?
18766     */
18767     if (pctxt == NULL)
18768 	ctxtGiven = 0;
18769     else
18770 	ctxtGiven = 1;
18771 
18772     switch (facet->type) {
18773         case XML_SCHEMA_FACET_MININCLUSIVE:
18774         case XML_SCHEMA_FACET_MINEXCLUSIVE:
18775         case XML_SCHEMA_FACET_MAXINCLUSIVE:
18776         case XML_SCHEMA_FACET_MAXEXCLUSIVE:
18777 	case XML_SCHEMA_FACET_ENUMERATION: {
18778                 /*
18779                  * Okay we need to validate the value
18780                  * at that point.
18781                  */
18782 		xmlSchemaTypePtr base;
18783 
18784 		/* 4.3.5.5 Constraints on enumeration Schema Components
18785 		* Schema Component Constraint: enumeration valid restriction
18786 		* It is an `error` if any member of {value} is not in the
18787 		* `value space` of {base type definition}.
18788 		*
18789 		* minInclusive, maxInclusive, minExclusive, maxExclusive:
18790 		* The value `must` be in the
18791 		* `value space` of the `base type`.
18792 		*/
18793 		/*
18794 		* This function is intended to deliver a compiled value
18795 		* on the facet. In this implementation of XML Schemata the
18796 		* type holding a facet, won't be a built-in type.
18797 		* Thus to ensure that other API
18798 		* calls (relaxng) do work, if the given type is a built-in
18799 		* type, we will assume that the given built-in type *is
18800 		* already* the base type.
18801 		*/
18802 		if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
18803 		    base = typeDecl->baseType;
18804 		    if (base == NULL) {
18805 			PERROR_INT("xmlSchemaCheckFacet",
18806 			    "a type user derived type has no base type");
18807 			return (-1);
18808 		    }
18809 		} else
18810 		    base = typeDecl;
18811 
18812 		if (! ctxtGiven) {
18813 		    /*
18814 		    * A context is needed if called from RelaxNG.
18815 		    */
18816 		    pctxt = xmlSchemaNewParserCtxt("*");
18817 		    if (pctxt == NULL)
18818 			return (-1);
18819 		}
18820 		/*
18821 		* NOTE: This call does not check the content nodes,
18822 		* since they are not available:
18823 		* facet->node is just the node holding the facet
18824 		* definition, *not* the attribute holding the *value*
18825 		* of the facet.
18826 		*/
18827 		ret = xmlSchemaVCheckCVCSimpleType(
18828 		    ACTXT_CAST pctxt, facet->node, base,
18829 		    facet->value, &(facet->val), 1, 1, 0);
18830                 if (ret != 0) {
18831 		    if (ret < 0) {
18832 			/* No error message for RelaxNG. */
18833 			if (ctxtGiven) {
18834 			    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18835 				XML_SCHEMAP_INTERNAL, facet->node, NULL,
18836 				"Internal error: xmlSchemaCheckFacet, "
18837 				"failed to validate the value '%s' of the "
18838 				"facet '%s' against the base type",
18839 				facet->value, xmlSchemaFacetTypeToString(facet->type));
18840 			}
18841 			goto internal_error;
18842 		    }
18843 		    ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18844 		    /* No error message for RelaxNG. */
18845 		    if (ctxtGiven) {
18846 			xmlChar *str = NULL;
18847 
18848 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
18849 			    ret, facet->node, WXS_BASIC_CAST facet,
18850 			    "The value '%s' of the facet does not validate "
18851 			    "against the base type '%s'",
18852 			    facet->value,
18853 			    xmlSchemaFormatQName(&str,
18854 				base->targetNamespace, base->name));
18855 			FREE_AND_NULL(str);
18856 		    }
18857 		    goto exit;
18858                 } else if (facet->val == NULL) {
18859 		    if (ctxtGiven) {
18860 			PERROR_INT("xmlSchemaCheckFacet",
18861 			    "value was not computed");
18862 		    }
18863 		    TODO
18864 		}
18865                 break;
18866             }
18867         case XML_SCHEMA_FACET_PATTERN:
18868             facet->regexp = xmlRegexpCompile(facet->value);
18869             if (facet->regexp == NULL) {
18870 		ret = XML_SCHEMAP_REGEXP_INVALID;
18871 		/* No error message for RelaxNG. */
18872 		if (ctxtGiven) {
18873 		    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18874 			ret, facet->node, WXS_BASIC_CAST typeDecl,
18875 			"The value '%s' of the facet 'pattern' is not a "
18876 			"valid regular expression",
18877 			facet->value, NULL);
18878 		}
18879             }
18880             break;
18881         case XML_SCHEMA_FACET_TOTALDIGITS:
18882         case XML_SCHEMA_FACET_FRACTIONDIGITS:
18883         case XML_SCHEMA_FACET_LENGTH:
18884         case XML_SCHEMA_FACET_MAXLENGTH:
18885         case XML_SCHEMA_FACET_MINLENGTH:
18886 
18887 	    if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
18888 		ret = xmlSchemaValidatePredefinedType(
18889 		    xmlSchemaGetBuiltInType(XML_SCHEMAS_PINTEGER),
18890 		    facet->value, &(facet->val));
18891 	    } else {
18892 		ret = xmlSchemaValidatePredefinedType(
18893 		    xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
18894 		    facet->value, &(facet->val));
18895 	    }
18896 	    if (ret != 0) {
18897 		if (ret < 0) {
18898 		    /* No error message for RelaxNG. */
18899 		    if (ctxtGiven) {
18900 			PERROR_INT("xmlSchemaCheckFacet",
18901 			    "validating facet value");
18902 		    }
18903 		    goto internal_error;
18904 		}
18905 		ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18906 		/* No error message for RelaxNG. */
18907 		if (ctxtGiven) {
18908 		    /* error code */
18909 		    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
18910 			ret, facet->node, WXS_BASIC_CAST typeDecl,
18911 			"The value '%s' of the facet '%s' is not a valid '%s'",
18912 			facet->value,
18913 			xmlSchemaFacetTypeToString(facet->type),
18914 			(facet->type != XML_SCHEMA_FACET_TOTALDIGITS) ?
18915 			    BAD_CAST "nonNegativeInteger" :
18916 			    BAD_CAST "positiveInteger",
18917 			NULL);
18918 		}
18919 	    }
18920 	    break;
18921 
18922         case XML_SCHEMA_FACET_WHITESPACE:{
18923                 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
18924                     facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
18925                 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
18926                     facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
18927                 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
18928                     facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
18929                 } else {
18930 		    ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18931                     /* No error message for RelaxNG. */
18932 		    if (ctxtGiven) {
18933 			/* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
18934 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
18935 			    ret, facet->node, WXS_BASIC_CAST typeDecl,
18936 			    "The value '%s' of the facet 'whitespace' is not "
18937 			    "valid", facet->value, NULL);
18938                     }
18939                 }
18940             }
18941         default:
18942             break;
18943     }
18944 exit:
18945     if ((! ctxtGiven) && (pctxt != NULL))
18946 	xmlSchemaFreeParserCtxt(pctxt);
18947     return (ret);
18948 internal_error:
18949     if ((! ctxtGiven) && (pctxt != NULL))
18950 	xmlSchemaFreeParserCtxt(pctxt);
18951     return (-1);
18952 }
18953 
18954 /**
18955  * xmlSchemaCheckFacetValues:
18956  * @typeDecl:  the schema type definition
18957  * @ctxt:  the schema parser context
18958  *
18959  * Checks the default values types, especially for facets
18960  */
18961 static int
xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,xmlSchemaParserCtxtPtr pctxt)18962 xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
18963 			  xmlSchemaParserCtxtPtr pctxt)
18964 {
18965     int res, olderrs = pctxt->nberrors;
18966     const xmlChar *name = typeDecl->name;
18967     /*
18968     * NOTE: It is intended to use the facets list, instead
18969     * of facetSet.
18970     */
18971     if (typeDecl->facets != NULL) {
18972 	xmlSchemaFacetPtr facet = typeDecl->facets;
18973 
18974 	/*
18975 	* Temporarily assign the "schema" to the validation context
18976 	* of the parser context. This is needed for NOTATION validation.
18977 	*/
18978 	if (pctxt->vctxt == NULL) {
18979 	    if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1)
18980 		return(-1);
18981 	}
18982 	pctxt->vctxt->schema = pctxt->schema;
18983 	while (facet != NULL) {
18984 	    res = xmlSchemaCheckFacet(facet, typeDecl, pctxt, name);
18985 	    HFAILURE
18986 	    facet = facet->next;
18987 	}
18988 	pctxt->vctxt->schema = NULL;
18989     }
18990     if (olderrs != pctxt->nberrors)
18991 	return(pctxt->err);
18992     return(0);
18993 exit_failure:
18994     return(-1);
18995 }
18996 
18997 /**
18998  * xmlSchemaGetCircModelGrDefRef:
18999  * @ctxtMGroup: the searched model group
19000  * @selfMGroup: the second searched model group
19001  * @particle: the first particle
19002  *
19003  * This one is intended to be used by
19004  * xmlSchemaCheckGroupDefCircular only.
19005  *
19006  * Returns the particle with the circular model group definition reference,
19007  * otherwise NULL.
19008  */
19009 static xmlSchemaTreeItemPtr
xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,xmlSchemaTreeItemPtr particle)19010 xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
19011 			      xmlSchemaTreeItemPtr particle)
19012 {
19013     xmlSchemaTreeItemPtr circ = NULL;
19014     xmlSchemaTreeItemPtr term;
19015     xmlSchemaModelGroupDefPtr gdef;
19016 
19017     for (; particle != NULL; particle = particle->next) {
19018 	term = particle->children;
19019 	if (term == NULL)
19020 	    continue;
19021 	switch (term->type) {
19022 	    case XML_SCHEMA_TYPE_GROUP:
19023 		gdef = (xmlSchemaModelGroupDefPtr) term;
19024 		if (gdef == groupDef)
19025 		    return (particle);
19026 		/*
19027 		* Mark this model group definition to avoid infinite
19028 		* recursion on circular references not yet examined.
19029 		*/
19030 		if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
19031 		    continue;
19032 		if (gdef->children != NULL) {
19033 		    gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
19034 		    circ = xmlSchemaGetCircModelGrDefRef(groupDef,
19035 			gdef->children->children);
19036 		    gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
19037 		    if (circ != NULL)
19038 			return (circ);
19039 		}
19040 		break;
19041 	    case XML_SCHEMA_TYPE_SEQUENCE:
19042 	    case XML_SCHEMA_TYPE_CHOICE:
19043 	    case XML_SCHEMA_TYPE_ALL:
19044 		circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
19045 		if (circ != NULL)
19046 		    return (circ);
19047 		break;
19048 	    default:
19049 		break;
19050 	}
19051     }
19052     return (NULL);
19053 }
19054 
19055 /**
19056  * xmlSchemaCheckGroupDefCircular:
19057  * @item:  the model group definition
19058  * @ctxt:  the parser context
19059  * @name:  the name
19060  *
19061  * Checks for circular references to model group definitions.
19062  */
19063 static void
xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,xmlSchemaParserCtxtPtr ctxt)19064 xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
19065 			       xmlSchemaParserCtxtPtr ctxt)
19066 {
19067     /*
19068     * Schema Component Constraint: Model Group Correct
19069     * 2 Circular groups are disallowed. That is, within the {particles}
19070     * of a group there must not be at any depth a particle whose {term}
19071     * is the group itself.
19072     */
19073     if ((item == NULL) ||
19074 	(item->type != XML_SCHEMA_TYPE_GROUP) ||
19075 	(item->children == NULL))
19076 	return;
19077     {
19078 	xmlSchemaTreeItemPtr circ;
19079 
19080 	circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
19081 	if (circ != NULL) {
19082 	    xmlChar *str = NULL;
19083 	    /*
19084 	    * TODO: The error report is not adequate: this constraint
19085 	    * is defined for model groups but not definitions, but since
19086 	    * there cannot be any circular model groups without a model group
19087 	    * definition (if not using a construction API), we check those
19088 	    * definitions only.
19089 	    */
19090 	    xmlSchemaPCustomErr(ctxt,
19091 		XML_SCHEMAP_MG_PROPS_CORRECT_2,
19092 		NULL, WXS_ITEM_NODE(circ),
19093 		"Circular reference to the model group definition '%s' "
19094 		"defined", xmlSchemaFormatQName(&str,
19095 		    item->targetNamespace, item->name));
19096 	    FREE_AND_NULL(str)
19097 	    /*
19098 	    * NOTE: We will cut the reference to avoid further
19099 	    * confusion of the processor. This is a fatal error.
19100 	    */
19101 	    circ->children = NULL;
19102 	}
19103     }
19104 }
19105 
19106 /**
19107  * xmlSchemaModelGroupToModelGroupDefFixup:
19108  * @ctxt:  the parser context
19109  * @mg:  the model group
19110  *
19111  * Assigns the model group of model group definitions to the "term"
19112  * of the referencing particle.
19113  * In xmlSchemaResolveModelGroupParticleReferences the model group
19114  * definitions were assigned to the "term", since needed for the
19115  * circularity check.
19116  *
19117  * Schema Component Constraint:
19118  *     All Group Limited (cos-all-limited) (1.2)
19119  */
19120 static void
xmlSchemaModelGroupToModelGroupDefFixup(xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,xmlSchemaModelGroupPtr mg)19121 xmlSchemaModelGroupToModelGroupDefFixup(
19122     xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
19123     xmlSchemaModelGroupPtr mg)
19124 {
19125     xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
19126 
19127     while (particle != NULL) {
19128 	if ((WXS_PARTICLE_TERM(particle) == NULL) ||
19129 	    ((WXS_PARTICLE_TERM(particle))->type !=
19130 		XML_SCHEMA_TYPE_GROUP))
19131 	{
19132 	    particle = WXS_PTC_CAST particle->next;
19133 	    continue;
19134 	}
19135 	if (WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle)) == NULL) {
19136 	    /*
19137 	    * TODO: Remove the particle.
19138 	    */
19139 	    WXS_PARTICLE_TERM(particle) = NULL;
19140 	    particle = WXS_PTC_CAST particle->next;
19141 	    continue;
19142 	}
19143 	/*
19144 	* Assign the model group to the {term} of the particle.
19145 	*/
19146 	WXS_PARTICLE_TERM(particle) =
19147 	    WXS_TREE_CAST WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle));
19148 
19149 	particle = WXS_PTC_CAST particle->next;
19150     }
19151 }
19152 
19153 /**
19154  * xmlSchemaCheckAttrGroupCircularRecur:
19155  * @ctxtGr: the searched attribute group
19156  * @attr: the current attribute list to be processed
19157  *
19158  * This one is intended to be used by
19159  * xmlSchemaCheckAttrGroupCircular only.
19160  *
19161  * Returns the circular attribute group reference, otherwise NULL.
19162  */
19163 static xmlSchemaQNameRefPtr
xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,xmlSchemaItemListPtr list)19164 xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,
19165 				     xmlSchemaItemListPtr list)
19166 {
19167     xmlSchemaAttributeGroupPtr gr;
19168     xmlSchemaQNameRefPtr ref, circ;
19169     int i;
19170     /*
19171     * We will search for an attribute group reference which
19172     * references the context attribute group.
19173     */
19174     for (i = 0; i < list->nbItems; i++) {
19175 	ref = list->items[i];
19176 	if ((ref->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19177 	    (ref->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
19178 	    (ref->item != NULL))
19179 	{
19180 	    gr = WXS_ATTR_GROUP_CAST ref->item;
19181 	    if (gr == ctxtGr)
19182 		return(ref);
19183 	    if (gr->flags & XML_SCHEMAS_ATTRGROUP_MARKED)
19184 		continue;
19185 	    /*
19186 	    * Mark as visited to avoid infinite recursion on
19187 	    * circular references not yet examined.
19188 	    */
19189 	    if ((gr->attrUses) &&
19190 		(gr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS))
19191 	    {
19192 		gr->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
19193 		circ = xmlSchemaCheckAttrGroupCircularRecur(ctxtGr,
19194 		    (xmlSchemaItemListPtr) gr->attrUses);
19195 		gr->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
19196 		if (circ != NULL)
19197 		    return (circ);
19198 	    }
19199 
19200 	}
19201     }
19202     return (NULL);
19203 }
19204 
19205 /**
19206  * xmlSchemaCheckAttrGroupCircular:
19207  * attrGr:  the attribute group definition
19208  * @ctxt:  the parser context
19209  * @name:  the name
19210  *
19211  * Checks for circular references of attribute groups.
19212  */
19213 static int
xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,xmlSchemaParserCtxtPtr ctxt)19214 xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
19215 				xmlSchemaParserCtxtPtr ctxt)
19216 {
19217     /*
19218     * Schema Representation Constraint:
19219     * Attribute Group Definition Representation OK
19220     * 3 Circular group reference is disallowed outside <redefine>.
19221     * That is, unless this element information item's parent is
19222     * <redefine>, then among the [children], if any, there must
19223     * not be an <attributeGroup> with ref [attribute] which resolves
19224     * to the component corresponding to this <attributeGroup>. Indirect
19225     * circularity is also ruled out. That is, when QName resolution
19226     * (Schema Document) ($3.15.3) is applied to a `QName` arising from
19227     * any <attributeGroup>s with a ref [attribute] among the [children],
19228     * it must not be the case that a `QName` is encountered at any depth
19229     * which resolves to the component corresponding to this <attributeGroup>.
19230     */
19231     if (attrGr->attrUses == NULL)
19232 	return(0);
19233     else if ((attrGr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS) == 0)
19234 	return(0);
19235     else {
19236 	xmlSchemaQNameRefPtr circ;
19237 
19238 	circ = xmlSchemaCheckAttrGroupCircularRecur(attrGr,
19239 	    (xmlSchemaItemListPtr) attrGr->attrUses);
19240 	if (circ != NULL) {
19241 	    xmlChar *str = NULL;
19242 	    /*
19243 	    * TODO: Report the referenced attr group as QName.
19244 	    */
19245 	    xmlSchemaPCustomErr(ctxt,
19246 		XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
19247 		NULL, WXS_ITEM_NODE(WXS_BASIC_CAST circ),
19248 		"Circular reference to the attribute group '%s' "
19249 		"defined", xmlSchemaGetComponentQName(&str, attrGr));
19250 	    FREE_AND_NULL(str);
19251 	    /*
19252 	    * NOTE: We will cut the reference to avoid further
19253 	    * confusion of the processor.
19254 	    * BADSPEC TODO: The spec should define how to process in this case.
19255 	    */
19256 	    circ->item = NULL;
19257 	    return(ctxt->err);
19258 	}
19259     }
19260     return(0);
19261 }
19262 
19263 static int
19264 xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19265 				  xmlSchemaAttributeGroupPtr attrGr);
19266 
19267 /**
19268  * xmlSchemaExpandAttributeGroupRefs:
19269  * @pctxt: the parser context
19270  * @node: the node of the component holding the attribute uses
19271  * @completeWild: the intersected wildcard to be returned
19272  * @list: the attribute uses
19273  *
19274  * Substitutes contained attribute group references
19275  * for their attribute uses. Wildcards are intersected.
19276  * Attribute use prohibitions are removed from the list
19277  * and returned via the @prohibs list.
19278  * Pointlessness of attr. prohibs, if a matching attr. decl
19279  * is existent a well, are checked.
19280  */
19281 static int
xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBasicItemPtr item,xmlSchemaWildcardPtr * completeWild,xmlSchemaItemListPtr list,xmlSchemaItemListPtr prohibs)19282 xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
19283 				  xmlSchemaBasicItemPtr item,
19284 				  xmlSchemaWildcardPtr *completeWild,
19285 				  xmlSchemaItemListPtr list,
19286 				  xmlSchemaItemListPtr prohibs)
19287 {
19288     xmlSchemaAttributeGroupPtr gr;
19289     xmlSchemaAttributeUsePtr use;
19290     xmlSchemaItemListPtr sublist;
19291     int i, j;
19292     int created = (*completeWild == NULL) ? 0 : 1;
19293 
19294     if (prohibs)
19295 	prohibs->nbItems = 0;
19296 
19297     for (i = 0; i < list->nbItems; i++) {
19298 	use = list->items[i];
19299 
19300 	if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
19301 	    if (prohibs == NULL) {
19302 		PERROR_INT("xmlSchemaExpandAttributeGroupRefs",
19303 		    "unexpected attr prohibition found");
19304 		return(-1);
19305 	    }
19306 	    /*
19307 	    * Remove from attribute uses.
19308 	    */
19309 	    if (xmlSchemaItemListRemove(list, i) == -1)
19310 		return(-1);
19311 	    i--;
19312 	    /*
19313 	    * Note that duplicate prohibitions were already
19314 	    * handled at parsing time.
19315 	    */
19316 	    /*
19317 	    * Add to list of prohibitions.
19318 	    */
19319 	    xmlSchemaItemListAddSize(prohibs, 2, use);
19320 	    continue;
19321 	}
19322 	if ((use->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19323 	    ((WXS_QNAME_CAST use)->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP))
19324 	{
19325 	    if ((WXS_QNAME_CAST use)->item == NULL)
19326 		return(-1);
19327 	    gr = WXS_ATTR_GROUP_CAST (WXS_QNAME_CAST use)->item;
19328 	    /*
19329 	    * Expand the referenced attr. group.
19330 	    * TODO: remove this, this is done in a previous step, so
19331 	    * already done here.
19332 	    */
19333 	    if ((gr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
19334 		if (xmlSchemaAttributeGroupExpandRefs(pctxt, gr) == -1)
19335 		    return(-1);
19336 	    }
19337 	    /*
19338 	    * Build the 'complete' wildcard; i.e. intersect multiple
19339 	    * wildcards.
19340 	    */
19341 	    if (gr->attributeWildcard != NULL) {
19342 		if (*completeWild == NULL) {
19343 		    *completeWild = gr->attributeWildcard;
19344 		} else {
19345 		    if (! created) {
19346 			xmlSchemaWildcardPtr tmpWild;
19347 
19348 			 /*
19349 			* Copy the first encountered wildcard as context,
19350 			* except for the annotation.
19351 			*
19352 			* Although the complete wildcard might not correspond
19353 			* to any node in the schema, we will anchor it on
19354 			* the node of the owner component.
19355 			*/
19356 			tmpWild =  xmlSchemaAddWildcard(pctxt, pctxt->schema,
19357 			    XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
19358 			    WXS_ITEM_NODE(item));
19359 			if (tmpWild == NULL)
19360 			    return(-1);
19361 			if (xmlSchemaCloneWildcardNsConstraints(pctxt,
19362 			    tmpWild, *completeWild) == -1)
19363 			    return (-1);
19364 			tmpWild->processContents = (*completeWild)->processContents;
19365 			*completeWild = tmpWild;
19366 			created = 1;
19367 		    }
19368 
19369 		    if (xmlSchemaIntersectWildcards(pctxt, *completeWild,
19370 			gr->attributeWildcard) == -1)
19371 			return(-1);
19372 		}
19373 	    }
19374 	    /*
19375 	    * Just remove the reference if the referenced group does not
19376 	    * contain any attribute uses.
19377 	    */
19378 	    sublist = ((xmlSchemaItemListPtr) gr->attrUses);
19379 	    if ((sublist == NULL) || sublist->nbItems == 0) {
19380 		if (xmlSchemaItemListRemove(list, i) == -1)
19381 		    return(-1);
19382 		i--;
19383 		continue;
19384 	    }
19385 	    /*
19386 	    * Add the attribute uses.
19387 	    */
19388 	    list->items[i] = sublist->items[0];
19389 	    if (sublist->nbItems != 1) {
19390 		for (j = 1; j < sublist->nbItems; j++) {
19391 		    i++;
19392 		    if (xmlSchemaItemListInsert(list,
19393 			    sublist->items[j], i) == -1)
19394 			return(-1);
19395 		}
19396 	    }
19397 	}
19398 
19399     }
19400     /*
19401     * Handle pointless prohibitions of declared attributes.
19402     */
19403     if (prohibs && (prohibs->nbItems != 0) && (list->nbItems != 0)) {
19404 	xmlSchemaAttributeUseProhibPtr prohib;
19405 
19406 	for (i = prohibs->nbItems -1; i >= 0; i--) {
19407 	    prohib = prohibs->items[i];
19408 	    for (j = 0; j < list->nbItems; j++) {
19409 		use = list->items[j];
19410 
19411 		if ((prohib->name == WXS_ATTRUSE_DECL_NAME(use)) &&
19412 		    (prohib->targetNamespace == WXS_ATTRUSE_DECL_TNS(use)))
19413 		{
19414 		    xmlChar *str = NULL;
19415 
19416 		    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
19417 			XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
19418 			prohib->node, NULL,
19419 			"Skipping pointless attribute use prohibition "
19420 			"'%s', since a corresponding attribute use "
19421 			"exists already in the type definition",
19422 			xmlSchemaFormatQName(&str,
19423 			    prohib->targetNamespace, prohib->name),
19424 			NULL, NULL);
19425 		    FREE_AND_NULL(str);
19426 		    /*
19427 		    * Remove the prohibition.
19428 		    */
19429 		    if (xmlSchemaItemListRemove(prohibs, i) == -1)
19430 			return(-1);
19431 		    break;
19432 		}
19433 	    }
19434 	}
19435     }
19436     return(0);
19437 }
19438 
19439 /**
19440  * xmlSchemaAttributeGroupExpandRefs:
19441  * @pctxt:  the parser context
19442  * @attrGr:  the attribute group definition
19443  *
19444  * Computation of:
19445  * {attribute uses} property
19446  * {attribute wildcard} property
19447  *
19448  * Substitutes contained attribute group references
19449  * for their attribute uses. Wildcards are intersected.
19450  */
19451 static int
xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,xmlSchemaAttributeGroupPtr attrGr)19452 xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19453 				  xmlSchemaAttributeGroupPtr attrGr)
19454 {
19455     if ((attrGr->attrUses == NULL) ||
19456 	(attrGr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED))
19457 	return(0);
19458 
19459     attrGr->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
19460     if (xmlSchemaExpandAttributeGroupRefs(pctxt, WXS_BASIC_CAST attrGr,
19461 	&(attrGr->attributeWildcard), attrGr->attrUses, NULL) == -1)
19462 	return(-1);
19463     return(0);
19464 }
19465 
19466 /**
19467  * xmlSchemaAttributeGroupExpandRefs:
19468  * @pctxt:  the parser context
19469  * @attrGr:  the attribute group definition
19470  *
19471  * Substitutes contained attribute group references
19472  * for their attribute uses. Wildcards are intersected.
19473  *
19474  * Schema Component Constraint:
19475  *    Attribute Group Definition Properties Correct (ag-props-correct)
19476  */
19477 static int
xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,xmlSchemaAttributeGroupPtr attrGr)19478 xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19479 				  xmlSchemaAttributeGroupPtr attrGr)
19480 {
19481     /*
19482     * SPEC ag-props-correct
19483     * (1) "The values of the properties of an attribute group definition
19484     * must be as described in the property tableau in The Attribute
19485     * Group Definition Schema Component ($3.6.1), modulo the impact of
19486     * Missing Sub-components ($5.3);"
19487     */
19488 
19489     if ((attrGr->attrUses != NULL) &&
19490 	(WXS_LIST_CAST attrGr->attrUses)->nbItems > 1)
19491     {
19492 	xmlSchemaItemListPtr uses = WXS_LIST_CAST attrGr->attrUses;
19493 	xmlSchemaAttributeUsePtr use, tmp;
19494 	int i, j, hasId = 0;
19495 
19496 	for (i = uses->nbItems -1; i >= 0; i--) {
19497 	    use = uses->items[i];
19498 	    /*
19499 	    * SPEC ag-props-correct
19500 	    * (2) "Two distinct members of the {attribute uses} must not have
19501 	    * {attribute declaration}s both of whose {name}s match and whose
19502 	    * {target namespace}s are identical."
19503 	    */
19504 	    if (i > 0) {
19505 		for (j = i -1; j >= 0; j--) {
19506 		    tmp = uses->items[j];
19507 		    if ((WXS_ATTRUSE_DECL_NAME(use) ==
19508 			WXS_ATTRUSE_DECL_NAME(tmp)) &&
19509 			(WXS_ATTRUSE_DECL_TNS(use) ==
19510 			WXS_ATTRUSE_DECL_TNS(tmp)))
19511 		    {
19512 			xmlChar *str = NULL;
19513 
19514 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
19515 			    XML_SCHEMAP_AG_PROPS_CORRECT,
19516 			    attrGr->node, WXS_BASIC_CAST attrGr,
19517 			    "Duplicate %s",
19518 			    xmlSchemaGetComponentDesignation(&str, use),
19519 			    NULL);
19520 			FREE_AND_NULL(str);
19521 			/*
19522 			* Remove the duplicate.
19523 			*/
19524 			if (xmlSchemaItemListRemove(uses, i) == -1)
19525 			    return(-1);
19526 			goto next_use;
19527 		    }
19528 		}
19529 	    }
19530 	    /*
19531 	    * SPEC ag-props-correct
19532 	    * (3) "Two distinct members of the {attribute uses} must not have
19533 	    * {attribute declaration}s both of whose {type definition}s are or
19534 	    * are derived from ID."
19535 	    * TODO: Does 'derived' include member-types of unions?
19536 	    */
19537 	    if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
19538 		if (xmlSchemaIsDerivedFromBuiltInType(
19539 		    WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
19540 		{
19541 		    if (hasId) {
19542 			xmlChar *str = NULL;
19543 
19544 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
19545 			    XML_SCHEMAP_AG_PROPS_CORRECT,
19546 			    attrGr->node, WXS_BASIC_CAST attrGr,
19547 			    "There must not exist more than one attribute "
19548 			    "declaration of type 'xs:ID' "
19549 			    "(or derived from 'xs:ID'). The %s violates this "
19550 			    "constraint",
19551 			    xmlSchemaGetComponentDesignation(&str, use),
19552 			    NULL);
19553 			FREE_AND_NULL(str);
19554 			if (xmlSchemaItemListRemove(uses, i) == -1)
19555 			    return(-1);
19556 		    }
19557 		    hasId = 1;
19558 		}
19559 	    }
19560 next_use: {}
19561 	}
19562     }
19563     return(0);
19564 }
19565 
19566 /**
19567  * xmlSchemaResolveAttrGroupReferences:
19568  * @attrgrpDecl:  the schema attribute definition
19569  * @ctxt:  the schema parser context
19570  * @name:  the attribute name
19571  *
19572  * Resolves references to attribute group definitions.
19573  */
19574 static int
xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,xmlSchemaParserCtxtPtr ctxt)19575 xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,
19576 				    xmlSchemaParserCtxtPtr ctxt)
19577 {
19578     xmlSchemaAttributeGroupPtr group;
19579 
19580     if (ref->item != NULL)
19581         return(0);
19582     group = xmlSchemaGetAttributeGroup(ctxt->schema,
19583 	ref->name,
19584 	ref->targetNamespace);
19585     if (group == NULL) {
19586 	xmlSchemaPResCompAttrErr(ctxt,
19587 	    XML_SCHEMAP_SRC_RESOLVE,
19588 	    NULL, ref->node,
19589 	    "ref", ref->name, ref->targetNamespace,
19590 	    ref->itemType, NULL);
19591 	return(ctxt->err);
19592     }
19593     ref->item = WXS_BASIC_CAST group;
19594     return(0);
19595 }
19596 
19597 /**
19598  * xmlSchemaCheckAttrPropsCorrect:
19599  * @item:  an schema attribute declaration/use
19600  * @ctxt:  a schema parser context
19601  * @name:  the name of the attribute
19602  *
19603  *
19604  * Schema Component Constraint:
19605  *    Attribute Declaration Properties Correct (a-props-correct)
19606  *
19607  * Validates the value constraints of an attribute declaration/use.
19608  * NOTE that this needs the simple type definitions to be already
19609  *   built and checked.
19610  */
19611 static int
xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,xmlSchemaAttributePtr attr)19612 xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19613 			       xmlSchemaAttributePtr attr)
19614 {
19615 
19616     /*
19617     * SPEC a-props-correct (1)
19618     * "The values of the properties of an attribute declaration must
19619     * be as described in the property tableau in The Attribute
19620     * Declaration Schema Component ($3.2.1), modulo the impact of
19621     * Missing Sub-components ($5.3)."
19622     */
19623 
19624     if (WXS_ATTR_TYPEDEF(attr) == NULL)
19625 	return(0);
19626 
19627     if (attr->defValue != NULL) {
19628 	int ret;
19629 
19630 	/*
19631 	* SPEC a-props-correct (3)
19632 	* "If the {type definition} is or is derived from ID then there
19633 	* must not be a {value constraint}."
19634 	*/
19635 	if (xmlSchemaIsDerivedFromBuiltInType(
19636 	    WXS_ATTR_TYPEDEF(attr), XML_SCHEMAS_ID))
19637 	{
19638 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
19639 		XML_SCHEMAP_A_PROPS_CORRECT_3,
19640 		NULL, WXS_BASIC_CAST attr,
19641 		"Value constraints are not allowed if the type definition "
19642 		"is or is derived from xs:ID",
19643 		NULL, NULL);
19644 	    return(pctxt->err);
19645 	}
19646 	/*
19647 	* SPEC a-props-correct (2)
19648 	* "if there is a {value constraint}, the canonical lexical
19649 	* representation of its value must be `valid` with respect
19650 	* to the {type definition} as defined in String Valid ($3.14.4)."
19651 	* TODO: Don't care about the *canonical* stuff here, this requirement
19652 	* will be removed in WXS 1.1 anyway.
19653 	*/
19654 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt,
19655 	    attr->node, WXS_ATTR_TYPEDEF(attr),
19656 	    attr->defValue, &(attr->defVal),
19657 	    1, 1, 0);
19658 	if (ret != 0) {
19659 	    if (ret < 0) {
19660 		PERROR_INT("xmlSchemaCheckAttrPropsCorrect",
19661 		    "calling xmlSchemaVCheckCVCSimpleType()");
19662 		return(-1);
19663 	    }
19664 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
19665 		XML_SCHEMAP_A_PROPS_CORRECT_2,
19666 		NULL, WXS_BASIC_CAST attr,
19667 		"The value of the value constraint is not valid",
19668 		NULL, NULL);
19669 	    return(pctxt->err);
19670 	}
19671     }
19672 
19673     return(0);
19674 }
19675 
19676 static xmlSchemaElementPtr
xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,xmlSchemaElementPtr ancestor)19677 xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
19678 				 xmlSchemaElementPtr ancestor)
19679 {
19680     xmlSchemaElementPtr ret;
19681 
19682     if (WXS_SUBST_HEAD(ancestor) == NULL)
19683 	return (NULL);
19684     if (WXS_SUBST_HEAD(ancestor) == elemDecl)
19685 	return (ancestor);
19686 
19687     if (WXS_SUBST_HEAD(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
19688 	return (NULL);
19689     WXS_SUBST_HEAD(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
19690     ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
19691 	WXS_SUBST_HEAD(ancestor));
19692     WXS_SUBST_HEAD(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
19693 
19694     return (ret);
19695 }
19696 
19697 /**
19698  * xmlSchemaCheckElemPropsCorrect:
19699  * @ctxt:  a schema parser context
19700  * @decl: the element declaration
19701  * @name:  the name of the attribute
19702  *
19703  * Schema Component Constraint:
19704  * Element Declaration Properties Correct (e-props-correct)
19705  *
19706  * STATUS:
19707  *   missing: (6)
19708  */
19709 static int
xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,xmlSchemaElementPtr elemDecl)19710 xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19711 			       xmlSchemaElementPtr elemDecl)
19712 {
19713     int ret = 0;
19714     xmlSchemaTypePtr typeDef = WXS_ELEM_TYPEDEF(elemDecl);
19715     /*
19716     * SPEC (1) "The values of the properties of an element declaration
19717     * must be as described in the property tableau in The Element
19718     * Declaration Schema Component ($3.3.1), modulo the impact of Missing
19719     * Sub-components ($5.3)."
19720     */
19721     if (WXS_SUBST_HEAD(elemDecl) != NULL) {
19722 	xmlSchemaElementPtr head = WXS_SUBST_HEAD(elemDecl), circ;
19723 
19724 	xmlSchemaCheckElementDeclComponent(head, pctxt);
19725 	/*
19726 	* SPEC (3) "If there is a non-`absent` {substitution group
19727 	* affiliation}, then {scope} must be global."
19728 	*/
19729 	if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
19730 	    xmlSchemaPCustomErr(pctxt,
19731 		XML_SCHEMAP_E_PROPS_CORRECT_3,
19732 		WXS_BASIC_CAST elemDecl, NULL,
19733 		"Only global element declarations can have a "
19734 		"substitution group affiliation", NULL);
19735 	    ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
19736 	}
19737 	/*
19738 	* TODO: SPEC (6) "Circular substitution groups are disallowed.
19739 	* That is, it must not be possible to return to an element declaration
19740 	* by repeatedly following the {substitution group affiliation}
19741 	* property."
19742 	*/
19743 	if (head == elemDecl)
19744 	    circ = head;
19745 	else if (WXS_SUBST_HEAD(head) != NULL)
19746 	    circ = xmlSchemaCheckSubstGroupCircular(head, head);
19747 	else
19748 	    circ = NULL;
19749 	if (circ != NULL) {
19750 	    xmlChar *strA = NULL, *strB = NULL;
19751 
19752 	    xmlSchemaPCustomErrExt(pctxt,
19753 		XML_SCHEMAP_E_PROPS_CORRECT_6,
19754 		WXS_BASIC_CAST circ, NULL,
19755 		"The element declaration '%s' defines a circular "
19756 		"substitution group to element declaration '%s'",
19757 		xmlSchemaGetComponentQName(&strA, circ),
19758 		xmlSchemaGetComponentQName(&strB, head),
19759 		NULL);
19760 	    FREE_AND_NULL(strA)
19761 	    FREE_AND_NULL(strB)
19762 	    ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
19763 	}
19764 	/*
19765 	* SPEC (4) "If there is a {substitution group affiliation},
19766 	* the {type definition}
19767 	* of the element declaration must be validly derived from the {type
19768 	* definition} of the {substitution group affiliation}, given the value
19769 	* of the {substitution group exclusions} of the {substitution group
19770 	* affiliation}, as defined in Type Derivation OK (Complex) ($3.4.6)
19771 	* (if the {type definition} is complex) or as defined in
19772 	* Type Derivation OK (Simple) ($3.14.6) (if the {type definition} is
19773 	* simple)."
19774 	*
19775 	* NOTE: {substitution group exclusions} means the values of the
19776 	* attribute "final".
19777 	*/
19778 
19779 	if (typeDef != WXS_ELEM_TYPEDEF(WXS_SUBST_HEAD(elemDecl))) {
19780 	    int set = 0;
19781 
19782 	    if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
19783 		set |= SUBSET_EXTENSION;
19784 	    if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
19785 		set |= SUBSET_RESTRICTION;
19786 
19787 	    if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST pctxt, typeDef,
19788 		WXS_ELEM_TYPEDEF(head), set) != 0) {
19789 		xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
19790 
19791 		ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
19792 		xmlSchemaPCustomErrExt(pctxt,
19793 		    XML_SCHEMAP_E_PROPS_CORRECT_4,
19794 		    WXS_BASIC_CAST elemDecl, NULL,
19795 		    "The type definition '%s' was "
19796 		    "either rejected by the substitution group "
19797 		    "affiliation '%s', or not validly derived from its type "
19798 		    "definition '%s'",
19799 		    xmlSchemaGetComponentQName(&strA, typeDef),
19800 		    xmlSchemaGetComponentQName(&strB, head),
19801 		    xmlSchemaGetComponentQName(&strC, WXS_ELEM_TYPEDEF(head)));
19802 		FREE_AND_NULL(strA)
19803 		FREE_AND_NULL(strB)
19804 		FREE_AND_NULL(strC)
19805 	    }
19806 	}
19807     }
19808     /*
19809     * SPEC (5) "If the {type definition} or {type definition}'s
19810     * {content type}
19811     * is or is derived from ID then there must not be a {value constraint}.
19812     * Note: The use of ID as a type definition for elements goes beyond
19813     * XML 1.0, and should be avoided if backwards compatibility is desired"
19814     */
19815     if ((elemDecl->value != NULL) &&
19816 	((WXS_IS_SIMPLE(typeDef) &&
19817 	  xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
19818 	 (WXS_IS_COMPLEX(typeDef) &&
19819 	  WXS_HAS_SIMPLE_CONTENT(typeDef) &&
19820 	  xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
19821 	    XML_SCHEMAS_ID)))) {
19822 
19823 	ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
19824 	xmlSchemaPCustomErr(pctxt,
19825 	    XML_SCHEMAP_E_PROPS_CORRECT_5,
19826 	    WXS_BASIC_CAST elemDecl, NULL,
19827 	    "The type definition (or type definition's content type) is or "
19828 	    "is derived from ID; value constraints are not allowed in "
19829 	    "conjunction with such a type definition", NULL);
19830     } else if (elemDecl->value != NULL) {
19831 	int vcret;
19832 	xmlNodePtr node = NULL;
19833 
19834 	/*
19835 	* SPEC (2) "If there is a {value constraint}, the canonical lexical
19836 	* representation of its value must be `valid` with respect to the
19837 	* {type definition} as defined in Element Default Valid (Immediate)
19838 	* ($3.3.6)."
19839 	*/
19840 	if (typeDef == NULL) {
19841 	    xmlSchemaPErr(pctxt, elemDecl->node,
19842 		XML_SCHEMAP_INTERNAL,
19843 		"Internal error: xmlSchemaCheckElemPropsCorrect, "
19844 		"type is missing... skipping validation of "
19845 		"the value constraint", NULL, NULL);
19846 	    return (-1);
19847 	}
19848 	if (elemDecl->node != NULL) {
19849 	    if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
19850 		node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19851 		    BAD_CAST "fixed");
19852 	    else
19853 		node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19854 		    BAD_CAST "default");
19855 	}
19856 	vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
19857 	    typeDef, elemDecl->value, &(elemDecl->defVal));
19858 	if (vcret != 0) {
19859 	    if (vcret < 0) {
19860 		PERROR_INT("xmlSchemaElemCheckValConstr",
19861 		    "failed to validate the value constraint of an "
19862 		    "element declaration");
19863 		return (-1);
19864 	    }
19865 	    return (vcret);
19866 	}
19867     }
19868 
19869     return (ret);
19870 }
19871 
19872 /**
19873  * xmlSchemaCheckElemSubstGroup:
19874  * @ctxt:  a schema parser context
19875  * @decl: the element declaration
19876  * @name:  the name of the attribute
19877  *
19878  * Schema Component Constraint:
19879  * Substitution Group (cos-equiv-class)
19880  *
19881  * In Libxml2 the subst. groups will be precomputed, in terms of that
19882  * a list will be built for each subst. group head, holding all direct
19883  * referents to this head.
19884  * NOTE that this function needs:
19885  *   1. circular subst. groups to be checked beforehand
19886  *   2. the declaration's type to be derived from the head's type
19887  *
19888  * STATUS:
19889  *
19890  */
19891 static void
xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,xmlSchemaElementPtr elemDecl)19892 xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
19893 			     xmlSchemaElementPtr elemDecl)
19894 {
19895     if ((WXS_SUBST_HEAD(elemDecl) == NULL) ||
19896 	/* SPEC (1) "Its {abstract} is false." */
19897 	(elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
19898 	return;
19899     {
19900 	xmlSchemaElementPtr head;
19901 	xmlSchemaTypePtr headType, type;
19902 	int set, methSet;
19903 	/*
19904 	* SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
19905 	* {disallowed substitutions} as the blocking constraint, as defined in
19906 	* Substitution Group OK (Transitive) ($3.3.6)."
19907 	*/
19908 	for (head = WXS_SUBST_HEAD(elemDecl); head != NULL;
19909 	    head = WXS_SUBST_HEAD(head)) {
19910 	    set = 0;
19911 	    methSet = 0;
19912 	    /*
19913 	    * The blocking constraints.
19914 	    */
19915 	    if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
19916 		continue;
19917 	    headType = head->subtypes;
19918 	    type = elemDecl->subtypes;
19919 	    if (headType == type)
19920 		goto add_member;
19921 	    if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
19922 		set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19923 	    if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
19924 		set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19925 	    /*
19926 	    * SPEC: Substitution Group OK (Transitive) (2.3)
19927 	    * "The set of all {derivation method}s involved in the
19928 	    * derivation of D's {type definition} from C's {type definition}
19929 	    * does not intersect with the union of the blocking constraint,
19930 	    * C's {prohibited substitutions} (if C is complex, otherwise the
19931 	    * empty set) and the {prohibited substitutions} (respectively the
19932 	    * empty set) of any intermediate {type definition}s in the
19933 	    * derivation of D's {type definition} from C's {type definition}."
19934 	    */
19935 	    /*
19936 	    * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
19937 	    * subst.head axis, the methSet does not need to be computed for
19938 	    * the full depth over and over.
19939 	    */
19940 	    /*
19941 	    * The set of all {derivation method}s involved in the derivation
19942 	    */
19943 	    while ((type != NULL) && (type != headType)) {
19944 		if ((WXS_IS_EXTENSION(type)) &&
19945 		    ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19946 		    methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19947 
19948 		if (WXS_IS_RESTRICTION(type) &&
19949 		    ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19950 		    methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19951 
19952 		type = type->baseType;
19953 	    }
19954 	    /*
19955 	    * The {prohibited substitutions} of all intermediate types +
19956 	    * the head's type.
19957 	    */
19958 	    type = elemDecl->subtypes->baseType;
19959 	    while (type != NULL) {
19960 		if (WXS_IS_COMPLEX(type)) {
19961 		    if ((type->flags &
19962 			    XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19963 			((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
19964 		    set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19965 		    if ((type->flags &
19966 			    XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19967 			((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19968 		    set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19969 		} else
19970 		    break;
19971 		if (type == headType)
19972 		    break;
19973 		type = type->baseType;
19974 	    }
19975 	    if ((set != 0) &&
19976 		(((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19977 		(methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
19978 		((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19979 		(methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
19980 		continue;
19981 	    }
19982 add_member:
19983 	    xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
19984 	    if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
19985 		head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
19986 	}
19987     }
19988 }
19989 
19990 #ifdef WXS_ELEM_DECL_CONS_ENABLED /* enable when finished */
19991 /**
19992  * xmlSchemaCheckElementDeclComponent
19993  * @pctxt: the schema parser context
19994  * @ctxtComponent: the context component (an element declaration)
19995  * @ctxtParticle: the first particle of the context component
19996  * @searchParticle: the element declaration particle to be analysed
19997  *
19998  * Schema Component Constraint: Element Declarations Consistent
19999  */
20000 static int
xmlSchemaCheckElementDeclConsistent(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBasicItemPtr ctxtComponent,xmlSchemaParticlePtr ctxtParticle,xmlSchemaParticlePtr searchParticle,xmlSchemaParticlePtr curParticle,int search)20001 xmlSchemaCheckElementDeclConsistent(xmlSchemaParserCtxtPtr pctxt,
20002 				    xmlSchemaBasicItemPtr ctxtComponent,
20003 				    xmlSchemaParticlePtr ctxtParticle,
20004 				    xmlSchemaParticlePtr searchParticle,
20005 				    xmlSchemaParticlePtr curParticle,
20006 				    int search)
20007 {
20008     return(0);
20009 
20010     int ret = 0;
20011     xmlSchemaParticlePtr cur = curParticle;
20012     if (curParticle == NULL) {
20013 	return(0);
20014     }
20015     if (WXS_PARTICLE_TERM(curParticle) == NULL) {
20016 	/*
20017 	* Just return in this case. A missing "term" of the particle
20018 	* might arise due to an invalid "term" component.
20019 	*/
20020 	return(0);
20021     }
20022     while (cur != NULL) {
20023 	switch (WXS_PARTICLE_TERM(cur)->type) {
20024 	    case XML_SCHEMA_TYPE_ANY:
20025 		break;
20026 	    case XML_SCHEMA_TYPE_ELEMENT:
20027 		if (search == 0) {
20028 		    ret = xmlSchemaCheckElementDeclConsistent(pctxt,
20029 			ctxtComponent, ctxtParticle, cur, ctxtParticle, 1);
20030 		    if (ret != 0)
20031 			return(ret);
20032 		} else {
20033 		    xmlSchemaElementPtr elem =
20034 			WXS_ELEM_CAST(WXS_PARTICLE_TERM(cur));
20035 		    /*
20036 		    * SPEC Element Declarations Consistent:
20037 		    * "If the {particles} contains, either directly,
20038 		    * indirectly (that is, within the {particles} of a
20039 		    * contained model group, recursively) or `implicitly`
20040 		    * two or more element declaration particles with
20041 		    * the same {name} and {target namespace}, then
20042 		    * all their type definitions must be the same
20043 		    * top-level definition [...]"
20044 		    */
20045 		    if (xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->name,
20046 			    WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->name) &&
20047 			xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
20048 			    WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->targetNamespace))
20049 		    {
20050 			xmlChar *strA = NULL, *strB = NULL;
20051 
20052 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
20053 			    /* TODO: error code */
20054 			    XML_SCHEMAP_COS_NONAMBIG,
20055 			    WXS_ITEM_NODE(cur), NULL,
20056 			    "In the content model of %s, there are multiple "
20057 			    "element declarations for '%s' with different "
20058 			    "type definitions",
20059 			    xmlSchemaGetComponentDesignation(&strA,
20060 				ctxtComponent),
20061 			    xmlSchemaFormatQName(&strB,
20062 				WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
20063 				WXS_PARTICLE_TERM_AS_ELEM(cur)->name));
20064 			FREE_AND_NULL(strA);
20065 			FREE_AND_NULL(strB);
20066 			return(XML_SCHEMAP_COS_NONAMBIG);
20067 		    }
20068 		}
20069 		break;
20070 	    case XML_SCHEMA_TYPE_SEQUENCE: {
20071 		break;
20072 		}
20073 	    case XML_SCHEMA_TYPE_CHOICE:{
20074 		/*
20075 		xmlSchemaTreeItemPtr sub;
20076 
20077 		sub = WXS_PARTICLE_TERM(particle)->children;  (xmlSchemaParticlePtr)
20078 		while (sub != NULL) {
20079 		    ret = xmlSchemaCheckElementDeclConsistent(pctxt, ctxtComponent,
20080 			ctxtParticle, ctxtElem);
20081 		    if (ret != 0)
20082 			return(ret);
20083 		    sub = sub->next;
20084 		}
20085 		*/
20086 		break;
20087 		}
20088 	    case XML_SCHEMA_TYPE_ALL:
20089 		break;
20090 	    case XML_SCHEMA_TYPE_GROUP:
20091 		break;
20092 	    default:
20093 		xmlSchemaInternalErr2(ACTXT_CAST pctxt,
20094 		    "xmlSchemaCheckElementDeclConsistent",
20095 		    "found unexpected term of type '%s' in content model",
20096 		    WXS_ITEM_TYPE_NAME(WXS_PARTICLE_TERM(cur)), NULL);
20097 		return(-1);
20098 	}
20099 	cur = (xmlSchemaParticlePtr) cur->next;
20100     }
20101 
20102 exit:
20103     return(ret);
20104 }
20105 #endif
20106 
20107 /**
20108  * xmlSchemaCheckElementDeclComponent
20109  * @item:  an schema element declaration/particle
20110  * @ctxt:  a schema parser context
20111  * @name:  the name of the attribute
20112  *
20113  * Validates the value constraints of an element declaration.
20114  * Adds substitution group members.
20115  */
20116 static void
xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,xmlSchemaParserCtxtPtr ctxt)20117 xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
20118 				   xmlSchemaParserCtxtPtr ctxt)
20119 {
20120     if (elemDecl == NULL)
20121 	return;
20122     if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
20123 	return;
20124     elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
20125     if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0) {
20126 	/*
20127 	* Adds substitution group members.
20128 	*/
20129 	xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
20130     }
20131 }
20132 
20133 /**
20134  * xmlSchemaResolveModelGroupParticleReferences:
20135  * @particle:  a particle component
20136  * @ctxt:  a parser context
20137  *
20138  * Resolves references of a model group's {particles} to
20139  * model group definitions and to element declarations.
20140  */
20141 static void
xmlSchemaResolveModelGroupParticleReferences(xmlSchemaParserCtxtPtr ctxt,xmlSchemaModelGroupPtr mg)20142 xmlSchemaResolveModelGroupParticleReferences(
20143     xmlSchemaParserCtxtPtr ctxt,
20144     xmlSchemaModelGroupPtr mg)
20145 {
20146     xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
20147     xmlSchemaQNameRefPtr ref;
20148     xmlSchemaBasicItemPtr refItem;
20149 
20150     /*
20151     * URGENT TODO: Test this.
20152     */
20153     while (particle != NULL) {
20154 	if ((WXS_PARTICLE_TERM(particle) == NULL) ||
20155 	    ((WXS_PARTICLE_TERM(particle))->type !=
20156 		XML_SCHEMA_EXTRA_QNAMEREF))
20157 	{
20158 	    goto next_particle;
20159 	}
20160 	ref = WXS_QNAME_CAST WXS_PARTICLE_TERM(particle);
20161 	/*
20162 	* Resolve the reference.
20163 	* NULL the {term} by default.
20164 	*/
20165 	particle->children = NULL;
20166 
20167 	refItem = xmlSchemaGetNamedComponent(ctxt->schema,
20168 	    ref->itemType, ref->name, ref->targetNamespace);
20169 	if (refItem == NULL) {
20170 	    xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
20171 		NULL, WXS_ITEM_NODE(particle), "ref", ref->name,
20172 		ref->targetNamespace, ref->itemType, NULL);
20173 	    /* TODO: remove the particle. */
20174 	    goto next_particle;
20175 	}
20176 	if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
20177 	    if (WXS_MODELGROUPDEF_MODEL(refItem) == NULL)
20178 		/* TODO: remove the particle. */
20179 		goto next_particle;
20180 	    /*
20181 	    * NOTE that we will assign the model group definition
20182 	    * itself to the "term" of the particle. This will ease
20183 	    * the check for circular model group definitions. After
20184 	    * that the "term" will be assigned the model group of the
20185 	    * model group definition.
20186 	    */
20187 	    if ((WXS_MODELGROUPDEF_MODEL(refItem))->type ==
20188 		    XML_SCHEMA_TYPE_ALL) {
20189 		/*
20190 		* SPEC cos-all-limited (1)
20191 		* SPEC cos-all-limited (1.2)
20192 		* "It appears only as the value of one or both of the
20193 		* following properties:"
20194 		* (1.1) "the {model group} property of a model group
20195 		*        definition."
20196 		* (1.2) "the {term} property of a particle [... of] the "
20197 		* {content type} of a complex type definition."
20198 		*/
20199 		xmlSchemaCustomErr(ACTXT_CAST ctxt,
20200 		    /* TODO: error code */
20201 		    XML_SCHEMAP_COS_ALL_LIMITED,
20202 		    WXS_ITEM_NODE(particle), NULL,
20203 		    "A model group definition is referenced, but "
20204 		    "it contains an 'all' model group, which "
20205 		    "cannot be contained by model groups",
20206 		    NULL, NULL);
20207 		/* TODO: remove the particle. */
20208 		goto next_particle;
20209 	    }
20210 	    particle->children = (xmlSchemaTreeItemPtr) refItem;
20211 	} else {
20212 	    /*
20213 	    * TODO: Are referenced element declarations the only
20214 	    * other components we expect here?
20215 	    */
20216 	    particle->children = (xmlSchemaTreeItemPtr) refItem;
20217 	}
20218 next_particle:
20219 	particle = WXS_PTC_CAST particle->next;
20220     }
20221 }
20222 
20223 static int
xmlSchemaAreValuesEqual(xmlSchemaValPtr x,xmlSchemaValPtr y)20224 xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
20225 		       xmlSchemaValPtr y)
20226 {
20227     xmlSchemaTypePtr tx, ty, ptx, pty;
20228     int ret;
20229 
20230     while (x != NULL) {
20231 	/* Same types. */
20232 	tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
20233 	ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
20234 	ptx = xmlSchemaGetPrimitiveType(tx);
20235 	pty = xmlSchemaGetPrimitiveType(ty);
20236 	/*
20237 	* (1) if a datatype T' is `derived` by `restriction` from an
20238 	* atomic datatype T then the `value space` of T' is a subset of
20239 	* the `value space` of T. */
20240 	/*
20241 	* (2) if datatypes T' and T'' are `derived` by `restriction`
20242 	* from a common atomic ancestor T then the `value space`s of T'
20243 	* and T'' may overlap.
20244 	*/
20245 	if (ptx != pty)
20246 	    return(0);
20247 	/*
20248 	* We assume computed values to be normalized, so do a fast
20249 	* string comparison for string based types.
20250 	*/
20251 	if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
20252 	    WXS_IS_ANY_SIMPLE_TYPE(ptx)) {
20253 	    if (! xmlStrEqual(
20254 		xmlSchemaValueGetAsString(x),
20255 		xmlSchemaValueGetAsString(y)))
20256 		return (0);
20257 	} else {
20258 	    ret = xmlSchemaCompareValuesWhtsp(
20259 		x, XML_SCHEMA_WHITESPACE_PRESERVE,
20260 		y, XML_SCHEMA_WHITESPACE_PRESERVE);
20261 	    if (ret == -2)
20262 		return(-1);
20263 	    if (ret != 0)
20264 		return(0);
20265 	}
20266 	/*
20267 	* Lists.
20268 	*/
20269 	x = xmlSchemaValueGetNext(x);
20270 	if (x != NULL) {
20271 	    y = xmlSchemaValueGetNext(y);
20272 	    if (y == NULL)
20273 		return (0);
20274 	} else if (xmlSchemaValueGetNext(y) != NULL)
20275 	    return (0);
20276 	else
20277 	    return (1);
20278     }
20279     return (0);
20280 }
20281 
20282 /**
20283  * xmlSchemaResolveAttrUseReferences:
20284  * @item:  an attribute use
20285  * @ctxt:  a parser context
20286  *
20287  * Resolves the referenced attribute declaration.
20288  */
20289 static int
xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,xmlSchemaParserCtxtPtr ctxt)20290 xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,
20291 				  xmlSchemaParserCtxtPtr ctxt)
20292 {
20293     if ((ctxt == NULL) || (ause == NULL))
20294 	return(-1);
20295     if ((ause->attrDecl == NULL) ||
20296 	(ause->attrDecl->type != XML_SCHEMA_EXTRA_QNAMEREF))
20297 	return(0);
20298 
20299     {
20300 	xmlSchemaQNameRefPtr ref = WXS_QNAME_CAST ause->attrDecl;
20301 
20302 	/*
20303 	* TODO: Evaluate, what errors could occur if the declaration is not
20304 	* found.
20305 	*/
20306 	ause->attrDecl = xmlSchemaGetAttributeDecl(ctxt->schema,
20307 	    ref->name, ref->targetNamespace);
20308         if (ause->attrDecl == NULL) {
20309 	    xmlSchemaPResCompAttrErr(ctxt,
20310 		XML_SCHEMAP_SRC_RESOLVE,
20311 		WXS_BASIC_CAST ause, ause->node,
20312 		"ref", ref->name, ref->targetNamespace,
20313 		XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20314             return(ctxt->err);;
20315         }
20316     }
20317     return(0);
20318 }
20319 
20320 /**
20321  * xmlSchemaCheckAttrUsePropsCorrect:
20322  * @ctxt:  a parser context
20323  * @use:  an attribute use
20324  *
20325  * Schema Component Constraint:
20326  * Attribute Use Correct (au-props-correct)
20327  *
20328  */
20329 static int
xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,xmlSchemaAttributeUsePtr use)20330 xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,
20331 			     xmlSchemaAttributeUsePtr use)
20332 {
20333     if ((ctxt == NULL) || (use == NULL))
20334 	return(-1);
20335     if ((use->defValue == NULL) || (WXS_ATTRUSE_DECL(use) == NULL) ||
20336 	((WXS_ATTRUSE_DECL(use))->type != XML_SCHEMA_TYPE_ATTRIBUTE))
20337 	return(0);
20338 
20339     /*
20340     * SPEC au-props-correct (1)
20341     * "The values of the properties of an attribute use must be as
20342     * described in the property tableau in The Attribute Use Schema
20343     * Component ($3.5.1), modulo the impact of Missing
20344     * Sub-components ($5.3)."
20345     */
20346 
20347     if (((WXS_ATTRUSE_DECL(use))->defValue != NULL) &&
20348 	((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMAS_ATTR_FIXED) &&
20349         ((use->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20350     {
20351 	xmlSchemaPCustomErr(ctxt,
20352 	    XML_SCHEMAP_AU_PROPS_CORRECT_2,
20353 	    WXS_BASIC_CAST use, NULL,
20354 	    "The attribute declaration has a 'fixed' value constraint "
20355 	    ", thus the attribute use must also have a 'fixed' value "
20356 	    "constraint",
20357 	    NULL);
20358 	return(ctxt->err);
20359     }
20360     /*
20361     * Compute and check the value constraint's value.
20362     */
20363     if ((use->defVal != NULL) && (WXS_ATTRUSE_TYPEDEF(use) != NULL)) {
20364 	int ret;
20365 	/*
20366 	* TODO: The spec seems to be missing a check of the
20367 	* value constraint of the attribute use. We will do it here.
20368 	*/
20369 	/*
20370 	* SPEC a-props-correct (3)
20371 	*/
20372 	if (xmlSchemaIsDerivedFromBuiltInType(
20373 	    WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
20374 	{
20375 	    xmlSchemaCustomErr(ACTXT_CAST ctxt,
20376 		XML_SCHEMAP_AU_PROPS_CORRECT,
20377 		NULL, WXS_BASIC_CAST use,
20378 		"Value constraints are not allowed if the type definition "
20379 		"is or is derived from xs:ID",
20380 		NULL, NULL);
20381 	    return(ctxt->err);
20382 	}
20383 
20384 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST ctxt,
20385 	    use->node, WXS_ATTRUSE_TYPEDEF(use),
20386 	    use->defValue, &(use->defVal),
20387 	    1, 1, 0);
20388 	if (ret != 0) {
20389 	    if (ret < 0) {
20390 		PERROR_INT2("xmlSchemaCheckAttrUsePropsCorrect",
20391 		    "calling xmlSchemaVCheckCVCSimpleType()");
20392 		return(-1);
20393 	    }
20394 	    xmlSchemaCustomErr(ACTXT_CAST ctxt,
20395 		XML_SCHEMAP_AU_PROPS_CORRECT,
20396 		NULL, WXS_BASIC_CAST use,
20397 		"The value of the value constraint is not valid",
20398 		NULL, NULL);
20399 	    return(ctxt->err);
20400 	}
20401     }
20402     /*
20403     * SPEC au-props-correct (2)
20404     * "If the {attribute declaration} has a fixed
20405     * {value constraint}, then if the attribute use itself has a
20406     * {value constraint}, it must also be fixed and its value must match
20407     * that of the {attribute declaration}'s {value constraint}."
20408     */
20409     if (((WXS_ATTRUSE_DECL(use))->defVal != NULL) &&
20410 	(((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20411     {
20412 	if (! xmlSchemaAreValuesEqual(use->defVal,
20413 		(WXS_ATTRUSE_DECL(use))->defVal))
20414 	{
20415 	    xmlSchemaPCustomErr(ctxt,
20416 		XML_SCHEMAP_AU_PROPS_CORRECT_2,
20417 		WXS_BASIC_CAST use, NULL,
20418 		"The 'fixed' value constraint of the attribute use "
20419 		"must match the attribute declaration's value "
20420 		"constraint '%s'",
20421 		(WXS_ATTRUSE_DECL(use))->defValue);
20422 	}
20423 	return(ctxt->err);
20424     }
20425     return(0);
20426 }
20427 
20428 
20429 
20430 
20431 /**
20432  * xmlSchemaResolveAttrTypeReferences:
20433  * @item:  an attribute declaration
20434  * @ctxt:  a parser context
20435  *
20436  * Resolves the referenced type definition component.
20437  */
20438 static int
xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,xmlSchemaParserCtxtPtr ctxt)20439 xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,
20440 				   xmlSchemaParserCtxtPtr ctxt)
20441 {
20442     /*
20443     * The simple type definition corresponding to the <simpleType> element
20444     * information item in the [children], if present, otherwise the simple
20445     * type definition `resolved` to by the `actual value` of the type
20446     * [attribute], if present, otherwise the `simple ur-type definition`.
20447     */
20448     if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
20449 	return(0);
20450     item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
20451     if (item->subtypes != NULL)
20452         return(0);
20453     if (item->typeName != NULL) {
20454         xmlSchemaTypePtr type;
20455 
20456 	type = xmlSchemaGetType(ctxt->schema, item->typeName,
20457 	    item->typeNs);
20458 	if ((type == NULL) || (! WXS_IS_SIMPLE(type))) {
20459 	    xmlSchemaPResCompAttrErr(ctxt,
20460 		XML_SCHEMAP_SRC_RESOLVE,
20461 		WXS_BASIC_CAST item, item->node,
20462 		"type", item->typeName, item->typeNs,
20463 		XML_SCHEMA_TYPE_SIMPLE, NULL);
20464 	    return(ctxt->err);
20465 	} else
20466 	    item->subtypes = type;
20467 
20468     } else {
20469 	/*
20470 	* The type defaults to the xs:anySimpleType.
20471 	*/
20472 	item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
20473     }
20474     return(0);
20475 }
20476 
20477 /**
20478  * xmlSchemaResolveIDCKeyReferences:
20479  * @idc:  the identity-constraint definition
20480  * @ctxt:  the schema parser context
20481  * @name:  the attribute name
20482  *
20483  * Resolve keyRef references to key/unique IDCs.
20484  * Schema Component Constraint:
20485  *   Identity-constraint Definition Properties Correct (c-props-correct)
20486  */
20487 static int
xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,xmlSchemaParserCtxtPtr pctxt)20488 xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,
20489 			  xmlSchemaParserCtxtPtr pctxt)
20490 {
20491     if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
20492         return(0);
20493     if (idc->ref->name != NULL) {
20494 	idc->ref->item = (xmlSchemaBasicItemPtr)
20495 	    xmlSchemaGetIDC(pctxt->schema, idc->ref->name,
20496 		idc->ref->targetNamespace);
20497         if (idc->ref->item == NULL) {
20498 	    /*
20499 	    * TODO: It is actually not an error to fail to resolve
20500 	    * at this stage. BUT we need to be that strict!
20501 	    */
20502 	    xmlSchemaPResCompAttrErr(pctxt,
20503 		XML_SCHEMAP_SRC_RESOLVE,
20504 		WXS_BASIC_CAST idc, idc->node,
20505 		"refer", idc->ref->name,
20506 		idc->ref->targetNamespace,
20507 		XML_SCHEMA_TYPE_IDC_KEY, NULL);
20508             return(pctxt->err);
20509 	} else if (idc->ref->item->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20510 	    /*
20511 	    * SPEC c-props-correct (1)
20512 	    */
20513 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20514 		XML_SCHEMAP_C_PROPS_CORRECT,
20515 		NULL, WXS_BASIC_CAST idc,
20516 		"The keyref references a keyref",
20517 		NULL, NULL);
20518 	    idc->ref->item = NULL;
20519 	    return(pctxt->err);
20520 	} else {
20521 	    if (idc->nbFields !=
20522 		((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
20523 		xmlChar *str = NULL;
20524 		xmlSchemaIDCPtr refer;
20525 
20526 		refer = (xmlSchemaIDCPtr) idc->ref->item;
20527 		/*
20528 		* SPEC c-props-correct(2)
20529 		* "If the {identity-constraint category} is keyref,
20530 		* the cardinality of the {fields} must equal that of
20531 		* the {fields} of the {referenced key}.
20532 		*/
20533 		xmlSchemaCustomErr(ACTXT_CAST pctxt,
20534 		    XML_SCHEMAP_C_PROPS_CORRECT,
20535 		    NULL, WXS_BASIC_CAST idc,
20536 		    "The cardinality of the keyref differs from the "
20537 		    "cardinality of the referenced key/unique '%s'",
20538 		    xmlSchemaFormatQName(&str, refer->targetNamespace,
20539 			refer->name),
20540 		    NULL);
20541 		FREE_AND_NULL(str)
20542 		return(pctxt->err);
20543 	    }
20544 	}
20545     }
20546     return(0);
20547 }
20548 
20549 static int
xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,xmlSchemaParserCtxtPtr pctxt)20550 xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,
20551 				       xmlSchemaParserCtxtPtr pctxt)
20552 {
20553     if (xmlSchemaGetAttributeDecl(pctxt->schema, prohib->name,
20554 	prohib->targetNamespace) == NULL) {
20555 
20556 	xmlSchemaPResCompAttrErr(pctxt,
20557 	    XML_SCHEMAP_SRC_RESOLVE,
20558 	    NULL, prohib->node,
20559 	    "ref", prohib->name, prohib->targetNamespace,
20560 	    XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20561 	return(XML_SCHEMAP_SRC_RESOLVE);
20562     }
20563     return(0);
20564 }
20565 
20566 #define WXS_REDEFINED_TYPE(c) \
20567 (((xmlSchemaTypePtr) item)->flags & XML_SCHEMAS_TYPE_REDEFINED)
20568 
20569 #define WXS_REDEFINED_MODEL_GROUP_DEF(c) \
20570 (((xmlSchemaModelGroupDefPtr) item)->flags & XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20571 
20572 #define WXS_REDEFINED_ATTR_GROUP(c) \
20573 (((xmlSchemaAttributeGroupPtr) item)->flags & XML_SCHEMAS_ATTRGROUP_REDEFINED)
20574 
20575 static int
xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)20576 xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)
20577 {
20578     int err = 0;
20579     xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20580     xmlSchemaBasicItemPtr prev, item;
20581     int wasRedefined;
20582 
20583     if (redef == NULL)
20584 	return(0);
20585 
20586     do {
20587 	item = redef->item;
20588 	/*
20589 	* First try to locate the redefined component in the
20590 	* schema graph starting with the redefined schema.
20591 	* NOTE: According to this schema bug entry:
20592 	*   http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005OctDec/0019.html
20593 	*   it's not clear if the referenced component needs to originate
20594 	*   from the <redefine>d schema _document_ or the schema; the latter
20595 	*   would include all imported and included sub-schemas of the
20596 	*   <redefine>d schema. Currently the latter approach is used.
20597 	*   SUPPLEMENT: It seems that the WG moves towards the latter
20598 	*   approach, so we are doing it right.
20599 	*
20600 	*/
20601 	prev = xmlSchemaFindRedefCompInGraph(
20602 	    redef->targetBucket, item->type,
20603 	    redef->refName, redef->refTargetNs);
20604 	if (prev == NULL) {
20605 	    xmlChar *str = NULL;
20606 	    xmlNodePtr node;
20607 
20608 	    /*
20609 	    * SPEC src-redefine:
20610 	    * (6.2.1) "The `actual value` of its own name attribute plus
20611 	    * target namespace must successfully `resolve` to a model
20612 	    * group definition in I."
20613 	    * (7.2.1) "The `actual value` of its own name attribute plus
20614 	    * target namespace must successfully `resolve` to an attribute
20615 	    * group definition in I."
20616 
20617 	    *
20618 	    * Note that, if we are redefining with the use of references
20619 	    * to components, the spec assumes the src-resolve to be used;
20620 	    * but this won't assure that we search only *inside* the
20621 	    * redefined schema.
20622 	    */
20623 	    if (redef->reference)
20624 		node = WXS_ITEM_NODE(redef->reference);
20625 	    else
20626 		node = WXS_ITEM_NODE(item);
20627 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20628 		/*
20629 		* TODO: error code.
20630 		* Probably XML_SCHEMAP_SRC_RESOLVE, if this is using the
20631 		* reference kind.
20632 		*/
20633 		XML_SCHEMAP_SRC_REDEFINE, node, NULL,
20634 		"The %s '%s' to be redefined could not be found in "
20635 		"the redefined schema",
20636 		WXS_ITEM_TYPE_NAME(item),
20637 		xmlSchemaFormatQName(&str, redef->refTargetNs,
20638 		    redef->refName));
20639 	    FREE_AND_NULL(str);
20640 	    err = pctxt->err;
20641 	    redef = redef->next;
20642 	    continue;
20643 	}
20644 	/*
20645 	* TODO: Obtaining and setting the redefinition state is really
20646 	* clumsy.
20647 	*/
20648 	wasRedefined = 0;
20649 	switch (item->type) {
20650 	    case XML_SCHEMA_TYPE_COMPLEX:
20651 	    case XML_SCHEMA_TYPE_SIMPLE:
20652 		if ((WXS_TYPE_CAST prev)->flags &
20653 		    XML_SCHEMAS_TYPE_REDEFINED)
20654 		{
20655 		    wasRedefined = 1;
20656 		    break;
20657 		}
20658 		/* Mark it as redefined. */
20659 		(WXS_TYPE_CAST prev)->flags |= XML_SCHEMAS_TYPE_REDEFINED;
20660 		/*
20661 		* Assign the redefined type to the
20662 		* base type of the redefining type.
20663 		* TODO: How
20664 		*/
20665 		((xmlSchemaTypePtr) item)->baseType =
20666 		    (xmlSchemaTypePtr) prev;
20667 		break;
20668 	    case XML_SCHEMA_TYPE_GROUP:
20669 		if ((WXS_MODEL_GROUPDEF_CAST prev)->flags &
20670 		    XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20671 		{
20672 		    wasRedefined = 1;
20673 		    break;
20674 		}
20675 		/* Mark it as redefined. */
20676 		(WXS_MODEL_GROUPDEF_CAST prev)->flags |=
20677 		    XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED;
20678 		if (redef->reference != NULL) {
20679 		    /*
20680 		    * Overwrite the QName-reference with the
20681 		    * referenced model group def.
20682 		    */
20683 		    (WXS_PTC_CAST redef->reference)->children =
20684 			WXS_TREE_CAST prev;
20685 		}
20686 		redef->target = prev;
20687 		break;
20688 	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20689 		if ((WXS_ATTR_GROUP_CAST prev)->flags &
20690 		    XML_SCHEMAS_ATTRGROUP_REDEFINED)
20691 		{
20692 		    wasRedefined = 1;
20693 		    break;
20694 		}
20695 		(WXS_ATTR_GROUP_CAST prev)->flags |=
20696 		    XML_SCHEMAS_ATTRGROUP_REDEFINED;
20697 		if (redef->reference != NULL) {
20698 		    /*
20699 		    * Assign the redefined attribute group to the
20700 		    * QName-reference component.
20701 		    * This is the easy case, since we will just
20702 		    * expand the redefined group.
20703 		    */
20704 		    (WXS_QNAME_CAST redef->reference)->item = prev;
20705 		    redef->target = NULL;
20706 		} else {
20707 		    /*
20708 		    * This is the complicated case: we need
20709 		    * to apply src-redefine (7.2.2) at a later
20710 		    * stage, i.e. when attribute group references
20711 		    * have been expanded and simple types have
20712 		    * been fixed.
20713 		    */
20714 		    redef->target = prev;
20715 		}
20716 		break;
20717 	    default:
20718 		PERROR_INT("xmlSchemaResolveRedefReferences",
20719 		    "Unexpected redefined component type");
20720 		return(-1);
20721 	}
20722 	if (wasRedefined) {
20723 	    xmlChar *str = NULL;
20724 	    xmlNodePtr node;
20725 
20726 	    if (redef->reference)
20727 		node = WXS_ITEM_NODE(redef->reference);
20728 	    else
20729 		node = WXS_ITEM_NODE(redef->item);
20730 
20731 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20732 		/* TODO: error code. */
20733 		XML_SCHEMAP_SRC_REDEFINE,
20734 		node, NULL,
20735 		"The referenced %s was already redefined. Multiple "
20736 		"redefinition of the same component is not supported",
20737 		xmlSchemaGetComponentDesignation(&str, prev),
20738 		NULL);
20739 	    FREE_AND_NULL(str)
20740 	    err = pctxt->err;
20741 	    redef = redef->next;
20742 	    continue;
20743 	}
20744 	redef = redef->next;
20745     } while (redef != NULL);
20746 
20747     return(err);
20748 }
20749 
20750 static int
xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)20751 xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)
20752 {
20753     int err = 0;
20754     xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20755     xmlSchemaBasicItemPtr item;
20756 
20757     if (redef == NULL)
20758 	return(0);
20759 
20760     do {
20761 	if (redef->target == NULL) {
20762 	    redef = redef->next;
20763 	    continue;
20764 	}
20765 	item = redef->item;
20766 
20767 	switch (item->type) {
20768 	    case XML_SCHEMA_TYPE_SIMPLE:
20769 	    case XML_SCHEMA_TYPE_COMPLEX:
20770 		/*
20771 		* Since the spec wants the {name} of the redefined
20772 		* type to be 'absent', we'll NULL it.
20773 		*/
20774 		(WXS_TYPE_CAST redef->target)->name = NULL;
20775 
20776 		/*
20777 		* TODO: Seems like there's nothing more to do. The normal
20778 		* inheritance mechanism is used. But not 100% sure.
20779 		*/
20780 		break;
20781 	    case XML_SCHEMA_TYPE_GROUP:
20782 		/*
20783 		* URGENT TODO:
20784 		* SPEC src-redefine:
20785 		* (6.2.2) "The {model group} of the model group definition
20786 		* which corresponds to it per XML Representation of Model
20787 		* Group Definition Schema Components ($3.7.2) must be a
20788 		* `valid restriction` of the {model group} of that model
20789 		* group definition in I, as defined in Particle Valid
20790 		* (Restriction) ($3.9.6)."
20791 		*/
20792 		break;
20793 	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20794 		/*
20795 		* SPEC src-redefine:
20796 		* (7.2.2) "The {attribute uses} and {attribute wildcard} of
20797 		* the attribute group definition which corresponds to it
20798 		* per XML Representation of Attribute Group Definition Schema
20799 		* Components ($3.6.2) must be `valid restrictions` of the
20800 		* {attribute uses} and {attribute wildcard} of that attribute
20801 		* group definition in I, as defined in clause 2, clause 3 and
20802 		* clause 4 of Derivation Valid (Restriction, Complex)
20803 		* ($3.4.6) (where references to the base type definition are
20804 		* understood as references to the attribute group definition
20805 		* in I)."
20806 		*/
20807 		err = xmlSchemaCheckDerivationOKRestriction2to4(pctxt,
20808 		    XML_SCHEMA_ACTION_REDEFINE,
20809 		    item, redef->target,
20810 		    (WXS_ATTR_GROUP_CAST item)->attrUses,
20811 		    (WXS_ATTR_GROUP_CAST redef->target)->attrUses,
20812 		    (WXS_ATTR_GROUP_CAST item)->attributeWildcard,
20813 		    (WXS_ATTR_GROUP_CAST redef->target)->attributeWildcard);
20814 		if (err == -1)
20815 		    return(-1);
20816 		break;
20817 	    default:
20818 		break;
20819 	}
20820 	redef = redef->next;
20821     } while (redef != NULL);
20822     return(0);
20823 }
20824 
20825 
20826 static int
xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBucketPtr bucket)20827 xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,
20828 		       xmlSchemaBucketPtr bucket)
20829 {
20830     xmlSchemaBasicItemPtr item;
20831     int err;
20832     xmlHashTablePtr *table;
20833     const xmlChar *name;
20834     int i;
20835 
20836 #define WXS_GET_GLOBAL_HASH(c, slot) { \
20837     if (WXS_IS_BUCKET_IMPMAIN((c)->type)) \
20838 	table = &(WXS_IMPBUCKET((c))->schema->slot); \
20839     else \
20840 	table = &(WXS_INCBUCKET((c))->ownerImport->schema->slot); }
20841 
20842     /*
20843     * Add global components to the schema's hash tables.
20844     * This is the place where duplicate components will be
20845     * detected.
20846     * TODO: I think normally we should support imports of the
20847     *   same namespace from multiple locations. We don't do currently,
20848     *   but if we do then according to:
20849     *   http://www.w3.org/Bugs/Public/show_bug.cgi?id=2224
20850     *   we would need, if imported directly, to import redefined
20851     *   components as well to be able to catch clashing components.
20852     *   (I hope I'll still know what this means after some months :-()
20853     */
20854     if (bucket == NULL)
20855 	return(-1);
20856     if (bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED)
20857 	return(0);
20858     bucket->flags |= XML_SCHEMA_BUCKET_COMPS_ADDED;
20859 
20860     for (i = 0; i < bucket->globals->nbItems; i++) {
20861 	item = bucket->globals->items[i];
20862 	table = NULL;
20863 	switch (item->type) {
20864 	    case XML_SCHEMA_TYPE_COMPLEX:
20865 	    case XML_SCHEMA_TYPE_SIMPLE:
20866 		if (WXS_REDEFINED_TYPE(item))
20867 		    continue;
20868 		name = (WXS_TYPE_CAST item)->name;
20869 		WXS_GET_GLOBAL_HASH(bucket, typeDecl)
20870 		break;
20871 	    case XML_SCHEMA_TYPE_ELEMENT:
20872 		name = (WXS_ELEM_CAST item)->name;
20873 		WXS_GET_GLOBAL_HASH(bucket, elemDecl)
20874 		break;
20875 	    case XML_SCHEMA_TYPE_ATTRIBUTE:
20876 		name = (WXS_ATTR_CAST item)->name;
20877 		WXS_GET_GLOBAL_HASH(bucket, attrDecl)
20878 		break;
20879 	    case XML_SCHEMA_TYPE_GROUP:
20880 		if (WXS_REDEFINED_MODEL_GROUP_DEF(item))
20881 		    continue;
20882 		name = (WXS_MODEL_GROUPDEF_CAST item)->name;
20883 		WXS_GET_GLOBAL_HASH(bucket, groupDecl)
20884 		break;
20885 	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20886 		if (WXS_REDEFINED_ATTR_GROUP(item))
20887 		    continue;
20888 		name = (WXS_ATTR_GROUP_CAST item)->name;
20889 		WXS_GET_GLOBAL_HASH(bucket, attrgrpDecl)
20890 		break;
20891 	    case XML_SCHEMA_TYPE_IDC_KEY:
20892 	    case XML_SCHEMA_TYPE_IDC_UNIQUE:
20893 	    case XML_SCHEMA_TYPE_IDC_KEYREF:
20894 		name = (WXS_IDC_CAST item)->name;
20895 		WXS_GET_GLOBAL_HASH(bucket, idcDef)
20896 		break;
20897 	    case XML_SCHEMA_TYPE_NOTATION:
20898 		name = ((xmlSchemaNotationPtr) item)->name;
20899 		WXS_GET_GLOBAL_HASH(bucket, notaDecl)
20900 		break;
20901 	    default:
20902 		PERROR_INT("xmlSchemaAddComponents",
20903 		    "Unexpected global component type");
20904 		continue;
20905 	}
20906 	if (*table == NULL) {
20907 	    *table = xmlHashCreateDict(10, pctxt->dict);
20908 	    if (*table == NULL) {
20909 		PERROR_INT("xmlSchemaAddComponents",
20910 		    "failed to create a component hash table");
20911 		return(-1);
20912 	    }
20913 	}
20914 	err = xmlHashAddEntry(*table, name, item);
20915 	if (err != 0) {
20916 	    xmlChar *str = NULL;
20917 
20918 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20919 		XML_SCHEMAP_REDEFINED_TYPE,
20920 		WXS_ITEM_NODE(item),
20921 		WXS_BASIC_CAST item,
20922 		"A global %s '%s' does already exist",
20923 		WXS_ITEM_TYPE_NAME(item),
20924 		xmlSchemaGetComponentQName(&str, item));
20925 	    FREE_AND_NULL(str);
20926 	}
20927     }
20928     /*
20929     * Process imported/included schemas.
20930     */
20931     if (bucket->relations != NULL) {
20932 	xmlSchemaSchemaRelationPtr rel = bucket->relations;
20933 	do {
20934 	    if ((rel->bucket != NULL) &&
20935 		((rel->bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED) == 0)) {
20936 		if (xmlSchemaAddComponents(pctxt, rel->bucket) == -1)
20937 		    return(-1);
20938 	    }
20939 	    rel = rel->next;
20940 	} while (rel != NULL);
20941     }
20942     return(0);
20943 }
20944 
20945 static int
xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBucketPtr rootBucket)20946 xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt,
20947 			 xmlSchemaBucketPtr rootBucket)
20948 {
20949     xmlSchemaConstructionCtxtPtr con = pctxt->constructor;
20950     xmlSchemaTreeItemPtr item, *items;
20951     int nbItems, i, ret = 0;
20952     xmlSchemaBucketPtr oldbucket = con->bucket;
20953     xmlSchemaElementPtr elemDecl;
20954 
20955 #define FIXHFAILURE if (pctxt->err == XML_SCHEMAP_INTERNAL) goto exit_failure;
20956 
20957     if ((con->pending == NULL) ||
20958 	(con->pending->nbItems == 0))
20959 	return(0);
20960 
20961     /*
20962     * Since xmlSchemaFixupComplexType() will create new particles
20963     * (local components), and those particle components need a bucket
20964     * on the constructor, we'll assure here that the constructor has
20965     * a bucket.
20966     * TODO: Think about storing locals _only_ on the main bucket.
20967     */
20968     if (con->bucket == NULL)
20969 	con->bucket = rootBucket;
20970 
20971     /* TODO:
20972     * SPEC (src-redefine):
20973     * (6.2) "If it has no such self-reference, then all of the
20974     * following must be true:"
20975 
20976     * (6.2.2) The {model group} of the model group definition which
20977     * corresponds to it per XML Representation of Model Group
20978     * Definition Schema Components ($3.7.2) must be a `valid
20979     * restriction` of the {model group} of that model group definition
20980     * in I, as defined in Particle Valid (Restriction) ($3.9.6)."
20981     */
20982     xmlSchemaCheckSRCRedefineFirst(pctxt);
20983 
20984     /*
20985     * Add global components to the schemata's hash tables.
20986     */
20987     xmlSchemaAddComponents(pctxt, rootBucket);
20988 
20989     pctxt->ctxtType = NULL;
20990     items = (xmlSchemaTreeItemPtr *) con->pending->items;
20991     nbItems = con->pending->nbItems;
20992     /*
20993     * Now that we have parsed *all* the schema document(s) and converted
20994     * them to schema components, we can resolve references, apply component
20995     * constraints, create the FSA from the content model, etc.
20996     */
20997     /*
20998     * Resolve references of..
20999     *
21000     * 1. element declarations:
21001     *   - the type definition
21002     *   - the substitution group affiliation
21003     * 2. simple/complex types:
21004     *   - the base type definition
21005     *   - the memberTypes of union types
21006     *   - the itemType of list types
21007     * 3. attributes declarations and attribute uses:
21008     *   - the type definition
21009     *   - if an attribute use, then the attribute declaration
21010     * 4. attribute group references:
21011     *   - the attribute group definition
21012     * 5. particles:
21013     *   - the term of the particle (e.g. a model group)
21014     * 6. IDC key-references:
21015     *   - the referenced IDC 'key' or 'unique' definition
21016     * 7. Attribute prohibitions which had a "ref" attribute.
21017     */
21018     for (i = 0; i < nbItems; i++) {
21019 	item = items[i];
21020 	switch (item->type) {
21021 	    case XML_SCHEMA_TYPE_ELEMENT:
21022 		xmlSchemaResolveElementReferences(
21023 		    (xmlSchemaElementPtr) item, pctxt);
21024 		FIXHFAILURE;
21025 		break;
21026 	    case XML_SCHEMA_TYPE_COMPLEX:
21027 	    case XML_SCHEMA_TYPE_SIMPLE:
21028 		xmlSchemaResolveTypeReferences(
21029 		    (xmlSchemaTypePtr) item, pctxt);
21030 		FIXHFAILURE;
21031 		break;
21032 	    case XML_SCHEMA_TYPE_ATTRIBUTE:
21033 		xmlSchemaResolveAttrTypeReferences(
21034 		    (xmlSchemaAttributePtr) item, pctxt);
21035 		FIXHFAILURE;
21036 		break;
21037 	    case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
21038 		xmlSchemaResolveAttrUseReferences(
21039 		    (xmlSchemaAttributeUsePtr) item, pctxt);
21040 		FIXHFAILURE;
21041 		break;
21042 	    case XML_SCHEMA_EXTRA_QNAMEREF:
21043 		if ((WXS_QNAME_CAST item)->itemType ==
21044 		    XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
21045 		{
21046 		    xmlSchemaResolveAttrGroupReferences(
21047 			WXS_QNAME_CAST item, pctxt);
21048 		}
21049 		FIXHFAILURE;
21050 		break;
21051 	    case XML_SCHEMA_TYPE_SEQUENCE:
21052 	    case XML_SCHEMA_TYPE_CHOICE:
21053 	    case XML_SCHEMA_TYPE_ALL:
21054 		xmlSchemaResolveModelGroupParticleReferences(pctxt,
21055 		    WXS_MODEL_GROUP_CAST item);
21056 		FIXHFAILURE;
21057 		break;
21058 	    case XML_SCHEMA_TYPE_IDC_KEY:
21059 	    case XML_SCHEMA_TYPE_IDC_UNIQUE:
21060 	    case XML_SCHEMA_TYPE_IDC_KEYREF:
21061 		xmlSchemaResolveIDCKeyReferences(
21062 		    (xmlSchemaIDCPtr) item, pctxt);
21063 		FIXHFAILURE;
21064 		break;
21065 	    case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
21066 		/*
21067 		* Handle attribute prohibition which had a
21068 		* "ref" attribute.
21069 		*/
21070 		xmlSchemaResolveAttrUseProhibReferences(
21071 		    WXS_ATTR_PROHIB_CAST item, pctxt);
21072 		FIXHFAILURE;
21073 		break;
21074 	    default:
21075 		break;
21076 	}
21077     }
21078     if (pctxt->nberrors != 0)
21079 	goto exit_error;
21080 
21081     /*
21082     * Now that all references are resolved we
21083     * can check for circularity of...
21084     * 1. the base axis of type definitions
21085     * 2. nested model group definitions
21086     * 3. nested attribute group definitions
21087     * TODO: check for circular substitution groups.
21088     */
21089     for (i = 0; i < nbItems; i++) {
21090 	item = items[i];
21091 	/*
21092 	* Let's better stop on the first error here.
21093 	*/
21094 	switch (item->type) {
21095 	    case XML_SCHEMA_TYPE_COMPLEX:
21096 	    case XML_SCHEMA_TYPE_SIMPLE:
21097 		xmlSchemaCheckTypeDefCircular(
21098 		    (xmlSchemaTypePtr) item, pctxt);
21099 		FIXHFAILURE;
21100 		if (pctxt->nberrors != 0)
21101 		    goto exit_error;
21102 		break;
21103 	    case XML_SCHEMA_TYPE_GROUP:
21104 		xmlSchemaCheckGroupDefCircular(
21105 		    (xmlSchemaModelGroupDefPtr) item, pctxt);
21106 		FIXHFAILURE;
21107 		if (pctxt->nberrors != 0)
21108 		    goto exit_error;
21109 		break;
21110 	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21111 		xmlSchemaCheckAttrGroupCircular(
21112 		    (xmlSchemaAttributeGroupPtr) item, pctxt);
21113 		FIXHFAILURE;
21114 		if (pctxt->nberrors != 0)
21115 		    goto exit_error;
21116 		break;
21117 	    default:
21118 		break;
21119 	}
21120     }
21121     if (pctxt->nberrors != 0)
21122 	goto exit_error;
21123     /*
21124     * Model group definition references:
21125     * Such a reference is reflected by a particle at the component
21126     * level. Until now the 'term' of such particles pointed
21127     * to the model group definition; this was done, in order to
21128     * ease circularity checks. Now we need to set the 'term' of
21129     * such particles to the model group of the model group definition.
21130     */
21131     for (i = 0; i < nbItems; i++) {
21132 	item = items[i];
21133 	switch (item->type) {
21134 	    case XML_SCHEMA_TYPE_SEQUENCE:
21135 	    case XML_SCHEMA_TYPE_CHOICE:
21136 		xmlSchemaModelGroupToModelGroupDefFixup(pctxt,
21137 		    WXS_MODEL_GROUP_CAST item);
21138 		break;
21139 	    default:
21140 		break;
21141 	}
21142     }
21143     if (pctxt->nberrors != 0)
21144 	goto exit_error;
21145     /*
21146     * Expand attribute group references of attribute group definitions.
21147     */
21148     for (i = 0; i < nbItems; i++) {
21149 	item = items[i];
21150 	switch (item->type) {
21151             case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21152 		if ((! WXS_ATTR_GROUP_EXPANDED(item)) &&
21153 		    WXS_ATTR_GROUP_HAS_REFS(item))
21154 		{
21155 		    xmlSchemaAttributeGroupExpandRefs(pctxt,
21156 			WXS_ATTR_GROUP_CAST item);
21157 		    FIXHFAILURE;
21158 		}
21159 		break;
21160 	    default:
21161 		break;
21162 	}
21163     }
21164     if (pctxt->nberrors != 0)
21165 	goto exit_error;
21166     /*
21167     * First compute the variety of simple types. This is needed as
21168     * a separate step, since otherwise we won't be able to detect
21169     * circular union types in all cases.
21170     */
21171     for (i = 0; i < nbItems; i++) {
21172 	item = items[i];
21173 	switch (item->type) {
21174             case XML_SCHEMA_TYPE_SIMPLE:
21175 		if (WXS_IS_TYPE_NOT_FIXED_1((xmlSchemaTypePtr) item)) {
21176 		    xmlSchemaFixupSimpleTypeStageOne(pctxt,
21177 			(xmlSchemaTypePtr) item);
21178 		    FIXHFAILURE;
21179 		}
21180 		break;
21181 	    default:
21182 		break;
21183 	}
21184     }
21185     if (pctxt->nberrors != 0)
21186 	goto exit_error;
21187     /*
21188     * Detect circular union types. Note that this needs the variety to
21189     * be already computed.
21190     */
21191     for (i = 0; i < nbItems; i++) {
21192 	item = items[i];
21193 	switch (item->type) {
21194             case XML_SCHEMA_TYPE_SIMPLE:
21195 		if (((xmlSchemaTypePtr) item)->memberTypes != NULL) {
21196 		    xmlSchemaCheckUnionTypeDefCircular(pctxt,
21197 			(xmlSchemaTypePtr) item);
21198 		    FIXHFAILURE;
21199 		}
21200 		break;
21201 	    default:
21202 		break;
21203 	}
21204     }
21205     if (pctxt->nberrors != 0)
21206 	goto exit_error;
21207 
21208     /*
21209     * Do the complete type fixup for simple types.
21210     */
21211     for (i = 0; i < nbItems; i++) {
21212 	item = items[i];
21213 	switch (item->type) {
21214             case XML_SCHEMA_TYPE_SIMPLE:
21215 		if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21216 		    xmlSchemaFixupSimpleTypeStageTwo(pctxt, WXS_TYPE_CAST item);
21217 		    FIXHFAILURE;
21218 		}
21219 		break;
21220 	    default:
21221 		break;
21222 	}
21223     }
21224     if (pctxt->nberrors != 0)
21225 	goto exit_error;
21226     /*
21227     * At this point we need build and check all simple types.
21228     */
21229     /*
21230     * Apply constraints for attribute declarations.
21231     */
21232     for (i = 0; i < nbItems; i++) {
21233 	item = items[i];
21234 	switch (item->type) {
21235 	    case XML_SCHEMA_TYPE_ATTRIBUTE:
21236 		xmlSchemaCheckAttrPropsCorrect(pctxt, WXS_ATTR_CAST item);
21237 		FIXHFAILURE;
21238 		break;
21239 	    default:
21240 		break;
21241 	}
21242     }
21243     if (pctxt->nberrors != 0)
21244 	goto exit_error;
21245     /*
21246     * Apply constraints for attribute uses.
21247     */
21248     for (i = 0; i < nbItems; i++) {
21249 	item = items[i];
21250 	switch (item->type) {
21251 	    case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
21252 		if (((xmlSchemaAttributeUsePtr)item)->defValue != NULL) {
21253 		    xmlSchemaCheckAttrUsePropsCorrect(pctxt,
21254 			WXS_ATTR_USE_CAST item);
21255 		    FIXHFAILURE;
21256 		}
21257 		break;
21258 	    default:
21259 		break;
21260 	}
21261     }
21262     if (pctxt->nberrors != 0)
21263 	goto exit_error;
21264 
21265     /*
21266     * Apply constraints for attribute group definitions.
21267     */
21268     for (i = 0; i < nbItems; i++) {
21269 	item = items[i];
21270 	switch (item->type) {
21271 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21272 	    if (( (WXS_ATTR_GROUP_CAST item)->attrUses != NULL) &&
21273 		( (WXS_LIST_CAST (WXS_ATTR_GROUP_CAST item)->attrUses)->nbItems > 1))
21274 	    {
21275 		xmlSchemaCheckAGPropsCorrect(pctxt, WXS_ATTR_GROUP_CAST item);
21276 		FIXHFAILURE;
21277 	    }
21278 	    break;
21279 	default:
21280 	    break;
21281 	}
21282     }
21283     if (pctxt->nberrors != 0)
21284 	goto exit_error;
21285 
21286     /*
21287     * Apply constraints for redefinitions.
21288     */
21289     if (WXS_CONSTRUCTOR(pctxt)->redefs != NULL)
21290 	xmlSchemaCheckSRCRedefineSecond(pctxt);
21291     if (pctxt->nberrors != 0)
21292 	goto exit_error;
21293 
21294     /*
21295     * Complex types are built and checked.
21296     */
21297     for (i = 0; i < nbItems; i++) {
21298 	item = con->pending->items[i];
21299 	switch (item->type) {
21300 	    case XML_SCHEMA_TYPE_COMPLEX:
21301 		if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21302 		    xmlSchemaFixupComplexType(pctxt, WXS_TYPE_CAST item);
21303 		    FIXHFAILURE;
21304 		}
21305 		break;
21306 	    default:
21307 		break;
21308 	}
21309     }
21310     if (pctxt->nberrors != 0)
21311 	goto exit_error;
21312 
21313     /*
21314     * The list could have changed, since xmlSchemaFixupComplexType()
21315     * will create particles and model groups in some cases.
21316     */
21317     items = (xmlSchemaTreeItemPtr *) con->pending->items;
21318     nbItems = con->pending->nbItems;
21319 
21320     /*
21321     * Apply some constraints for element declarations.
21322     */
21323     for (i = 0; i < nbItems; i++) {
21324 	item = items[i];
21325 	switch (item->type) {
21326 	    case XML_SCHEMA_TYPE_ELEMENT:
21327 		elemDecl = (xmlSchemaElementPtr) item;
21328 
21329 		if ((elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED) == 0)
21330 		{
21331 		    xmlSchemaCheckElementDeclComponent(
21332 			(xmlSchemaElementPtr) elemDecl, pctxt);
21333 		    FIXHFAILURE;
21334 		}
21335 
21336 #ifdef WXS_ELEM_DECL_CONS_ENABLED
21337 		/*
21338 		* Schema Component Constraint: Element Declarations Consistent
21339 		* Apply this constraint to local types of element declarations.
21340 		*/
21341 		if ((WXS_ELEM_TYPEDEF(elemDecl) != NULL) &&
21342 		    (WXS_IS_COMPLEX(WXS_ELEM_TYPEDEF(elemDecl))) &&
21343 		    (WXS_TYPE_IS_LOCAL(WXS_ELEM_TYPEDEF(elemDecl))))
21344 		{
21345 		    xmlSchemaCheckElementDeclConsistent(pctxt,
21346 			WXS_BASIC_CAST elemDecl,
21347 			WXS_TYPE_PARTICLE(WXS_ELEM_TYPEDEF(elemDecl)),
21348 			NULL, NULL, 0);
21349 		}
21350 #endif
21351 		break;
21352 	    default:
21353 		break;
21354 	}
21355     }
21356     if (pctxt->nberrors != 0)
21357 	goto exit_error;
21358 
21359     /*
21360     * Finally we can build the automaton from the content model of
21361     * complex types.
21362     */
21363 
21364     for (i = 0; i < nbItems; i++) {
21365 	item = items[i];
21366 	switch (item->type) {
21367 	    case XML_SCHEMA_TYPE_COMPLEX:
21368 		xmlSchemaBuildContentModel((xmlSchemaTypePtr) item, pctxt);
21369 		/* FIXHFAILURE; */
21370 		break;
21371 	    default:
21372 		break;
21373 	}
21374     }
21375     if (pctxt->nberrors != 0)
21376 	goto exit_error;
21377     /*
21378     * URGENT TODO: cos-element-consistent
21379     */
21380     goto exit;
21381 
21382 exit_error:
21383     ret = pctxt->err;
21384     goto exit;
21385 
21386 exit_failure:
21387     ret = -1;
21388 
21389 exit:
21390     /*
21391     * Reset the constructor. This is needed for XSI acquisition, since
21392     * those items will be processed over and over again for every XSI
21393     * if not cleared here.
21394     */
21395     con->bucket = oldbucket;
21396     con->pending->nbItems = 0;
21397     if (con->substGroups != NULL) {
21398 	xmlHashFree(con->substGroups, xmlSchemaSubstGroupFreeEntry);
21399 	con->substGroups = NULL;
21400     }
21401     if (con->redefs != NULL) {
21402 	xmlSchemaRedefListFree(con->redefs);
21403 	con->redefs = NULL;
21404     }
21405     return(ret);
21406 }
21407 /**
21408  * xmlSchemaParse:
21409  * @ctxt:  a schema validation context
21410  *
21411  * parse a schema definition resource and build an internal
21412  * XML Schema structure which can be used to validate instances.
21413  *
21414  * Returns the internal XML Schema structure built from the resource or
21415  *         NULL in case of error
21416  */
21417 xmlSchemaPtr
xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)21418 xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
21419 {
21420     xmlSchemaPtr mainSchema = NULL;
21421     xmlSchemaBucketPtr bucket = NULL;
21422     int res;
21423 
21424     /*
21425     * This one is used if the schema to be parsed was specified via
21426     * the API; i.e. not automatically by the validated instance document.
21427     */
21428 
21429     xmlSchemaInitTypes();
21430 
21431     if (ctxt == NULL)
21432         return (NULL);
21433 
21434     /* TODO: Init the context. Is this all we need?*/
21435     ctxt->nberrors = 0;
21436     ctxt->err = 0;
21437     ctxt->counter = 0;
21438 
21439     /* Create the *main* schema. */
21440     mainSchema = xmlSchemaNewSchema(ctxt);
21441     if (mainSchema == NULL)
21442 	goto exit_failure;
21443     /*
21444     * Create the schema constructor.
21445     */
21446     if (ctxt->constructor == NULL) {
21447 	ctxt->constructor = xmlSchemaConstructionCtxtCreate(ctxt->dict);
21448 	if (ctxt->constructor == NULL)
21449 	    return(NULL);
21450 	/* Take ownership of the constructor to be able to free it. */
21451 	ctxt->ownsConstructor = 1;
21452     }
21453     ctxt->constructor->mainSchema = mainSchema;
21454     /*
21455     * Locate and add the schema document.
21456     */
21457     res = xmlSchemaAddSchemaDoc(ctxt, XML_SCHEMA_SCHEMA_MAIN,
21458 	ctxt->URL, ctxt->doc, ctxt->buffer, ctxt->size, NULL,
21459 	NULL, NULL, &bucket);
21460     if (res == -1)
21461 	goto exit_failure;
21462     if (res != 0)
21463 	goto exit;
21464 
21465     if (bucket == NULL) {
21466 	/* TODO: Error code, actually we failed to *locate* the schema. */
21467 	if (ctxt->URL)
21468 	    xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21469 		NULL, NULL,
21470 		"Failed to locate the main schema resource at '%s'",
21471 		ctxt->URL, NULL);
21472 	else
21473 	    xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21474 		NULL, NULL,
21475 		"Failed to locate the main schema resource",
21476 		    NULL, NULL);
21477 	goto exit;
21478     }
21479     /* Then do the parsing for good. */
21480     if (xmlSchemaParseNewDocWithContext(ctxt, mainSchema, bucket) == -1)
21481 	goto exit_failure;
21482     if (ctxt->nberrors != 0)
21483 	goto exit;
21484 
21485     mainSchema->doc = bucket->doc;
21486     mainSchema->preserve = ctxt->preserve;
21487 
21488     ctxt->schema = mainSchema;
21489 
21490     if (xmlSchemaFixupComponents(ctxt, WXS_CONSTRUCTOR(ctxt)->mainBucket) == -1)
21491 	goto exit_failure;
21492 
21493     /*
21494     * TODO: This is not nice, since we cannot distinguish from the
21495     * result if there was an internal error or not.
21496     */
21497 exit:
21498     if (ctxt->nberrors != 0) {
21499 	if (mainSchema) {
21500 	    xmlSchemaFree(mainSchema);
21501 	    mainSchema = NULL;
21502 	}
21503 	if (ctxt->constructor) {
21504 	    xmlSchemaConstructionCtxtFree(ctxt->constructor);
21505 	    ctxt->constructor = NULL;
21506 	    ctxt->ownsConstructor = 0;
21507 	}
21508     }
21509     ctxt->schema = NULL;
21510     return(mainSchema);
21511 exit_failure:
21512     /*
21513     * Quite verbose, but should catch internal errors, which were
21514     * not communicated.
21515     */
21516     if (mainSchema) {
21517         xmlSchemaFree(mainSchema);
21518 	mainSchema = NULL;
21519     }
21520     if (ctxt->constructor) {
21521 	xmlSchemaConstructionCtxtFree(ctxt->constructor);
21522 	ctxt->constructor = NULL;
21523 	ctxt->ownsConstructor = 0;
21524     }
21525     PERROR_INT2("xmlSchemaParse",
21526 	"An internal error occurred");
21527     ctxt->schema = NULL;
21528     return(NULL);
21529 }
21530 
21531 /**
21532  * xmlSchemaSetParserErrors:
21533  * @ctxt:  a schema validation context
21534  * @err:  the error callback
21535  * @warn:  the warning callback
21536  * @ctx:  contextual data for the callbacks
21537  *
21538  * Set the callback functions used to handle errors for a validation context
21539  */
21540 void
xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,xmlSchemaValidityErrorFunc err,xmlSchemaValidityWarningFunc warn,void * ctx)21541 xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21542                          xmlSchemaValidityErrorFunc err,
21543                          xmlSchemaValidityWarningFunc warn, void *ctx)
21544 {
21545     if (ctxt == NULL)
21546         return;
21547     ctxt->error = err;
21548     ctxt->warning = warn;
21549     ctxt->errCtxt = ctx;
21550     if (ctxt->vctxt != NULL)
21551 	xmlSchemaSetValidErrors(ctxt->vctxt, err, warn, ctx);
21552 }
21553 
21554 /**
21555  * xmlSchemaSetParserStructuredErrors:
21556  * @ctxt:  a schema parser context
21557  * @serror:  the structured error function
21558  * @ctx: the functions context
21559  *
21560  * Set the structured error callback
21561  */
21562 void
xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,xmlStructuredErrorFunc serror,void * ctx)21563 xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,
21564 				   xmlStructuredErrorFunc serror,
21565 				   void *ctx)
21566 {
21567     if (ctxt == NULL)
21568 	return;
21569     ctxt->serror = serror;
21570     ctxt->errCtxt = ctx;
21571     if (ctxt->vctxt != NULL)
21572 	xmlSchemaSetValidStructuredErrors(ctxt->vctxt, serror, ctx);
21573 }
21574 
21575 /**
21576  * xmlSchemaGetParserErrors:
21577  * @ctxt:  a XMl-Schema parser context
21578  * @err: the error callback result
21579  * @warn: the warning callback result
21580  * @ctx: contextual data for the callbacks result
21581  *
21582  * Get the callback information used to handle errors for a parser context
21583  *
21584  * Returns -1 in case of failure, 0 otherwise
21585  */
21586 int
xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,xmlSchemaValidityErrorFunc * err,xmlSchemaValidityWarningFunc * warn,void ** ctx)21587 xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21588 			 xmlSchemaValidityErrorFunc * err,
21589 			 xmlSchemaValidityWarningFunc * warn, void **ctx)
21590 {
21591 	if (ctxt == NULL)
21592 		return(-1);
21593 	if (err != NULL)
21594 		*err = ctxt->error;
21595 	if (warn != NULL)
21596 		*warn = ctxt->warning;
21597 	if (ctx != NULL)
21598 		*ctx = ctxt->errCtxt;
21599 	return(0);
21600 }
21601 
21602 /**
21603  * xmlSchemaFacetTypeToString:
21604  * @type:  the facet type
21605  *
21606  * Convert the xmlSchemaTypeType to a char string.
21607  *
21608  * Returns the char string representation of the facet type if the
21609  *     type is a facet and an "Internal Error" string otherwise.
21610  */
21611 static const xmlChar *
xmlSchemaFacetTypeToString(xmlSchemaTypeType type)21612 xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
21613 {
21614     switch (type) {
21615         case XML_SCHEMA_FACET_PATTERN:
21616             return (BAD_CAST "pattern");
21617         case XML_SCHEMA_FACET_MAXEXCLUSIVE:
21618             return (BAD_CAST "maxExclusive");
21619         case XML_SCHEMA_FACET_MAXINCLUSIVE:
21620             return (BAD_CAST "maxInclusive");
21621         case XML_SCHEMA_FACET_MINEXCLUSIVE:
21622             return (BAD_CAST "minExclusive");
21623         case XML_SCHEMA_FACET_MININCLUSIVE:
21624             return (BAD_CAST "minInclusive");
21625         case XML_SCHEMA_FACET_WHITESPACE:
21626             return (BAD_CAST "whiteSpace");
21627         case XML_SCHEMA_FACET_ENUMERATION:
21628             return (BAD_CAST "enumeration");
21629         case XML_SCHEMA_FACET_LENGTH:
21630             return (BAD_CAST "length");
21631         case XML_SCHEMA_FACET_MAXLENGTH:
21632             return (BAD_CAST "maxLength");
21633         case XML_SCHEMA_FACET_MINLENGTH:
21634             return (BAD_CAST "minLength");
21635         case XML_SCHEMA_FACET_TOTALDIGITS:
21636             return (BAD_CAST "totalDigits");
21637         case XML_SCHEMA_FACET_FRACTIONDIGITS:
21638             return (BAD_CAST "fractionDigits");
21639         default:
21640             break;
21641     }
21642     return (BAD_CAST "Internal Error");
21643 }
21644 
21645 static xmlSchemaWhitespaceValueType
xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)21646 xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
21647 {
21648     /*
21649     * The normalization type can be changed only for types which are derived
21650     * from xsd:string.
21651     */
21652     if (type->type == XML_SCHEMA_TYPE_BASIC) {
21653 	/*
21654 	* Note that we assume a whitespace of preserve for anySimpleType.
21655 	*/
21656 	if ((type->builtInType == XML_SCHEMAS_STRING) ||
21657 	    (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
21658 	    return(XML_SCHEMA_WHITESPACE_PRESERVE);
21659 	else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
21660 	    return(XML_SCHEMA_WHITESPACE_REPLACE);
21661 	else {
21662 	    /*
21663 	    * For all `atomic` datatypes other than string (and types `derived`
21664 	    * by `restriction` from it) the value of whiteSpace is fixed to
21665 	    * collapse
21666 	    * Note that this includes built-in list datatypes.
21667 	    */
21668 	    return(XML_SCHEMA_WHITESPACE_COLLAPSE);
21669 	}
21670     } else if (WXS_IS_LIST(type)) {
21671 	/*
21672 	* For list types the facet "whiteSpace" is fixed to "collapse".
21673 	*/
21674 	return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21675     } else if (WXS_IS_UNION(type)) {
21676 	return (XML_SCHEMA_WHITESPACE_UNKNOWN);
21677     } else if (WXS_IS_ATOMIC(type)) {
21678 	if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
21679 	    return (XML_SCHEMA_WHITESPACE_PRESERVE);
21680 	else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
21681 	    return (XML_SCHEMA_WHITESPACE_REPLACE);
21682 	else
21683 	    return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21684     }
21685     return (-1);
21686 }
21687 
21688 /************************************************************************
21689  *									*
21690  *			Simple type validation				*
21691  *									*
21692  ************************************************************************/
21693 
21694 
21695 /************************************************************************
21696  *									*
21697  *			DOM Validation code				*
21698  *									*
21699  ************************************************************************/
21700 
21701 /**
21702  * xmlSchemaAssembleByLocation:
21703  * @pctxt:  a schema parser context
21704  * @vctxt:  a schema validation context
21705  * @schema: the existing schema
21706  * @node: the node that fired the assembling
21707  * @nsName: the namespace name of the new schema
21708  * @location: the location of the schema
21709  *
21710  * Expands an existing schema by an additional schema.
21711  *
21712  * Returns 0 if the new schema is correct, a positive error code
21713  * number otherwise and -1 in case of an internal or API error.
21714  */
21715 static int
xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,xmlSchemaPtr schema,xmlNodePtr node,const xmlChar * nsName,const xmlChar * location)21716 xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
21717 			    xmlSchemaPtr schema,
21718 			    xmlNodePtr node,
21719 			    const xmlChar *nsName,
21720 			    const xmlChar *location)
21721 {
21722     int ret = 0;
21723     xmlSchemaParserCtxtPtr pctxt;
21724     xmlSchemaBucketPtr bucket = NULL;
21725 
21726     if ((vctxt == NULL) || (schema == NULL))
21727 	return (-1);
21728 
21729     if (vctxt->pctxt == NULL) {
21730 	VERROR_INT("xmlSchemaAssembleByLocation",
21731 	    "no parser context available");
21732 	return(-1);
21733     }
21734     pctxt = vctxt->pctxt;
21735     if (pctxt->constructor == NULL) {
21736 	PERROR_INT("xmlSchemaAssembleByLocation",
21737 	    "no constructor");
21738 	return(-1);
21739     }
21740     /*
21741     * Acquire the schema document.
21742     */
21743     location = xmlSchemaBuildAbsoluteURI(pctxt->dict,
21744 	location, node);
21745     /*
21746     * Note that we pass XML_SCHEMA_SCHEMA_IMPORT here;
21747     * the process will automatically change this to
21748     * XML_SCHEMA_SCHEMA_MAIN if it is the first schema document.
21749     */
21750     ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
21751 	location, NULL, NULL, 0, node, NULL, nsName,
21752 	&bucket);
21753     if (ret != 0)
21754 	return(ret);
21755     if (bucket == NULL) {
21756 	/*
21757 	* Generate a warning that the document could not be located.
21758 	*/
21759 	xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21760 	    node, NULL,
21761 	    "The document at location '%s' could not be acquired",
21762 	    location, NULL, NULL);
21763 	return(ret);
21764     }
21765     /*
21766     * The first located schema will be handled as if all other
21767     * schemas imported by XSI were imported by this first schema.
21768     */
21769     if ((bucket != NULL) &&
21770 	(WXS_CONSTRUCTOR(pctxt)->bucket == NULL))
21771 	WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
21772     /*
21773     * TODO: Is this handled like an import? I.e. is it not an error
21774     * if the schema cannot be located?
21775     */
21776     if ((bucket == NULL) || (! CAN_PARSE_SCHEMA(bucket)))
21777 	return(0);
21778     /*
21779     * We will reuse the parser context for every schema imported
21780     * directly via XSI. So reset the context.
21781     */
21782     pctxt->nberrors = 0;
21783     pctxt->err = 0;
21784     pctxt->doc = bucket->doc;
21785 
21786     ret = xmlSchemaParseNewDocWithContext(pctxt, schema, bucket);
21787     if (ret == -1) {
21788 	pctxt->doc = NULL;
21789 	goto exit_failure;
21790     }
21791     /* Paranoid error channelling. */
21792     if ((ret == 0) && (pctxt->nberrors != 0))
21793 	ret = pctxt->err;
21794     if (pctxt->nberrors == 0) {
21795 	/*
21796 	* Only bother to fixup pending components, if there was
21797 	* no error yet.
21798 	* For every XSI acquired schema (and its sub-schemata) we will
21799 	* fixup the components.
21800 	*/
21801 	xmlSchemaFixupComponents(pctxt, bucket);
21802 	ret = pctxt->err;
21803 	/*
21804 	* Not nice, but we need somehow to channel the schema parser
21805 	* error to the validation context.
21806 	*/
21807 	if ((ret != 0) && (vctxt->err == 0))
21808 	    vctxt->err = ret;
21809 	vctxt->nberrors += pctxt->nberrors;
21810     } else {
21811 	/* Add to validation error sum. */
21812 	vctxt->nberrors += pctxt->nberrors;
21813     }
21814     pctxt->doc = NULL;
21815     return(ret);
21816 exit_failure:
21817     pctxt->doc = NULL;
21818     return (-1);
21819 }
21820 
21821 static xmlSchemaAttrInfoPtr
xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,int metaType)21822 xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
21823 			 int metaType)
21824 {
21825     if (vctxt->nbAttrInfos == 0)
21826 	return (NULL);
21827     {
21828 	int i;
21829 	xmlSchemaAttrInfoPtr iattr;
21830 
21831 	for (i = 0; i < vctxt->nbAttrInfos; i++) {
21832 	    iattr = vctxt->attrInfos[i];
21833 	    if (iattr->metaType == metaType)
21834 		return (iattr);
21835 	}
21836 
21837     }
21838     return (NULL);
21839 }
21840 
21841 /**
21842  * xmlSchemaAssembleByXSI:
21843  * @vctxt:  a schema validation context
21844  *
21845  * Expands an existing schema by an additional schema using
21846  * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
21847  * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
21848  * must be set to 1.
21849  *
21850  * Returns 0 if the new schema is correct, a positive error code
21851  * number otherwise and -1 in case of an internal or API error.
21852  */
21853 static int
xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)21854 xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
21855 {
21856     const xmlChar *cur, *end;
21857     const xmlChar *nsname = NULL, *location;
21858     int count = 0;
21859     int ret = 0;
21860     xmlSchemaAttrInfoPtr iattr;
21861 
21862     /*
21863     * Parse the value; we will assume an even number of values
21864     * to be given (this is how Xerces and XSV work).
21865     *
21866     * URGENT TODO: !! This needs to work for both
21867     * @noNamespaceSchemaLocation AND @schemaLocation on the same
21868     * element !!
21869     */
21870     iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21871 	XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
21872     if (iattr == NULL)
21873 	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21874 	XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
21875     if (iattr == NULL)
21876 	return (0);
21877     cur = iattr->value;
21878     do {
21879 	/*
21880 	* TODO: Move the string parsing mechanism away from here.
21881 	*/
21882 	if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
21883 	    /*
21884 	    * Get the namespace name.
21885 	    */
21886 	    while (IS_BLANK_CH(*cur))
21887 		cur++;
21888 	    end = cur;
21889 	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21890 		end++;
21891 	    if (end == cur)
21892 		break;
21893 	    count++; /* TODO: Don't use the schema's dict. */
21894 	    nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21895 	    cur = end;
21896 	}
21897 	/*
21898 	* Get the URI.
21899 	*/
21900 	while (IS_BLANK_CH(*cur))
21901 	    cur++;
21902 	end = cur;
21903 	while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21904 	    end++;
21905 	if (end == cur) {
21906 	    if (iattr->metaType ==
21907 		XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC)
21908 	    {
21909 		/*
21910 		* If using @schemaLocation then tuples are expected.
21911 		* I.e. the namespace name *and* the document's URI.
21912 		*/
21913 		xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21914 		    iattr->node, NULL,
21915 		    "The value must consist of tuples: the target namespace "
21916 		    "name and the document's URI", NULL, NULL, NULL);
21917 	    }
21918 	    break;
21919 	}
21920 	count++; /* TODO: Don't use the schema's dict. */
21921 	location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21922 	cur = end;
21923 	ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
21924 	    iattr->node, nsname, location);
21925 	if (ret == -1) {
21926 	    VERROR_INT("xmlSchemaAssembleByXSI",
21927 		"assembling schemata");
21928 	    return (-1);
21929 	}
21930     } while (*cur != 0);
21931     return (ret);
21932 }
21933 
21934 static const xmlChar *
xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,const xmlChar * prefix)21935 xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
21936 			 const xmlChar *prefix)
21937 {
21938     if (vctxt->sax != NULL) {
21939 	int i, j;
21940 	xmlSchemaNodeInfoPtr inode;
21941 
21942 	for (i = vctxt->depth; i >= 0; i--) {
21943 	    if (vctxt->elemInfos[i]->nbNsBindings != 0) {
21944 		inode = vctxt->elemInfos[i];
21945 		for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
21946 		    if (((prefix == NULL) &&
21947 			    (inode->nsBindings[j] == NULL)) ||
21948 			((prefix != NULL) && xmlStrEqual(prefix,
21949 			    inode->nsBindings[j]))) {
21950 
21951 			/*
21952 			* Note that the namespace bindings are already
21953 			* in a string dict.
21954 			*/
21955 			return (inode->nsBindings[j+1]);
21956 		    }
21957 		}
21958 	    }
21959 	}
21960 	return (NULL);
21961 #ifdef LIBXML_READER_ENABLED
21962     } else if (vctxt->reader != NULL) {
21963 	xmlChar *nsName;
21964 
21965 	nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
21966 	if (nsName != NULL) {
21967 	    const xmlChar *ret;
21968 
21969 	    ret = xmlDictLookup(vctxt->dict, nsName, -1);
21970 	    xmlFree(nsName);
21971 	    return (ret);
21972 	} else
21973 	    return (NULL);
21974 #endif
21975     } else {
21976 	xmlNsPtr ns;
21977 
21978 	if ((vctxt->inode->node == NULL) ||
21979 	    (vctxt->inode->node->doc == NULL)) {
21980 	    VERROR_INT("xmlSchemaLookupNamespace",
21981 		"no node or node's doc available");
21982 	    return (NULL);
21983 	}
21984 	ns = xmlSearchNs(vctxt->inode->node->doc,
21985 	    vctxt->inode->node, prefix);
21986 	if (ns != NULL)
21987 	    return (ns->href);
21988 	return (NULL);
21989     }
21990 }
21991 
21992 /*
21993 * This one works on the schema of the validation context.
21994 */
21995 static int
xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,xmlSchemaPtr schema,xmlNodePtr node,const xmlChar * value,xmlSchemaValPtr * val,int valNeeded)21996 xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
21997 			  xmlSchemaPtr schema,
21998 			  xmlNodePtr node,
21999 			  const xmlChar *value,
22000 			  xmlSchemaValPtr *val,
22001 			  int valNeeded)
22002 {
22003     int ret;
22004 
22005     if (vctxt && (vctxt->schema == NULL)) {
22006 	VERROR_INT("xmlSchemaValidateNotation",
22007 	    "a schema is needed on the validation context");
22008 	return (-1);
22009     }
22010     ret = xmlValidateQName(value, 1);
22011     if (ret != 0)
22012 	return (ret);
22013     {
22014 	xmlChar *localName = NULL;
22015 	xmlChar *prefix = NULL;
22016 
22017 	localName = xmlSplitQName2(value, &prefix);
22018 	if (prefix != NULL) {
22019 	    const xmlChar *nsName = NULL;
22020 
22021 	    if (vctxt != NULL)
22022 		nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
22023 	    else if (node != NULL) {
22024 		xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
22025 		if (ns != NULL)
22026 		    nsName = ns->href;
22027 	    } else {
22028 		xmlFree(prefix);
22029 		xmlFree(localName);
22030 		return (1);
22031 	    }
22032 	    if (nsName == NULL) {
22033 		xmlFree(prefix);
22034 		xmlFree(localName);
22035 		return (1);
22036 	    }
22037 	    if (xmlSchemaGetNotation(schema, localName, nsName) != NULL) {
22038 		if ((valNeeded) && (val != NULL)) {
22039 		    (*val) = xmlSchemaNewNOTATIONValue(xmlStrdup(localName),
22040 						       xmlStrdup(nsName));
22041 		    if (*val == NULL)
22042 			ret = -1;
22043 		}
22044 	    } else
22045 		ret = 1;
22046 	    xmlFree(prefix);
22047 	    xmlFree(localName);
22048 	} else {
22049 	    if (xmlSchemaGetNotation(schema, value, NULL) != NULL) {
22050 		if (valNeeded && (val != NULL)) {
22051 		    (*val) = xmlSchemaNewNOTATIONValue(
22052 			BAD_CAST xmlStrdup(value), NULL);
22053 		    if (*val == NULL)
22054 			ret = -1;
22055 		}
22056 	    } else
22057 		return (1);
22058 	}
22059     }
22060     return (ret);
22061 }
22062 
22063 static int
xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,const xmlChar * lname,const xmlChar * nsname)22064 xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,
22065 		       const xmlChar* lname,
22066 		       const xmlChar* nsname)
22067 {
22068     int i;
22069 
22070     lname = xmlDictLookup(vctxt->dict, lname, -1);
22071     if (lname == NULL)
22072 	return(-1);
22073     if (nsname != NULL) {
22074 	nsname = xmlDictLookup(vctxt->dict, nsname, -1);
22075 	if (nsname == NULL)
22076 	    return(-1);
22077     }
22078     for (i = 0; i < vctxt->nodeQNames->nbItems; i += 2) {
22079 	if ((vctxt->nodeQNames->items [i] == lname) &&
22080 	    (vctxt->nodeQNames->items[i +1] == nsname))
22081 	    /* Already there */
22082 	    return(i);
22083     }
22084     /* Add new entry. */
22085     i = vctxt->nodeQNames->nbItems;
22086     xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) lname);
22087     xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) nsname);
22088     return(i);
22089 }
22090 
22091 /************************************************************************
22092  *									*
22093  *  Validation of identity-constraints (IDC)                            *
22094  *									*
22095  ************************************************************************/
22096 
22097 /**
22098  * xmlSchemaAugmentIDC:
22099  * @idcDef: the IDC definition
22100  *
22101  * Creates an augmented IDC definition item.
22102  *
22103  * Returns the item, or NULL on internal errors.
22104  */
22105 static void
xmlSchemaAugmentIDC(void * payload,void * data,const xmlChar * name ATTRIBUTE_UNUSED)22106 xmlSchemaAugmentIDC(void *payload, void *data,
22107                     const xmlChar *name ATTRIBUTE_UNUSED)
22108 {
22109     xmlSchemaIDCPtr idcDef = (xmlSchemaIDCPtr) payload;
22110     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) data;
22111     xmlSchemaIDCAugPtr aidc;
22112 
22113     aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
22114     if (aidc == NULL) {
22115 	xmlSchemaVErrMemory(vctxt,
22116 	    "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
22117 	    NULL);
22118 	return;
22119     }
22120     aidc->keyrefDepth = -1;
22121     aidc->def = idcDef;
22122     aidc->next = NULL;
22123     if (vctxt->aidcs == NULL)
22124 	vctxt->aidcs = aidc;
22125     else {
22126 	aidc->next = vctxt->aidcs;
22127 	vctxt->aidcs = aidc;
22128     }
22129     /*
22130     * Save if we have keyrefs at all.
22131     */
22132     if ((vctxt->hasKeyrefs == 0) &&
22133 	(idcDef->type == XML_SCHEMA_TYPE_IDC_KEYREF))
22134 	vctxt->hasKeyrefs = 1;
22135 }
22136 
22137 /**
22138  * xmlSchemaAugmentImportedIDC:
22139  * @imported: the imported schema
22140  *
22141  * Creates an augmented IDC definition for the imported schema.
22142  */
22143 static void
xmlSchemaAugmentImportedIDC(void * payload,void * data,const xmlChar * name ATTRIBUTE_UNUSED)22144 xmlSchemaAugmentImportedIDC(void *payload, void *data,
22145                             const xmlChar *name ATTRIBUTE_UNUSED) {
22146     xmlSchemaImportPtr imported = (xmlSchemaImportPtr) payload;
22147     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) data;
22148     if (imported->schema->idcDef != NULL) {
22149 	    xmlHashScan(imported->schema->idcDef, xmlSchemaAugmentIDC, vctxt);
22150     }
22151 }
22152 
22153 /**
22154  * xmlSchemaIDCNewBinding:
22155  * @idcDef: the IDC definition of this binding
22156  *
22157  * Creates a new IDC binding.
22158  *
22159  * Returns the new IDC binding, NULL on internal errors.
22160  */
22161 static xmlSchemaPSVIIDCBindingPtr
xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)22162 xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
22163 {
22164     xmlSchemaPSVIIDCBindingPtr ret;
22165 
22166     ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
22167 	    sizeof(xmlSchemaPSVIIDCBinding));
22168     if (ret == NULL) {
22169 	xmlSchemaVErrMemory(NULL,
22170 	    "allocating a PSVI IDC binding item", NULL);
22171 	return (NULL);
22172     }
22173     memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
22174     ret->definition = idcDef;
22175     return (ret);
22176 }
22177 
22178 /**
22179  * xmlSchemaIDCStoreNodeTableItem:
22180  * @vctxt: the WXS validation context
22181  * @item: the IDC node table item
22182  *
22183  * The validation context is used to store IDC node table items.
22184  * They are stored to avoid copying them if IDC node-tables are merged
22185  * with corresponding parent IDC node-tables (bubbling).
22186  *
22187  * Returns 0 if succeeded, -1 on internal errors.
22188  */
22189 static int
xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,xmlSchemaPSVIIDCNodePtr item)22190 xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
22191 			       xmlSchemaPSVIIDCNodePtr item)
22192 {
22193     /*
22194     * Add to global list.
22195     */
22196     if (vctxt->idcNodes == NULL) {
22197 	vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22198 	    xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
22199 	if (vctxt->idcNodes == NULL) {
22200 	    xmlSchemaVErrMemory(vctxt,
22201 		"allocating the IDC node table item list", NULL);
22202 	    return (-1);
22203 	}
22204 	vctxt->sizeIdcNodes = 20;
22205     } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
22206 	vctxt->sizeIdcNodes *= 2;
22207 	vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22208 	    xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
22209 	    sizeof(xmlSchemaPSVIIDCNodePtr));
22210 	if (vctxt->idcNodes == NULL) {
22211 	    xmlSchemaVErrMemory(vctxt,
22212 		"re-allocating the IDC node table item list", NULL);
22213 	    return (-1);
22214 	}
22215     }
22216     vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
22217 
22218     return (0);
22219 }
22220 
22221 /**
22222  * xmlSchemaIDCStoreKey:
22223  * @vctxt: the WXS validation context
22224  * @item: the IDC key
22225  *
22226  * The validation context is used to store an IDC key.
22227  *
22228  * Returns 0 if succeeded, -1 on internal errors.
22229  */
22230 static int
xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,xmlSchemaPSVIIDCKeyPtr key)22231 xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
22232 		     xmlSchemaPSVIIDCKeyPtr key)
22233 {
22234     /*
22235     * Add to global list.
22236     */
22237     if (vctxt->idcKeys == NULL) {
22238 	vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22239 	    xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
22240 	if (vctxt->idcKeys == NULL) {
22241 	    xmlSchemaVErrMemory(vctxt,
22242 		"allocating the IDC key storage list", NULL);
22243 	    return (-1);
22244 	}
22245 	vctxt->sizeIdcKeys = 40;
22246     } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
22247 	vctxt->sizeIdcKeys *= 2;
22248 	vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22249 	    xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
22250 	    sizeof(xmlSchemaPSVIIDCKeyPtr));
22251 	if (vctxt->idcKeys == NULL) {
22252 	    xmlSchemaVErrMemory(vctxt,
22253 		"re-allocating the IDC key storage list", NULL);
22254 	    return (-1);
22255 	}
22256     }
22257     vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
22258 
22259     return (0);
22260 }
22261 
22262 /**
22263  * xmlSchemaIDCAppendNodeTableItem:
22264  * @bind: the IDC binding
22265  * @ntItem: the node-table item
22266  *
22267  * Appends the IDC node-table item to the binding.
22268  *
22269  * Returns 0 on success and -1 on internal errors.
22270  */
22271 static int
xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,xmlSchemaPSVIIDCNodePtr ntItem)22272 xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
22273 				xmlSchemaPSVIIDCNodePtr ntItem)
22274 {
22275     if (bind->nodeTable == NULL) {
22276 	bind->sizeNodes = 10;
22277 	bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22278 	    xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
22279 	if (bind->nodeTable == NULL) {
22280 	    xmlSchemaVErrMemory(NULL,
22281 		"allocating an array of IDC node-table items", NULL);
22282 	    return(-1);
22283 	}
22284     } else if (bind->sizeNodes <= bind->nbNodes) {
22285 	bind->sizeNodes *= 2;
22286 	bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22287 	    xmlRealloc(bind->nodeTable, bind->sizeNodes *
22288 		sizeof(xmlSchemaPSVIIDCNodePtr));
22289 	if (bind->nodeTable == NULL) {
22290 	    xmlSchemaVErrMemory(NULL,
22291 		"re-allocating an array of IDC node-table items", NULL);
22292 	    return(-1);
22293 	}
22294     }
22295     bind->nodeTable[bind->nbNodes++] = ntItem;
22296     return(0);
22297 }
22298 
22299 /**
22300  * xmlSchemaIDCAcquireBinding:
22301  * @vctxt: the WXS validation context
22302  * @matcher: the IDC matcher
22303  *
22304  * Looks up an PSVI IDC binding, for the IDC definition and
22305  * of the given matcher. If none found, a new one is created
22306  * and added to the IDC table.
22307  *
22308  * Returns an IDC binding or NULL on internal errors.
22309  */
22310 static xmlSchemaPSVIIDCBindingPtr
xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,xmlSchemaIDCMatcherPtr matcher)22311 xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,
22312 			  xmlSchemaIDCMatcherPtr matcher)
22313 {
22314     xmlSchemaNodeInfoPtr ielem;
22315 
22316     ielem = vctxt->elemInfos[matcher->depth];
22317 
22318     if (ielem->idcTable == NULL) {
22319 	ielem->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
22320 	if (ielem->idcTable == NULL)
22321 	    return (NULL);
22322 	return(ielem->idcTable);
22323     } else {
22324 	xmlSchemaPSVIIDCBindingPtr bind = NULL;
22325 
22326 	bind = ielem->idcTable;
22327 	do {
22328 	    if (bind->definition == matcher->aidc->def)
22329 		return(bind);
22330 	    if (bind->next == NULL) {
22331 		bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
22332 		if (bind->next == NULL)
22333 		    return (NULL);
22334 		return(bind->next);
22335 	    }
22336 	    bind = bind->next;
22337 	} while (bind != NULL);
22338     }
22339     return (NULL);
22340 }
22341 
22342 static xmlSchemaItemListPtr
xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,xmlSchemaIDCMatcherPtr matcher)22343 xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
22344 			     xmlSchemaIDCMatcherPtr matcher)
22345 {
22346     if (matcher->targets == NULL)
22347 	matcher->targets = xmlSchemaItemListCreate();
22348     return(matcher->targets);
22349 }
22350 
22351 /**
22352  * xmlSchemaIDCFreeKey:
22353  * @key: the IDC key
22354  *
22355  * Frees an IDC key together with its compiled value.
22356  */
22357 static void
xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)22358 xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
22359 {
22360     if (key->val != NULL)
22361 	xmlSchemaFreeValue(key->val);
22362     xmlFree(key);
22363 }
22364 
22365 /**
22366  * xmlSchemaIDCFreeBinding:
22367  *
22368  * Frees an IDC binding. Note that the node table-items
22369  * are not freed.
22370  */
22371 static void
xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)22372 xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
22373 {
22374     if (bind->nodeTable != NULL)
22375 	xmlFree(bind->nodeTable);
22376     if (bind->dupls != NULL)
22377 	xmlSchemaItemListFree(bind->dupls);
22378     xmlFree(bind);
22379 }
22380 
22381 /**
22382  * xmlSchemaIDCFreeIDCTable:
22383  * @bind: the first IDC binding in the list
22384  *
22385  * Frees an IDC table, i.e. all the IDC bindings in the list.
22386  */
22387 static void
xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)22388 xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
22389 {
22390     xmlSchemaPSVIIDCBindingPtr prev;
22391 
22392     while (bind != NULL) {
22393 	prev = bind;
22394 	bind = bind->next;
22395 	xmlSchemaIDCFreeBinding(prev);
22396     }
22397 }
22398 
22399 static void
xmlFreeIDCHashEntry(void * payload,const xmlChar * name ATTRIBUTE_UNUSED)22400 xmlFreeIDCHashEntry (void *payload, const xmlChar *name ATTRIBUTE_UNUSED)
22401 {
22402     xmlIDCHashEntryPtr e = payload, n;
22403     while (e) {
22404 	n = e->next;
22405 	xmlFree(e);
22406 	e = n;
22407     }
22408 }
22409 
22410 /**
22411  * xmlSchemaIDCFreeMatcherList:
22412  * @matcher: the first IDC matcher in the list
22413  *
22414  * Frees a list of IDC matchers.
22415  */
22416 static void
xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)22417 xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
22418 {
22419     xmlSchemaIDCMatcherPtr next;
22420 
22421     while (matcher != NULL) {
22422 	next = matcher->next;
22423 	if (matcher->keySeqs != NULL) {
22424 	    int i;
22425 	    for (i = 0; i < matcher->sizeKeySeqs; i++)
22426 		if (matcher->keySeqs[i] != NULL)
22427 		    xmlFree(matcher->keySeqs[i]);
22428 	    xmlFree(matcher->keySeqs);
22429 	}
22430 	if (matcher->targets != NULL) {
22431 	    if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22432 		int i;
22433 		xmlSchemaPSVIIDCNodePtr idcNode;
22434 		/*
22435 		* Node-table items for keyrefs are not stored globally
22436 		* to the validation context, since they are not bubbled.
22437 		* We need to free them here.
22438 		*/
22439 		for (i = 0; i < matcher->targets->nbItems; i++) {
22440 		    idcNode =
22441 			(xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22442 		    xmlFree(idcNode->keys);
22443 		    xmlFree(idcNode);
22444 		}
22445 	    }
22446 	    xmlSchemaItemListFree(matcher->targets);
22447 	}
22448 	if (matcher->htab != NULL)
22449 	  xmlHashFree(matcher->htab, xmlFreeIDCHashEntry);
22450 	xmlFree(matcher);
22451 	matcher = next;
22452     }
22453 }
22454 
22455 /**
22456  * xmlSchemaIDCReleaseMatcherList:
22457  * @vctxt: the WXS validation context
22458  * @matcher: the first IDC matcher in the list
22459  *
22460  * Caches a list of IDC matchers for reuse.
22461  */
22462 static void
xmlSchemaIDCReleaseMatcherList(xmlSchemaValidCtxtPtr vctxt,xmlSchemaIDCMatcherPtr matcher)22463 xmlSchemaIDCReleaseMatcherList(xmlSchemaValidCtxtPtr vctxt,
22464 			       xmlSchemaIDCMatcherPtr matcher)
22465 {
22466     xmlSchemaIDCMatcherPtr next;
22467 
22468     while (matcher != NULL) {
22469 	next = matcher->next;
22470 	if (matcher->keySeqs != NULL) {
22471 	    int i;
22472 	    /*
22473 	    * Don't free the array, but only the content.
22474 	    */
22475 	    for (i = 0; i < matcher->sizeKeySeqs; i++)
22476 		if (matcher->keySeqs[i] != NULL) {
22477 		    xmlFree(matcher->keySeqs[i]);
22478 		    matcher->keySeqs[i] = NULL;
22479 		}
22480 	}
22481 	if (matcher->targets) {
22482 	    if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22483 		int i;
22484 		xmlSchemaPSVIIDCNodePtr idcNode;
22485 		/*
22486 		* Node-table items for keyrefs are not stored globally
22487 		* to the validation context, since they are not bubbled.
22488 		* We need to free them here.
22489 		*/
22490 		for (i = 0; i < matcher->targets->nbItems; i++) {
22491 		    idcNode =
22492 			(xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22493 		    xmlFree(idcNode->keys);
22494 		    xmlFree(idcNode);
22495 		}
22496 	    }
22497 	    xmlSchemaItemListFree(matcher->targets);
22498 	    matcher->targets = NULL;
22499 	}
22500 	if (matcher->htab != NULL) {
22501 	    xmlHashFree(matcher->htab, xmlFreeIDCHashEntry);
22502 	    matcher->htab = NULL;
22503 	}
22504 	matcher->next = NULL;
22505 	/*
22506 	* Cache the matcher.
22507 	*/
22508 	if (vctxt->idcMatcherCache != NULL)
22509 	    matcher->nextCached = vctxt->idcMatcherCache;
22510 	vctxt->idcMatcherCache = matcher;
22511 
22512 	matcher = next;
22513     }
22514 }
22515 
22516 /**
22517  * xmlSchemaIDCAddStateObject:
22518  * @vctxt: the WXS validation context
22519  * @matcher: the IDC matcher
22520  * @sel: the XPath information
22521  * @parent: the parent "selector" state object if any
22522  * @type: "selector" or "field"
22523  *
22524  * Creates/reuses and activates state objects for the given
22525  * XPath information; if the XPath expression consists of unions,
22526  * multiple state objects are created for every unioned expression.
22527  *
22528  * Returns 0 on success and -1 on internal errors.
22529  */
22530 static int
xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,xmlSchemaIDCMatcherPtr matcher,xmlSchemaIDCSelectPtr sel,int type)22531 xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
22532 			xmlSchemaIDCMatcherPtr matcher,
22533 			xmlSchemaIDCSelectPtr sel,
22534 			int type)
22535 {
22536     xmlSchemaIDCStateObjPtr sto;
22537 
22538     /*
22539     * Reuse the state objects from the pool.
22540     */
22541     if (vctxt->xpathStatePool != NULL) {
22542 	sto = vctxt->xpathStatePool;
22543 	vctxt->xpathStatePool = sto->next;
22544 	sto->next = NULL;
22545     } else {
22546 	/*
22547 	* Create a new state object.
22548 	*/
22549 	sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
22550 	if (sto == NULL) {
22551 	    xmlSchemaVErrMemory(NULL,
22552 		"allocating an IDC state object", NULL);
22553 	    return (-1);
22554 	}
22555 	memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
22556     }
22557     /*
22558     * Add to global list.
22559     */
22560     if (vctxt->xpathStates != NULL)
22561 	sto->next = vctxt->xpathStates;
22562     vctxt->xpathStates = sto;
22563 
22564     /*
22565     * Free the old xpath validation context.
22566     */
22567     if (sto->xpathCtxt != NULL)
22568 	xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
22569 
22570     /*
22571     * Create a new XPath (pattern) validation context.
22572     */
22573     sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
22574 	(xmlPatternPtr) sel->xpathComp);
22575     if (sto->xpathCtxt == NULL) {
22576 	VERROR_INT("xmlSchemaIDCAddStateObject",
22577 	    "failed to create an XPath validation context");
22578 	return (-1);
22579     }
22580     sto->type = type;
22581     sto->depth = vctxt->depth;
22582     sto->matcher = matcher;
22583     sto->sel = sel;
22584     sto->nbHistory = 0;
22585 
22586 #ifdef DEBUG_IDC
22587     xmlGenericError(xmlGenericErrorContext, "IDC:   STO push '%s'\n",
22588 	sto->sel->xpath);
22589 #endif
22590     return (0);
22591 }
22592 
22593 /**
22594  * xmlSchemaXPathEvaluate:
22595  * @vctxt: the WXS validation context
22596  * @nodeType: the nodeType of the current node
22597  *
22598  * Evaluates all active XPath state objects.
22599  *
22600  * Returns the number of IC "field" state objects which resolved to
22601  * this node, 0 if none resolved and -1 on internal errors.
22602  */
22603 static int
xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,xmlElementType nodeType)22604 xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
22605 		       xmlElementType nodeType)
22606 {
22607     xmlSchemaIDCStateObjPtr sto, head = NULL, first;
22608     int res, resolved = 0, depth = vctxt->depth;
22609 
22610     if (vctxt->xpathStates == NULL)
22611 	return (0);
22612 
22613     if (nodeType == XML_ATTRIBUTE_NODE)
22614 	depth++;
22615 #ifdef DEBUG_IDC
22616     {
22617 	xmlChar *str = NULL;
22618 	xmlGenericError(xmlGenericErrorContext,
22619 	    "IDC: EVAL on %s, depth %d, type %d\n",
22620 	    xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22621 		vctxt->inode->localName), depth, nodeType);
22622 	FREE_AND_NULL(str)
22623     }
22624 #endif
22625     /*
22626     * Process all active XPath state objects.
22627     */
22628     first = vctxt->xpathStates;
22629     sto = first;
22630     while (sto != head) {
22631 #ifdef DEBUG_IDC
22632 	if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
22633 	    xmlGenericError(xmlGenericErrorContext, "IDC:   ['%s'] selector '%s'\n",
22634 		sto->matcher->aidc->def->name, sto->sel->xpath);
22635 	else
22636 	    xmlGenericError(xmlGenericErrorContext, "IDC:   ['%s'] field '%s'\n",
22637 		sto->matcher->aidc->def->name, sto->sel->xpath);
22638 #endif
22639 	if (nodeType == XML_ELEMENT_NODE)
22640 	    res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
22641 		vctxt->inode->localName, vctxt->inode->nsName);
22642 	else
22643 	    res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
22644 		vctxt->inode->localName, vctxt->inode->nsName);
22645 
22646 	if (res == -1) {
22647 	    VERROR_INT("xmlSchemaXPathEvaluate",
22648 		"calling xmlStreamPush()");
22649 	    return (-1);
22650 	}
22651 	if (res == 0)
22652 	    goto next_sto;
22653 	/*
22654 	* Full match.
22655 	*/
22656 #ifdef DEBUG_IDC
22657 	xmlGenericError(xmlGenericErrorContext, "IDC:     "
22658 	    "MATCH\n");
22659 #endif
22660 	/*
22661 	* Register a match in the state object history.
22662 	*/
22663 	if (sto->history == NULL) {
22664 	    sto->history = (int *) xmlMalloc(5 * sizeof(int));
22665 	    if (sto->history == NULL) {
22666 		xmlSchemaVErrMemory(NULL,
22667 		    "allocating the state object history", NULL);
22668 		return(-1);
22669 	    }
22670 	    sto->sizeHistory = 5;
22671 	} else if (sto->sizeHistory <= sto->nbHistory) {
22672 	    sto->sizeHistory *= 2;
22673 	    sto->history = (int *) xmlRealloc(sto->history,
22674 		sto->sizeHistory * sizeof(int));
22675 	    if (sto->history == NULL) {
22676 		xmlSchemaVErrMemory(NULL,
22677 		    "re-allocating the state object history", NULL);
22678 		return(-1);
22679 	    }
22680 	}
22681 	sto->history[sto->nbHistory++] = depth;
22682 
22683 #ifdef DEBUG_IDC
22684 	xmlGenericError(xmlGenericErrorContext, "IDC:       push match '%d'\n",
22685 	    vctxt->depth);
22686 #endif
22687 
22688 	if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22689 	    xmlSchemaIDCSelectPtr sel;
22690 	    /*
22691 	    * Activate state objects for the IDC fields of
22692 	    * the IDC selector.
22693 	    */
22694 #ifdef DEBUG_IDC
22695 	    xmlGenericError(xmlGenericErrorContext, "IDC:     "
22696 		"activating field states\n");
22697 #endif
22698 	    sel = sto->matcher->aidc->def->fields;
22699 	    while (sel != NULL) {
22700 		if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
22701 		    sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
22702 		    return (-1);
22703 		sel = sel->next;
22704 	    }
22705 	} else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22706 	    /*
22707 	    * An IDC key node was found by the IDC field.
22708 	    */
22709 #ifdef DEBUG_IDC
22710 	    xmlGenericError(xmlGenericErrorContext,
22711 		"IDC:     key found\n");
22712 #endif
22713 	    /*
22714 	    * Notify that the character value of this node is
22715 	    * needed.
22716 	    */
22717 	    if (resolved == 0) {
22718 		if ((vctxt->inode->flags &
22719 		    XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
22720 		vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
22721 	    }
22722 	    resolved++;
22723 	}
22724 next_sto:
22725 	if (sto->next == NULL) {
22726 	    /*
22727 	    * Evaluate field state objects created on this node as well.
22728 	    */
22729 	    head = first;
22730 	    sto = vctxt->xpathStates;
22731 	} else
22732 	    sto = sto->next;
22733     }
22734     return (resolved);
22735 }
22736 
22737 static const xmlChar *
xmlSchemaFormatIDCKeySequence_1(xmlSchemaValidCtxtPtr vctxt,xmlChar ** buf,xmlSchemaPSVIIDCKeyPtr * seq,int count,int for_hash)22738 xmlSchemaFormatIDCKeySequence_1(xmlSchemaValidCtxtPtr vctxt,
22739 				xmlChar **buf,
22740 				xmlSchemaPSVIIDCKeyPtr *seq,
22741 				int count, int for_hash)
22742 {
22743     int i, res;
22744     xmlChar *value = NULL;
22745 
22746     *buf = xmlStrdup(BAD_CAST "[");
22747     for (i = 0; i < count; i++) {
22748 	*buf = xmlStrcat(*buf, BAD_CAST "'");
22749 	if (!for_hash)
22750 	    res = xmlSchemaGetCanonValueWhtspExt(seq[i]->val,
22751 		    xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type),
22752 		    &value);
22753 	else {
22754 	    res = xmlSchemaGetCanonValueHash(seq[i]->val, &value);
22755 	}
22756 	if (res == 0)
22757 	    *buf = xmlStrcat(*buf, BAD_CAST value);
22758 	else {
22759 	    VERROR_INT("xmlSchemaFormatIDCKeySequence",
22760 		"failed to compute a canonical value");
22761 	    *buf = xmlStrcat(*buf, BAD_CAST "???");
22762 	}
22763 	if (i < count -1)
22764 	    *buf = xmlStrcat(*buf, BAD_CAST "', ");
22765 	else
22766 	    *buf = xmlStrcat(*buf, BAD_CAST "'");
22767 	if (value != NULL) {
22768 	    xmlFree(value);
22769 	    value = NULL;
22770 	}
22771     }
22772     *buf = xmlStrcat(*buf, BAD_CAST "]");
22773 
22774     return (BAD_CAST *buf);
22775 }
22776 
22777 static const xmlChar *
xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,xmlChar ** buf,xmlSchemaPSVIIDCKeyPtr * seq,int count)22778 xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
22779 			      xmlChar **buf,
22780 			      xmlSchemaPSVIIDCKeyPtr *seq,
22781 			      int count)
22782 {
22783     return xmlSchemaFormatIDCKeySequence_1(vctxt, buf, seq, count, 0);
22784 }
22785 
22786 static const xmlChar *
xmlSchemaHashKeySequence(xmlSchemaValidCtxtPtr vctxt,xmlChar ** buf,xmlSchemaPSVIIDCKeyPtr * seq,int count)22787 xmlSchemaHashKeySequence(xmlSchemaValidCtxtPtr vctxt,
22788 			 xmlChar **buf,
22789 			 xmlSchemaPSVIIDCKeyPtr *seq,
22790 			 int count)
22791 {
22792     return xmlSchemaFormatIDCKeySequence_1(vctxt, buf, seq, count, 1);
22793 }
22794 
22795 /**
22796  * xmlSchemaXPathPop:
22797  * @vctxt: the WXS validation context
22798  *
22799  * Pops all XPath states.
22800  *
22801  * Returns 0 on success and -1 on internal errors.
22802  */
22803 static int
xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)22804 xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)
22805 {
22806     xmlSchemaIDCStateObjPtr sto;
22807     int res;
22808 
22809     if (vctxt->xpathStates == NULL)
22810 	return(0);
22811     sto = vctxt->xpathStates;
22812     do {
22813 	res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22814 	if (res == -1)
22815 	    return (-1);
22816 	sto = sto->next;
22817     } while (sto != NULL);
22818     return(0);
22819 }
22820 
22821 /**
22822  * xmlSchemaXPathProcessHistory:
22823  * @vctxt: the WXS validation context
22824  * @type: the simple/complex type of the current node if any at all
22825  * @val: the precompiled value
22826  *
22827  * Processes and pops the history items of the IDC state objects.
22828  * IDC key-sequences are validated/created on IDC bindings.
22829  *
22830  * Returns 0 on success and -1 on internal errors.
22831  */
22832 static int
xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,int depth)22833 xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
22834 			     int depth)
22835 {
22836     xmlSchemaIDCStateObjPtr sto, nextsto;
22837     int res, matchDepth;
22838     xmlSchemaPSVIIDCKeyPtr key = NULL;
22839     xmlSchemaTypePtr type = vctxt->inode->typeDef, simpleType = NULL;
22840 
22841     if (vctxt->xpathStates == NULL)
22842 	return (0);
22843     sto = vctxt->xpathStates;
22844 
22845 #ifdef DEBUG_IDC
22846     {
22847 	xmlChar *str = NULL;
22848 	xmlGenericError(xmlGenericErrorContext,
22849 	    "IDC: BACK on %s, depth %d\n",
22850 	    xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22851 		vctxt->inode->localName), vctxt->depth);
22852 	FREE_AND_NULL(str)
22853     }
22854 #endif
22855     /*
22856     * Evaluate the state objects.
22857     */
22858     while (sto != NULL) {
22859 	res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22860 	if (res == -1) {
22861 	    VERROR_INT("xmlSchemaXPathProcessHistory",
22862 		"calling xmlStreamPop()");
22863 	    return (-1);
22864 	}
22865 #ifdef DEBUG_IDC
22866 	xmlGenericError(xmlGenericErrorContext, "IDC:   stream pop '%s'\n",
22867 	    sto->sel->xpath);
22868 #endif
22869 	if (sto->nbHistory == 0)
22870 	    goto deregister_check;
22871 
22872 	matchDepth = sto->history[sto->nbHistory -1];
22873 
22874 	/*
22875 	* Only matches at the current depth are of interest.
22876 	*/
22877 	if (matchDepth != depth) {
22878 	    sto = sto->next;
22879 	    continue;
22880 	}
22881 	if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22882 	    /*
22883 	    * NOTE: According to
22884 	    *   http://www.w3.org/Bugs/Public/show_bug.cgi?id=2198
22885 	    *   ... the simple-content of complex types is also allowed.
22886 	    */
22887 
22888 	    if (WXS_IS_COMPLEX(type)) {
22889 		if (WXS_HAS_SIMPLE_CONTENT(type)) {
22890 		    /*
22891 		    * Sanity check for complex types with simple content.
22892 		    */
22893 		    simpleType = type->contentTypeDef;
22894 		    if (simpleType == NULL) {
22895 			VERROR_INT("xmlSchemaXPathProcessHistory",
22896 			    "field resolves to a CT with simple content "
22897 			    "but the CT is missing the ST definition");
22898 			return (-1);
22899 		    }
22900 		} else
22901 		    simpleType = NULL;
22902 	    } else
22903 		simpleType = type;
22904 	    if (simpleType == NULL) {
22905 		xmlChar *str = NULL;
22906 
22907 		/*
22908 		* Not qualified if the field resolves to a node of non
22909 		* simple type.
22910 		*/
22911 		xmlSchemaCustomErr(ACTXT_CAST vctxt,
22912 		    XML_SCHEMAV_CVC_IDC, NULL,
22913 		    WXS_BASIC_CAST sto->matcher->aidc->def,
22914 		    "The XPath '%s' of a field of %s does evaluate to a node of "
22915 		    "non-simple type",
22916 		    sto->sel->xpath,
22917 		    xmlSchemaGetIDCDesignation(&str, sto->matcher->aidc->def));
22918 		FREE_AND_NULL(str);
22919 		sto->nbHistory--;
22920 		goto deregister_check;
22921 	    }
22922 
22923 	    if ((key == NULL) && (vctxt->inode->val == NULL)) {
22924 		/*
22925 		* Failed to provide the normalized value; maybe
22926 		* the value was invalid.
22927 		*/
22928 		VERROR(XML_SCHEMAV_CVC_IDC,
22929 		    WXS_BASIC_CAST sto->matcher->aidc->def,
22930 		    "Warning: No precomputed value available, the value "
22931 		    "was either invalid or something strange happened");
22932 		sto->nbHistory--;
22933 		goto deregister_check;
22934 	    } else {
22935 		xmlSchemaIDCMatcherPtr matcher = sto->matcher;
22936 		xmlSchemaPSVIIDCKeyPtr *keySeq;
22937 		int pos, idx;
22938 
22939 		/*
22940 		* The key will be anchored on the matcher's list of
22941 		* key-sequences. The position in this list is determined
22942 		* by the target node's depth relative to the matcher's
22943 		* depth of creation (i.e. the depth of the scope element).
22944 		*
22945 		* Element        Depth    Pos   List-entries
22946 		* <scope>          0              NULL
22947 		*   <bar>          1              NULL
22948 		*     <target/>    2       2      target
22949 		*   <bar>
22950                 * </scope>
22951 		*
22952 		* The size of the list is only dependent on the depth of
22953 		* the tree.
22954 		* An entry will be NULLed in selector_leave, i.e. when
22955 		* we hit the target's
22956 		*/
22957 		pos = sto->depth - matcher->depth;
22958 		idx = sto->sel->index;
22959 
22960 		/*
22961 		* Create/grow the array of key-sequences.
22962 		*/
22963 		if (matcher->keySeqs == NULL) {
22964 		    if (pos > 9)
22965 			matcher->sizeKeySeqs = pos * 2;
22966 		    else
22967 			matcher->sizeKeySeqs = 10;
22968 		    matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22969 			xmlMalloc(matcher->sizeKeySeqs *
22970 			sizeof(xmlSchemaPSVIIDCKeyPtr *));
22971 		    if (matcher->keySeqs == NULL) {
22972 			xmlSchemaVErrMemory(NULL,
22973 			    "allocating an array of key-sequences",
22974 			    NULL);
22975 			return(-1);
22976 		    }
22977 		    memset(matcher->keySeqs, 0,
22978 			matcher->sizeKeySeqs *
22979 			sizeof(xmlSchemaPSVIIDCKeyPtr *));
22980 		} else if (pos >= matcher->sizeKeySeqs) {
22981 		    int i = matcher->sizeKeySeqs;
22982 
22983 		    matcher->sizeKeySeqs *= 2;
22984 		    matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22985 			xmlRealloc(matcher->keySeqs,
22986 			matcher->sizeKeySeqs *
22987 			sizeof(xmlSchemaPSVIIDCKeyPtr *));
22988 		    if (matcher->keySeqs == NULL) {
22989 			xmlSchemaVErrMemory(NULL,
22990 			    "reallocating an array of key-sequences",
22991 			    NULL);
22992 			return (-1);
22993 		    }
22994 		    /*
22995 		    * The array needs to be NULLed.
22996 		    * TODO: Use memset?
22997 		    */
22998 		    for (; i < matcher->sizeKeySeqs; i++)
22999 			matcher->keySeqs[i] = NULL;
23000 		}
23001 
23002 		/*
23003 		* Get/create the key-sequence.
23004 		*/
23005 		keySeq = matcher->keySeqs[pos];
23006 		if (keySeq == NULL) {
23007 		    goto create_sequence;
23008 		} else if (keySeq[idx] != NULL) {
23009 		    xmlChar *str = NULL;
23010 		    /*
23011 		    * cvc-identity-constraint:
23012 		    * 3 For each node in the `target node set` all
23013 		    * of the {fields}, with that node as the context
23014 		    * node, evaluate to either an empty node-set or
23015 		    * a node-set with exactly one member, which must
23016 		    * have a simple type.
23017 		    *
23018 		    * The key was already set; report an error.
23019 		    */
23020 		    xmlSchemaCustomErr(ACTXT_CAST vctxt,
23021 			XML_SCHEMAV_CVC_IDC, NULL,
23022 			WXS_BASIC_CAST matcher->aidc->def,
23023 			"The XPath '%s' of a field of %s evaluates to a "
23024 			"node-set with more than one member",
23025 			sto->sel->xpath,
23026 			xmlSchemaGetIDCDesignation(&str, matcher->aidc->def));
23027 		    FREE_AND_NULL(str);
23028 		    sto->nbHistory--;
23029 		    goto deregister_check;
23030 		} else
23031 		    goto create_key;
23032 
23033 create_sequence:
23034 		/*
23035 		* Create a key-sequence.
23036 		*/
23037 		keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
23038 		    matcher->aidc->def->nbFields *
23039 		    sizeof(xmlSchemaPSVIIDCKeyPtr));
23040 		if (keySeq == NULL) {
23041 		    xmlSchemaVErrMemory(NULL,
23042 			"allocating an IDC key-sequence", NULL);
23043 		    return(-1);
23044 		}
23045 		memset(keySeq, 0, matcher->aidc->def->nbFields *
23046 		    sizeof(xmlSchemaPSVIIDCKeyPtr));
23047 		matcher->keySeqs[pos] = keySeq;
23048 create_key:
23049 		/*
23050 		* Create a key once per node only.
23051 		*/
23052 		if (key == NULL) {
23053 		    key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
23054 			sizeof(xmlSchemaPSVIIDCKey));
23055 		    if (key == NULL) {
23056 			xmlSchemaVErrMemory(NULL,
23057 			    "allocating a IDC key", NULL);
23058 			xmlFree(keySeq);
23059 			matcher->keySeqs[pos] = NULL;
23060 			return(-1);
23061 		    }
23062 		    /*
23063 		    * Consume the compiled value.
23064 		    */
23065 		    key->type = simpleType;
23066 		    key->val = vctxt->inode->val;
23067 		    vctxt->inode->val = NULL;
23068 		    /*
23069 		    * Store the key in a global list.
23070 		    */
23071 		    if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
23072 			xmlSchemaIDCFreeKey(key);
23073 			return (-1);
23074 		    }
23075 		}
23076 		keySeq[idx] = key;
23077 	    }
23078 	} else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
23079 
23080 	    xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
23081 	    /* xmlSchemaPSVIIDCBindingPtr bind; */
23082 	    xmlSchemaPSVIIDCNodePtr ntItem;
23083 	    xmlSchemaIDCMatcherPtr matcher;
23084 	    xmlSchemaIDCPtr idc;
23085 	    xmlSchemaItemListPtr targets;
23086 	    int pos, i, j, nbKeys;
23087 	    /*
23088 	    * Here we have the following scenario:
23089 	    * An IDC 'selector' state object resolved to a target node,
23090 	    * during the time this target node was in the
23091 	    * ancestor-or-self axis, the 'field' state object(s) looked
23092 	    * out for matching nodes to create a key-sequence for this
23093 	    * target node. Now we are back to this target node and need
23094 	    * to put the key-sequence, together with the target node
23095 	    * itself, into the node-table of the corresponding IDC
23096 	    * binding.
23097 	    */
23098 	    matcher = sto->matcher;
23099 	    idc = matcher->aidc->def;
23100 	    nbKeys = idc->nbFields;
23101 	    pos = depth - matcher->depth;
23102 	    /*
23103 	    * Check if the matcher has any key-sequences at all, plus
23104 	    * if it has a key-sequence for the current target node.
23105 	    */
23106 	    if ((matcher->keySeqs == NULL) ||
23107 		(matcher->sizeKeySeqs <= pos)) {
23108 		if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
23109 		    goto selector_key_error;
23110 		else
23111 		    goto selector_leave;
23112 	    }
23113 
23114 	    keySeq = &(matcher->keySeqs[pos]);
23115 	    if (*keySeq == NULL) {
23116 		if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
23117 		    goto selector_key_error;
23118 		else
23119 		    goto selector_leave;
23120 	    }
23121 
23122 	    for (i = 0; i < nbKeys; i++) {
23123 		if ((*keySeq)[i] == NULL) {
23124 		    /*
23125 		    * Not qualified, if not all fields did resolve.
23126 		    */
23127 		    if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
23128 			/*
23129 			* All fields of a "key" IDC must resolve.
23130 			*/
23131 			goto selector_key_error;
23132 		    }
23133 		    goto selector_leave;
23134 		}
23135 	    }
23136 	    /*
23137 	    * All fields did resolve.
23138 	    */
23139 
23140 	    /*
23141 	    * 4.1 If the {identity-constraint category} is unique(/key),
23142 	    * then no two members of the `qualified node set` have
23143 	    * `key-sequences` whose members are pairwise equal, as
23144 	    * defined by Equal in [XML Schemas: Datatypes].
23145 	    *
23146 	    * Get the IDC binding from the matcher and check for
23147 	    * duplicate key-sequences.
23148 	    */
23149 #if 0
23150 	    bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
23151 #endif
23152 	    targets = xmlSchemaIDCAcquireTargetList(vctxt, matcher);
23153 	    if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
23154 		(targets->nbItems != 0)) {
23155 		xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
23156 		xmlIDCHashEntryPtr e;
23157 
23158 		res = 0;
23159 
23160 		if (!matcher->htab)
23161 		    e = NULL;
23162 		else {
23163 		    xmlChar *value = NULL;
23164 		    xmlSchemaHashKeySequence(vctxt, &value, *keySeq, nbKeys);
23165 		    e = xmlHashLookup(matcher->htab, value);
23166 		    FREE_AND_NULL(value);
23167 		}
23168 
23169 		/*
23170 		* Compare the key-sequences, key by key.
23171 		*/
23172 		for (;e; e = e->next) {
23173 		    bkeySeq =
23174 			((xmlSchemaPSVIIDCNodePtr) targets->items[e->index])->keys;
23175 		    for (j = 0; j < nbKeys; j++) {
23176 			ckey = (*keySeq)[j];
23177 			bkey = bkeySeq[j];
23178 			res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
23179 			if (res == -1) {
23180 			    return (-1);
23181 			} else if (res == 0) {
23182 			    /*
23183 			    * One of the keys differs, so the key-sequence
23184 			    * won't be equal; get out.
23185 			    */
23186 			    break;
23187 			}
23188 		    }
23189 		    if (res == 1) {
23190 			/*
23191 			* Duplicate key-sequence found.
23192 			*/
23193 			break;
23194 		    }
23195 		}
23196 		if (e) {
23197 		    xmlChar *str = NULL, *strB = NULL;
23198 		    /*
23199 		    * TODO: Try to report the key-sequence.
23200 		    */
23201 		    xmlSchemaCustomErr(ACTXT_CAST vctxt,
23202 			XML_SCHEMAV_CVC_IDC, NULL,
23203 			WXS_BASIC_CAST idc,
23204 			"Duplicate key-sequence %s in %s",
23205 			xmlSchemaFormatIDCKeySequence(vctxt, &str,
23206 			    (*keySeq), nbKeys),
23207 			xmlSchemaGetIDCDesignation(&strB, idc));
23208 		    FREE_AND_NULL(str);
23209 		    FREE_AND_NULL(strB);
23210 		    goto selector_leave;
23211 		}
23212 	    }
23213 	    /*
23214 	    * Add a node-table item to the IDC binding.
23215 	    */
23216 	    ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
23217 		sizeof(xmlSchemaPSVIIDCNode));
23218 	    if (ntItem == NULL) {
23219 		xmlSchemaVErrMemory(NULL,
23220 		    "allocating an IDC node-table item", NULL);
23221 		xmlFree(*keySeq);
23222 		*keySeq = NULL;
23223 		return(-1);
23224 	    }
23225 	    memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
23226 
23227 	    /*
23228 	    * Store the node-table item in a global list.
23229 	    */
23230 	    if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
23231 		if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
23232 		    xmlFree(ntItem);
23233 		    xmlFree(*keySeq);
23234 		    *keySeq = NULL;
23235 		    return (-1);
23236 		}
23237 		ntItem->nodeQNameID = -1;
23238 	    } else {
23239 		/*
23240 		* Save a cached QName for this node on the IDC node, to be
23241 		* able to report it, even if the node is not saved.
23242 		*/
23243 		ntItem->nodeQNameID = xmlSchemaVAddNodeQName(vctxt,
23244 		    vctxt->inode->localName, vctxt->inode->nsName);
23245 		if (ntItem->nodeQNameID == -1) {
23246 		    xmlFree(ntItem);
23247 		    xmlFree(*keySeq);
23248 		    *keySeq = NULL;
23249 		    return (-1);
23250 		}
23251 	    }
23252 	    /*
23253 	    * Init the node-table item: Save the node, position and
23254 	    * consume the key-sequence.
23255 	    */
23256 	    ntItem->node = vctxt->node;
23257 	    ntItem->nodeLine = vctxt->inode->nodeLine;
23258 	    ntItem->keys = *keySeq;
23259 	    *keySeq = NULL;
23260 #if 0
23261 	    if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1)
23262 #endif
23263 	    if (xmlSchemaItemListAdd(targets, ntItem) == -1) {
23264 		if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23265 		    /*
23266 		    * Free the item, since keyref items won't be
23267 		    * put on a global list.
23268 		    */
23269 		    xmlFree(ntItem->keys);
23270 		    xmlFree(ntItem);
23271 		}
23272 		return (-1);
23273 	    }
23274 	    if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
23275 		xmlChar *value = NULL;
23276 		xmlIDCHashEntryPtr r, e;
23277 		if (!matcher->htab)
23278 		  matcher->htab = xmlHashCreate(4);
23279 		xmlSchemaHashKeySequence(vctxt, &value, ntItem->keys, nbKeys);
23280 		e = xmlMalloc(sizeof *e);
23281 		e->index = targets->nbItems - 1;
23282 		r = xmlHashLookup(matcher->htab, value);
23283 		if (r) {
23284 		    e->next = r->next;
23285 		    r->next = e;
23286 		} else {
23287 		    e->next = NULL;
23288 		    xmlHashAddEntry(matcher->htab, value, e);
23289 		}
23290 		FREE_AND_NULL(value);
23291 	    }
23292 
23293 	    goto selector_leave;
23294 selector_key_error:
23295 	    {
23296 		xmlChar *str = NULL;
23297 		/*
23298 		* 4.2.1 (KEY) The `target node set` and the
23299 		* `qualified node set` are equal, that is, every
23300 		* member of the `target node set` is also a member
23301 		* of the `qualified node set` and vice versa.
23302 		*/
23303 		xmlSchemaCustomErr(ACTXT_CAST vctxt,
23304 		    XML_SCHEMAV_CVC_IDC, NULL,
23305 		    WXS_BASIC_CAST idc,
23306 		    "Not all fields of %s evaluate to a node",
23307 		    xmlSchemaGetIDCDesignation(&str, idc), NULL);
23308 		FREE_AND_NULL(str);
23309 	    }
23310 selector_leave:
23311 	    /*
23312 	    * Free the key-sequence if not added to the IDC table.
23313 	    */
23314 	    if ((keySeq != NULL) && (*keySeq != NULL)) {
23315 		xmlFree(*keySeq);
23316 		*keySeq = NULL;
23317 	    }
23318 	} /* if selector */
23319 
23320 	sto->nbHistory--;
23321 
23322 deregister_check:
23323 	/*
23324 	* Deregister state objects if they reach the depth of creation.
23325 	*/
23326 	if ((sto->nbHistory == 0) && (sto->depth == depth)) {
23327 #ifdef DEBUG_IDC
23328 	    xmlGenericError(xmlGenericErrorContext, "IDC:   STO pop '%s'\n",
23329 		sto->sel->xpath);
23330 #endif
23331 	    if (vctxt->xpathStates != sto) {
23332 		VERROR_INT("xmlSchemaXPathProcessHistory",
23333 		    "The state object to be removed is not the first "
23334 		    "in the list");
23335 	    }
23336 	    nextsto = sto->next;
23337 	    /*
23338 	    * Unlink from the list of active XPath state objects.
23339 	    */
23340 	    vctxt->xpathStates = sto->next;
23341 	    sto->next = vctxt->xpathStatePool;
23342 	    /*
23343 	    * Link it to the pool of reusable state objects.
23344 	    */
23345 	    vctxt->xpathStatePool = sto;
23346 	    sto = nextsto;
23347 	} else
23348 	    sto = sto->next;
23349     } /* while (sto != NULL) */
23350     return (0);
23351 }
23352 
23353 /**
23354  * xmlSchemaIDCRegisterMatchers:
23355  * @vctxt: the WXS validation context
23356  * @elemDecl: the element declaration
23357  *
23358  * Creates helper objects to evaluate IDC selectors/fields
23359  * successively.
23360  *
23361  * Returns 0 if OK and -1 on internal errors.
23362  */
23363 static int
xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,xmlSchemaElementPtr elemDecl)23364 xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
23365 			     xmlSchemaElementPtr elemDecl)
23366 {
23367     xmlSchemaIDCMatcherPtr matcher, last = NULL;
23368     xmlSchemaIDCPtr idc, refIdc;
23369     xmlSchemaIDCAugPtr aidc;
23370 
23371     idc = (xmlSchemaIDCPtr) elemDecl->idcs;
23372     if (idc == NULL)
23373 	return (0);
23374 
23375 #ifdef DEBUG_IDC
23376     {
23377 	xmlChar *str = NULL;
23378 	xmlGenericError(xmlGenericErrorContext,
23379 	    "IDC: REGISTER on %s, depth %d\n",
23380 	    (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
23381 		vctxt->inode->localName), vctxt->depth);
23382 	FREE_AND_NULL(str)
23383     }
23384 #endif
23385     if (vctxt->inode->idcMatchers != NULL) {
23386 	VERROR_INT("xmlSchemaIDCRegisterMatchers",
23387 	    "The chain of IDC matchers is expected to be empty");
23388 	return (-1);
23389     }
23390     do {
23391 	if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23392 	    /*
23393 	    * Since IDCs bubbles are expensive we need to know the
23394 	    * depth at which the bubbles should stop; this will be
23395 	    * the depth of the top-most keyref IDC. If no keyref
23396 	    * references a key/unique IDC, the keyrefDepth will
23397 	    * be -1, indicating that no bubbles are needed.
23398 	    */
23399 	    refIdc = (xmlSchemaIDCPtr) idc->ref->item;
23400 	    if (refIdc != NULL) {
23401 		/*
23402 		* Remember that we have keyrefs on this node.
23403 		*/
23404 		vctxt->inode->hasKeyrefs = 1;
23405 		/*
23406 		* Lookup the referenced augmented IDC info.
23407 		*/
23408 		aidc = vctxt->aidcs;
23409 		while (aidc != NULL) {
23410 		    if (aidc->def == refIdc)
23411 			break;
23412 		    aidc = aidc->next;
23413 		}
23414 		if (aidc == NULL) {
23415 		    VERROR_INT("xmlSchemaIDCRegisterMatchers",
23416 			"Could not find an augmented IDC item for an IDC "
23417 			"definition");
23418 		    return (-1);
23419 		}
23420 		if ((aidc->keyrefDepth == -1) ||
23421 		    (vctxt->depth < aidc->keyrefDepth))
23422 		    aidc->keyrefDepth = vctxt->depth;
23423 	    }
23424 	}
23425 	/*
23426 	* Lookup the augmented IDC item for the IDC definition.
23427 	*/
23428 	aidc = vctxt->aidcs;
23429 	while (aidc != NULL) {
23430 	    if (aidc->def == idc)
23431 		break;
23432 	    aidc = aidc->next;
23433 	}
23434 	if (aidc == NULL) {
23435 	    VERROR_INT("xmlSchemaIDCRegisterMatchers",
23436 		"Could not find an augmented IDC item for an IDC definition");
23437 	    return (-1);
23438 	}
23439 	/*
23440 	* Create an IDC matcher for every IDC definition.
23441 	*/
23442 	if (vctxt->idcMatcherCache != NULL) {
23443 	    /*
23444 	    * Reuse a cached matcher.
23445 	    */
23446 	    matcher = vctxt->idcMatcherCache;
23447 	    vctxt->idcMatcherCache = matcher->nextCached;
23448 	    matcher->nextCached = NULL;
23449 	} else {
23450 	    matcher = (xmlSchemaIDCMatcherPtr)
23451 		xmlMalloc(sizeof(xmlSchemaIDCMatcher));
23452 	    if (matcher == NULL) {
23453 		xmlSchemaVErrMemory(vctxt,
23454 		    "allocating an IDC matcher", NULL);
23455 		return (-1);
23456 	    }
23457 	    memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
23458 	}
23459 	if (last == NULL)
23460 	    vctxt->inode->idcMatchers = matcher;
23461 	else
23462 	    last->next = matcher;
23463 	last = matcher;
23464 
23465 	matcher->type = IDC_MATCHER;
23466 	matcher->depth = vctxt->depth;
23467 	matcher->aidc = aidc;
23468 	matcher->idcType = aidc->def->type;
23469 #ifdef DEBUG_IDC
23470 	xmlGenericError(xmlGenericErrorContext, "IDC:   register matcher\n");
23471 #endif
23472 	/*
23473 	* Init the automaton state object.
23474 	*/
23475 	if (xmlSchemaIDCAddStateObject(vctxt, matcher,
23476 	    idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
23477 	    return (-1);
23478 
23479 	idc = idc->next;
23480     } while (idc != NULL);
23481     return (0);
23482 }
23483 
23484 static int
xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,xmlSchemaNodeInfoPtr ielem)23485 xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,
23486 			   xmlSchemaNodeInfoPtr ielem)
23487 {
23488     xmlSchemaPSVIIDCBindingPtr bind;
23489     int res, i, j, k, nbTargets, nbFields, nbDupls, nbNodeTable;
23490     xmlSchemaPSVIIDCKeyPtr *keys, *ntkeys;
23491     xmlSchemaPSVIIDCNodePtr *targets, *dupls;
23492 
23493     xmlSchemaIDCMatcherPtr matcher = ielem->idcMatchers;
23494     /* vctxt->createIDCNodeTables */
23495     while (matcher != NULL) {
23496 	/*
23497 	* Skip keyref IDCs and empty IDC target-lists.
23498 	*/
23499 	if ((matcher->aidc->def->type == XML_SCHEMA_TYPE_IDC_KEYREF) ||
23500 	    WXS_ILIST_IS_EMPTY(matcher->targets))
23501 	{
23502 	    matcher = matcher->next;
23503 	    continue;
23504 	}
23505 	/*
23506 	* If we _want_ the IDC node-table to be created in any case
23507 	* then do so. Otherwise create them only if keyrefs need them.
23508 	*/
23509 	if ((! vctxt->createIDCNodeTables) &&
23510 	    ((matcher->aidc->keyrefDepth == -1) ||
23511 	     (matcher->aidc->keyrefDepth > vctxt->depth)))
23512 	{
23513 	    matcher = matcher->next;
23514 	    continue;
23515 	}
23516 	/*
23517 	* Get/create the IDC binding on this element for the IDC definition.
23518 	*/
23519 	bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
23520 	if (bind == NULL)
23521 	   goto internal_error;
23522 
23523 	if (! WXS_ILIST_IS_EMPTY(bind->dupls)) {
23524 	    dupls = (xmlSchemaPSVIIDCNodePtr *) bind->dupls->items;
23525 	    nbDupls = bind->dupls->nbItems;
23526 	} else {
23527 	    dupls = NULL;
23528 	    nbDupls = 0;
23529 	}
23530 	if (bind->nodeTable != NULL) {
23531 	    nbNodeTable = bind->nbNodes;
23532 	} else {
23533 	    nbNodeTable = 0;
23534 	}
23535 
23536 	if ((nbNodeTable == 0) && (nbDupls == 0)) {
23537 	    /*
23538 	    * Transfer all IDC target-nodes to the IDC node-table.
23539 	    */
23540 	    bind->nodeTable =
23541 		(xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23542 	    bind->sizeNodes = matcher->targets->sizeItems;
23543 	    bind->nbNodes = matcher->targets->nbItems;
23544 
23545 	    matcher->targets->items = NULL;
23546 	    matcher->targets->sizeItems = 0;
23547 	    matcher->targets->nbItems = 0;
23548 	    if (matcher->htab) {
23549 		xmlHashFree(matcher->htab, xmlFreeIDCHashEntry);
23550 		matcher->htab = NULL;
23551 	    }
23552 	} else {
23553 	    /*
23554 	    * Compare the key-sequences and add to the IDC node-table.
23555 	    */
23556 	    nbTargets = matcher->targets->nbItems;
23557 	    targets = (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23558 	    nbFields = matcher->aidc->def->nbFields;
23559 	    i = 0;
23560 	    do {
23561 		keys = targets[i]->keys;
23562 		if (nbDupls) {
23563 		    /*
23564 		    * Search in already found duplicates first.
23565 		    */
23566 		    j = 0;
23567 		    do {
23568 			if (nbFields == 1) {
23569 			    res = xmlSchemaAreValuesEqual(keys[0]->val,
23570 				dupls[j]->keys[0]->val);
23571 			    if (res == -1)
23572 				goto internal_error;
23573 			    if (res == 1) {
23574 				/*
23575 				* Equal key-sequence.
23576 				*/
23577 				goto next_target;
23578 			    }
23579 			} else {
23580 			    res = 0;
23581 			    ntkeys = dupls[j]->keys;
23582 			    for (k = 0; k < nbFields; k++) {
23583 				res = xmlSchemaAreValuesEqual(keys[k]->val,
23584 				    ntkeys[k]->val);
23585 				if (res == -1)
23586 				    goto internal_error;
23587 				if (res == 0) {
23588 				    /*
23589 				    * One of the keys differs.
23590 				    */
23591 				    break;
23592 				}
23593 			    }
23594 			    if (res == 1) {
23595 				/*
23596 				* Equal key-sequence found.
23597 				*/
23598 				goto next_target;
23599 			    }
23600 			}
23601 			j++;
23602 		    } while (j < nbDupls);
23603 		}
23604 		if (nbNodeTable) {
23605 		    j = 0;
23606 		    do {
23607 			if (nbFields == 1) {
23608 			    res = xmlSchemaAreValuesEqual(keys[0]->val,
23609 				bind->nodeTable[j]->keys[0]->val);
23610 			    if (res == -1)
23611 				goto internal_error;
23612 			    if (res == 0) {
23613 				/*
23614 				* The key-sequence differs.
23615 				*/
23616 				goto next_node_table_entry;
23617 			    }
23618 			} else {
23619 			    res = 0;
23620 			    ntkeys = bind->nodeTable[j]->keys;
23621 			    for (k = 0; k < nbFields; k++) {
23622 				res = xmlSchemaAreValuesEqual(keys[k]->val,
23623 				    ntkeys[k]->val);
23624 				if (res == -1)
23625 				    goto internal_error;
23626 				if (res == 0) {
23627 				    /*
23628 				    * One of the keys differs.
23629 				    */
23630 				    goto next_node_table_entry;
23631 				}
23632 			    }
23633 			}
23634 			/*
23635 			* Add the duplicate to the list of duplicates.
23636 			*/
23637 			if (bind->dupls == NULL) {
23638 			    bind->dupls = xmlSchemaItemListCreate();
23639 			    if (bind->dupls == NULL)
23640 				goto internal_error;
23641 			}
23642 			if (xmlSchemaItemListAdd(bind->dupls, bind->nodeTable[j]) == -1)
23643 			    goto internal_error;
23644 			/*
23645 			* Remove the duplicate entry from the IDC node-table.
23646 			*/
23647 			bind->nodeTable[j] = bind->nodeTable[bind->nbNodes -1];
23648 			bind->nbNodes--;
23649 
23650 			goto next_target;
23651 
23652 next_node_table_entry:
23653 			j++;
23654 		    } while (j < nbNodeTable);
23655 		}
23656 		/*
23657 		* If everything is fine, then add the IDC target-node to
23658 		* the IDC node-table.
23659 		*/
23660 		if (xmlSchemaIDCAppendNodeTableItem(bind, targets[i]) == -1)
23661 		    goto internal_error;
23662 
23663 next_target:
23664 		i++;
23665 	    } while (i < nbTargets);
23666 	}
23667 	matcher = matcher->next;
23668     }
23669     return(0);
23670 
23671 internal_error:
23672     return(-1);
23673 }
23674 
23675 /**
23676  * xmlSchemaBubbleIDCNodeTables:
23677  * @depth: the current tree depth
23678  *
23679  * Merges IDC bindings of an element at @depth into the corresponding IDC
23680  * bindings of its parent element. If a duplicate note-table entry is found,
23681  * both, the parent node-table entry and child entry are discarded from the
23682  * node-table of the parent.
23683  *
23684  * Returns 0 if OK and -1 on internal errors.
23685  */
23686 static int
xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)23687 xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
23688 {
23689     xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
23690     xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL; /* parent IDC bindings. */
23691     xmlSchemaPSVIIDCNodePtr node, parNode = NULL, *dupls, *parNodes; /* node-table entries. */
23692     xmlSchemaIDCAugPtr aidc;
23693     int i, j, k, ret = 0, nbFields, oldNum, oldDupls;
23694 
23695     bind = vctxt->inode->idcTable;
23696     if (bind == NULL) {
23697 	/* Fine, no table, no bubbles. */
23698 	return (0);
23699     }
23700 
23701     parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
23702     /*
23703     * Walk all bindings; create new or add to existing bindings.
23704     * Remove duplicate key-sequences.
23705     */
23706     while (bind != NULL) {
23707 
23708 	if ((bind->nbNodes == 0) && WXS_ILIST_IS_EMPTY(bind->dupls))
23709 	    goto next_binding;
23710 	/*
23711 	* Check if the key/unique IDC table needs to be bubbled.
23712 	*/
23713 	if (! vctxt->createIDCNodeTables) {
23714 	    aidc = vctxt->aidcs;
23715 	    do {
23716 		if (aidc->def == bind->definition) {
23717 		    if ((aidc->keyrefDepth == -1) ||
23718 			(aidc->keyrefDepth >= vctxt->depth)) {
23719 			goto next_binding;
23720 		    }
23721 		    break;
23722 		}
23723 		aidc = aidc->next;
23724 	    } while (aidc != NULL);
23725 	}
23726 
23727 	if (parTable != NULL)
23728 	    parBind = *parTable;
23729 	/*
23730 	* Search a matching parent binding for the
23731 	* IDC definition.
23732 	*/
23733 	while (parBind != NULL) {
23734 	    if (parBind->definition == bind->definition)
23735 		break;
23736 	    parBind = parBind->next;
23737 	}
23738 
23739 	if (parBind != NULL) {
23740 	    /*
23741 	    * Compare every node-table entry of the child node,
23742 	    * i.e. the key-sequence within, ...
23743 	    */
23744 	    oldNum = parBind->nbNodes; /* Skip newly added items. */
23745 
23746 	    if (! WXS_ILIST_IS_EMPTY(parBind->dupls)) {
23747 		oldDupls = parBind->dupls->nbItems;
23748 		dupls = (xmlSchemaPSVIIDCNodePtr *) parBind->dupls->items;
23749 	    } else {
23750 		dupls = NULL;
23751 		oldDupls = 0;
23752 	    }
23753 
23754 	    parNodes = parBind->nodeTable;
23755 	    nbFields = bind->definition->nbFields;
23756 
23757 	    for (i = 0; i < bind->nbNodes; i++) {
23758 		node = bind->nodeTable[i];
23759 		if (node == NULL)
23760 		    continue;
23761 		/*
23762 		* ...with every key-sequence of the parent node, already
23763 		* evaluated to be a duplicate key-sequence.
23764 		*/
23765 		if (oldDupls) {
23766 		    j = 0;
23767 		    while (j < oldDupls) {
23768 			if (nbFields == 1) {
23769 			    ret = xmlSchemaAreValuesEqual(
23770 				node->keys[0]->val,
23771 				dupls[j]->keys[0]->val);
23772 			    if (ret == -1)
23773 				goto internal_error;
23774 			    if (ret == 0) {
23775 				j++;
23776 				continue;
23777 			    }
23778 			} else {
23779 			    parNode = dupls[j];
23780 			    for (k = 0; k < nbFields; k++) {
23781 				ret = xmlSchemaAreValuesEqual(
23782 				    node->keys[k]->val,
23783 				    parNode->keys[k]->val);
23784 				if (ret == -1)
23785 				    goto internal_error;
23786 				if (ret == 0)
23787 				    break;
23788 			    }
23789 			}
23790 			if (ret == 1)
23791 			    /* Duplicate found. */
23792 			    break;
23793 			j++;
23794 		    }
23795 		    if (j != oldDupls) {
23796 			/* Duplicate found. Skip this entry. */
23797 			continue;
23798 		    }
23799 		}
23800 		/*
23801 		* ... and with every key-sequence of the parent node.
23802 		*/
23803 		if (oldNum) {
23804 		    j = 0;
23805 		    while (j < oldNum) {
23806 			parNode = parNodes[j];
23807 			if (nbFields == 1) {
23808 			    ret = xmlSchemaAreValuesEqual(
23809 				node->keys[0]->val,
23810 				parNode->keys[0]->val);
23811 			    if (ret == -1)
23812 				goto internal_error;
23813 			    if (ret == 0) {
23814 				j++;
23815 				continue;
23816 			    }
23817 			} else {
23818 			    for (k = 0; k < nbFields; k++) {
23819 				ret = xmlSchemaAreValuesEqual(
23820 				    node->keys[k]->val,
23821 				    parNode->keys[k]->val);
23822 				if (ret == -1)
23823 				    goto internal_error;
23824 				if (ret == 0)
23825 				    break;
23826 			    }
23827 			}
23828 			if (ret == 1)
23829 			    /* Duplicate found. */
23830 			    break;
23831 			j++;
23832 		    }
23833 		    if (j != oldNum) {
23834 			/*
23835 			* Handle duplicates. Move the duplicate in
23836 			* the parent's node-table to the list of
23837 			* duplicates.
23838 			*/
23839 			oldNum--;
23840 			parBind->nbNodes--;
23841 			/*
23842 			* Move last old item to pos of duplicate.
23843 			*/
23844 			parNodes[j] = parNodes[oldNum];
23845 
23846 			if (parBind->nbNodes != oldNum) {
23847 			    /*
23848 			    * If new items exist, move last new item to
23849 			    * last of old items.
23850 			    */
23851 			    parNodes[oldNum] =
23852 				parNodes[parBind->nbNodes];
23853 			}
23854 			if (parBind->dupls == NULL) {
23855 			    parBind->dupls = xmlSchemaItemListCreate();
23856 			    if (parBind->dupls == NULL)
23857 				goto internal_error;
23858 			}
23859 			xmlSchemaItemListAdd(parBind->dupls, parNode);
23860 		    } else {
23861 			/*
23862 			* Add the node-table entry (node and key-sequence) of
23863 			* the child node to the node table of the parent node.
23864 			*/
23865 			if (parBind->nodeTable == NULL) {
23866 			    parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23867 				xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
23868 			    if (parBind->nodeTable == NULL) {
23869 				xmlSchemaVErrMemory(NULL,
23870 				    "allocating IDC list of node-table items", NULL);
23871 				goto internal_error;
23872 			    }
23873 			    parBind->sizeNodes = 1;
23874 			} else if (parBind->nbNodes >= parBind->sizeNodes) {
23875 			    parBind->sizeNodes *= 2;
23876 			    parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23877 				xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
23878 				sizeof(xmlSchemaPSVIIDCNodePtr));
23879 			    if (parBind->nodeTable == NULL) {
23880 				xmlSchemaVErrMemory(NULL,
23881 				    "re-allocating IDC list of node-table items", NULL);
23882 				goto internal_error;
23883 			    }
23884 			}
23885 			parNodes = parBind->nodeTable;
23886 			/*
23887 			* Append the new node-table entry to the 'new node-table
23888 			* entries' section.
23889 			*/
23890 			parNodes[parBind->nbNodes++] = node;
23891 		    }
23892 
23893 		}
23894 
23895 	    }
23896 	} else {
23897 	    /*
23898 	    * No binding for the IDC was found: create a new one and
23899 	    * copy all node-tables.
23900 	    */
23901 	    parBind = xmlSchemaIDCNewBinding(bind->definition);
23902 	    if (parBind == NULL)
23903 		goto internal_error;
23904 
23905 	    /*
23906 	    * TODO: Hmm, how to optimize the initial number of
23907 	    * allocated entries?
23908 	    */
23909 	    if (bind->nbNodes != 0) {
23910 		/*
23911 		* Add all IDC node-table entries.
23912 		*/
23913 		if (! vctxt->psviExposeIDCNodeTables) {
23914 		    /*
23915 		    * Just move the entries.
23916 		    * NOTE: this is quite save here, since
23917 		    * all the keyref lookups have already been
23918 		    * performed.
23919 		    */
23920 		    parBind->nodeTable = bind->nodeTable;
23921 		    bind->nodeTable = NULL;
23922 		    parBind->sizeNodes = bind->sizeNodes;
23923 		    bind->sizeNodes = 0;
23924 		    parBind->nbNodes = bind->nbNodes;
23925 		    bind->nbNodes = 0;
23926 		} else {
23927 		    /*
23928 		    * Copy the entries.
23929 		    */
23930 		    parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23931 			xmlMalloc(bind->nbNodes *
23932 			sizeof(xmlSchemaPSVIIDCNodePtr));
23933 		    if (parBind->nodeTable == NULL) {
23934 			xmlSchemaVErrMemory(NULL,
23935 			    "allocating an array of IDC node-table "
23936 			    "items", NULL);
23937 			xmlSchemaIDCFreeBinding(parBind);
23938 			goto internal_error;
23939 		    }
23940 		    parBind->sizeNodes = bind->nbNodes;
23941 		    parBind->nbNodes = bind->nbNodes;
23942 		    memcpy(parBind->nodeTable, bind->nodeTable,
23943 			bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
23944 		}
23945 	    }
23946 	    if (bind->dupls) {
23947 		/*
23948 		* Move the duplicates.
23949 		*/
23950 		if (parBind->dupls != NULL)
23951 		    xmlSchemaItemListFree(parBind->dupls);
23952 		parBind->dupls = bind->dupls;
23953 		bind->dupls = NULL;
23954 	    }
23955             if (parTable != NULL) {
23956                 if (*parTable == NULL)
23957                     *parTable = parBind;
23958                 else {
23959                     parBind->next = *parTable;
23960                     *parTable = parBind;
23961                 }
23962             }
23963 	}
23964 
23965 next_binding:
23966 	bind = bind->next;
23967     }
23968     return (0);
23969 
23970 internal_error:
23971     return(-1);
23972 }
23973 
23974 /**
23975  * xmlSchemaCheckCVCIDCKeyRef:
23976  * @vctxt: the WXS validation context
23977  * @elemDecl: the element declaration
23978  *
23979  * Check the cvc-idc-keyref constraints.
23980  */
23981 static int
xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)23982 xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
23983 {
23984     xmlSchemaIDCMatcherPtr matcher;
23985     xmlSchemaPSVIIDCBindingPtr bind;
23986 
23987     matcher = vctxt->inode->idcMatchers;
23988     /*
23989     * Find a keyref.
23990     */
23991     while (matcher != NULL) {
23992 	if ((matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) &&
23993 	    matcher->targets &&
23994 	    matcher->targets->nbItems)
23995 	{
23996 	    int i, j, k, res, nbFields, hasDupls;
23997 	    xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
23998 	    xmlSchemaPSVIIDCNodePtr refNode = NULL;
23999 	    xmlHashTablePtr table = NULL;
24000 
24001 	    nbFields = matcher->aidc->def->nbFields;
24002 
24003 	    /*
24004 	    * Find the IDC node-table for the referenced IDC key/unique.
24005 	    */
24006 	    bind = vctxt->inode->idcTable;
24007 	    while (bind != NULL) {
24008 		if ((xmlSchemaIDCPtr) matcher->aidc->def->ref->item ==
24009 		    bind->definition)
24010 		    break;
24011 		bind = bind->next;
24012 	    }
24013 	    hasDupls = (bind && bind->dupls && bind->dupls->nbItems) ? 1 : 0;
24014 	    /*
24015 	    * Search for a matching key-sequences.
24016 	    */
24017 	    if (bind) {
24018 		table = xmlHashCreate(bind->nbNodes * 2);
24019 		for (j = 0; j < bind->nbNodes; j++) {
24020 		    xmlChar *value;
24021 		    xmlIDCHashEntryPtr r, e;
24022 		    keys = bind->nodeTable[j]->keys;
24023 		    xmlSchemaHashKeySequence(vctxt, &value, keys, nbFields);
24024 		    e = xmlMalloc(sizeof *e);
24025 		    e->index = j;
24026 		    r = xmlHashLookup(table, value);
24027 		    if (r) {
24028 			e->next = r->next;
24029 			r->next = e;
24030 		    } else {
24031 			e->next = NULL;
24032 			xmlHashAddEntry(table, value, e);
24033 		    }
24034 		    FREE_AND_NULL(value);
24035 		}
24036 	    }
24037 	    for (i = 0; i < matcher->targets->nbItems; i++) {
24038 		res = 0;
24039 		refNode = matcher->targets->items[i];
24040 		if (bind != NULL) {
24041 		    xmlChar *value;
24042 		    xmlIDCHashEntryPtr e;
24043 		    refKeys = refNode->keys;
24044 		    xmlSchemaHashKeySequence(vctxt, &value, refKeys, nbFields);
24045 		    e = xmlHashLookup(table, value);
24046 		    FREE_AND_NULL(value);
24047 		    res = 0;
24048 		    for (;e; e = e->next) {
24049 			keys = bind->nodeTable[e->index]->keys;
24050 			for (k = 0; k < nbFields; k++) {
24051 			    res = xmlSchemaAreValuesEqual(keys[k]->val,
24052 							  refKeys[k]->val);
24053 			    if (res == 0)
24054 			        break;
24055 			    else if (res == -1) {
24056 				return (-1);
24057 			    }
24058 			}
24059 			if (res == 1) {
24060 			    /*
24061 			     * Match found.
24062 			     */
24063 			    break;
24064 			}
24065 		    }
24066 		    if ((res == 0) && hasDupls) {
24067 			/*
24068 			* Search in duplicates
24069 			*/
24070 			for (j = 0; j < bind->dupls->nbItems; j++) {
24071 			    keys = ((xmlSchemaPSVIIDCNodePtr)
24072 				bind->dupls->items[j])->keys;
24073 			    for (k = 0; k < nbFields; k++) {
24074 				res = xmlSchemaAreValuesEqual(keys[k]->val,
24075 				    refKeys[k]->val);
24076 				if (res == 0)
24077 				    break;
24078 				else if (res == -1) {
24079 				    return (-1);
24080 				}
24081 			    }
24082 			    if (res == 1) {
24083 				/*
24084 				* Match in duplicates found.
24085 				*/
24086 				xmlChar *str = NULL, *strB = NULL;
24087 				xmlSchemaKeyrefErr(vctxt,
24088 				    XML_SCHEMAV_CVC_IDC, refNode,
24089 				    (xmlSchemaTypePtr) matcher->aidc->def,
24090 				    "More than one match found for "
24091 				    "key-sequence %s of keyref '%s'",
24092 				    xmlSchemaFormatIDCKeySequence(vctxt, &str,
24093 					refNode->keys, nbFields),
24094 				    xmlSchemaGetComponentQName(&strB,
24095 					matcher->aidc->def));
24096 				FREE_AND_NULL(str);
24097 				FREE_AND_NULL(strB);
24098 				break;
24099 			    }
24100 			}
24101 		    }
24102 		}
24103 
24104 		if (res == 0) {
24105 		    xmlChar *str = NULL, *strB = NULL;
24106 		    xmlSchemaKeyrefErr(vctxt,
24107 			XML_SCHEMAV_CVC_IDC, refNode,
24108 			(xmlSchemaTypePtr) matcher->aidc->def,
24109 			"No match found for key-sequence %s of keyref '%s'",
24110 			xmlSchemaFormatIDCKeySequence(vctxt, &str,
24111 			    refNode->keys, nbFields),
24112 			xmlSchemaGetComponentQName(&strB, matcher->aidc->def));
24113 		    FREE_AND_NULL(str);
24114 		    FREE_AND_NULL(strB);
24115 		}
24116 	    }
24117 	    if (table) {
24118 		xmlHashFree(table, xmlFreeIDCHashEntry);
24119 	    }
24120 	}
24121 	matcher = matcher->next;
24122     }
24123     /* TODO: Return an error if any error encountered. */
24124     return (0);
24125 }
24126 
24127 /************************************************************************
24128  *									*
24129  *			XML Reader validation code                      *
24130  *									*
24131  ************************************************************************/
24132 
24133 static xmlSchemaAttrInfoPtr
xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)24134 xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
24135 {
24136     xmlSchemaAttrInfoPtr iattr;
24137     /*
24138     * Grow/create list of attribute infos.
24139     */
24140     if (vctxt->attrInfos == NULL) {
24141 	vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
24142 	    xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
24143 	vctxt->sizeAttrInfos = 1;
24144 	if (vctxt->attrInfos == NULL) {
24145 	    xmlSchemaVErrMemory(vctxt,
24146 		"allocating attribute info list", NULL);
24147 	    return (NULL);
24148 	}
24149     } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
24150 	vctxt->sizeAttrInfos++;
24151 	vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
24152 	    xmlRealloc(vctxt->attrInfos,
24153 		vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
24154 	if (vctxt->attrInfos == NULL) {
24155 	    xmlSchemaVErrMemory(vctxt,
24156 		"re-allocating attribute info list", NULL);
24157 	    return (NULL);
24158 	}
24159     } else {
24160 	iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
24161 	if (iattr->localName != NULL) {
24162 	    VERROR_INT("xmlSchemaGetFreshAttrInfo",
24163 		"attr info not cleared");
24164 	    return (NULL);
24165 	}
24166 	iattr->nodeType = XML_ATTRIBUTE_NODE;
24167 	return (iattr);
24168     }
24169     /*
24170     * Create an attribute info.
24171     */
24172     iattr = (xmlSchemaAttrInfoPtr)
24173 	xmlMalloc(sizeof(xmlSchemaAttrInfo));
24174     if (iattr == NULL) {
24175 	xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
24176 	return (NULL);
24177     }
24178     memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
24179     iattr->nodeType = XML_ATTRIBUTE_NODE;
24180     vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
24181 
24182     return (iattr);
24183 }
24184 
24185 static int
xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,xmlNodePtr attrNode,int nodeLine,const xmlChar * localName,const xmlChar * nsName,int ownedNames,xmlChar * value,int ownedValue)24186 xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
24187 			xmlNodePtr attrNode,
24188 			int nodeLine,
24189 			const xmlChar *localName,
24190 			const xmlChar *nsName,
24191 			int ownedNames,
24192 			xmlChar *value,
24193 			int ownedValue)
24194 {
24195     xmlSchemaAttrInfoPtr attr;
24196 
24197     attr = xmlSchemaGetFreshAttrInfo(vctxt);
24198     if (attr == NULL) {
24199 	VERROR_INT("xmlSchemaPushAttribute",
24200 	    "calling xmlSchemaGetFreshAttrInfo()");
24201 	return (-1);
24202     }
24203     attr->node = attrNode;
24204     attr->nodeLine = nodeLine;
24205     attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
24206     attr->localName = localName;
24207     attr->nsName = nsName;
24208     if (ownedNames)
24209 	attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
24210     /*
24211     * Evaluate if it's an XSI attribute.
24212     */
24213     if (nsName != NULL) {
24214 	if (xmlStrEqual(localName, BAD_CAST "nil")) {
24215 	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
24216 		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
24217 	    }
24218 	} else if (xmlStrEqual(localName, BAD_CAST "type")) {
24219 	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
24220 		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
24221 	    }
24222 	} else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
24223 	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
24224 		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
24225 	    }
24226 	} else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
24227 	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
24228 		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
24229 	    }
24230 	} else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
24231 	    attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
24232 	}
24233     }
24234     attr->value = value;
24235     if (ownedValue)
24236 	attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
24237     if (attr->metaType != 0)
24238 	attr->state = XML_SCHEMAS_ATTR_META;
24239     return (0);
24240 }
24241 
24242 /**
24243  * xmlSchemaClearElemInfo:
24244  * @vctxt: the WXS validation context
24245  * @ielem: the element information item
24246  */
24247 static void
xmlSchemaClearElemInfo(xmlSchemaValidCtxtPtr vctxt,xmlSchemaNodeInfoPtr ielem)24248 xmlSchemaClearElemInfo(xmlSchemaValidCtxtPtr vctxt,
24249 		       xmlSchemaNodeInfoPtr ielem)
24250 {
24251     ielem->hasKeyrefs = 0;
24252     ielem->appliedXPath = 0;
24253     if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
24254 	FREE_AND_NULL(ielem->localName);
24255 	FREE_AND_NULL(ielem->nsName);
24256     } else {
24257 	ielem->localName = NULL;
24258 	ielem->nsName = NULL;
24259     }
24260     if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
24261 	FREE_AND_NULL(ielem->value);
24262     } else {
24263 	ielem->value = NULL;
24264     }
24265     if (ielem->val != NULL) {
24266 	/*
24267 	* PSVI TODO: Be careful not to free it when the value is
24268 	* exposed via PSVI.
24269 	*/
24270 	xmlSchemaFreeValue(ielem->val);
24271 	ielem->val = NULL;
24272     }
24273     if (ielem->idcMatchers != NULL) {
24274 	/*
24275 	* REVISIT OPTIMIZE TODO: Use a pool of IDC matchers.
24276 	*   Does it work?
24277 	*/
24278 	xmlSchemaIDCReleaseMatcherList(vctxt, ielem->idcMatchers);
24279 #if 0
24280 	xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
24281 #endif
24282 	ielem->idcMatchers = NULL;
24283     }
24284     if (ielem->idcTable != NULL) {
24285 	/*
24286 	* OPTIMIZE TODO: Use a pool of IDC tables??.
24287 	*/
24288 	xmlSchemaIDCFreeIDCTable(ielem->idcTable);
24289 	ielem->idcTable = NULL;
24290     }
24291     if (ielem->regexCtxt != NULL) {
24292 	xmlRegFreeExecCtxt(ielem->regexCtxt);
24293 	ielem->regexCtxt = NULL;
24294     }
24295     if (ielem->nsBindings != NULL) {
24296 	xmlFree((xmlChar **)ielem->nsBindings);
24297 	ielem->nsBindings = NULL;
24298 	ielem->nbNsBindings = 0;
24299 	ielem->sizeNsBindings = 0;
24300     }
24301 }
24302 
24303 /**
24304  * xmlSchemaGetFreshElemInfo:
24305  * @vctxt: the schema validation context
24306  *
24307  * Creates/reuses and initializes the element info item for
24308  * the current tree depth.
24309  *
24310  * Returns the element info item or NULL on API or internal errors.
24311  */
24312 static xmlSchemaNodeInfoPtr
xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)24313 xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
24314 {
24315     xmlSchemaNodeInfoPtr info = NULL;
24316 
24317     if (vctxt->depth > vctxt->sizeElemInfos) {
24318 	VERROR_INT("xmlSchemaGetFreshElemInfo",
24319 	    "inconsistent depth encountered");
24320 	return (NULL);
24321     }
24322     if (vctxt->elemInfos == NULL) {
24323 	vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24324 	    xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
24325 	if (vctxt->elemInfos == NULL) {
24326 	    xmlSchemaVErrMemory(vctxt,
24327 		"allocating the element info array", NULL);
24328 	    return (NULL);
24329 	}
24330 	memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
24331 	vctxt->sizeElemInfos = 10;
24332     } else if (vctxt->sizeElemInfos <= vctxt->depth) {
24333 	int i = vctxt->sizeElemInfos;
24334 
24335 	vctxt->sizeElemInfos *= 2;
24336 	vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24337 	    xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
24338 	    sizeof(xmlSchemaNodeInfoPtr));
24339 	if (vctxt->elemInfos == NULL) {
24340 	    xmlSchemaVErrMemory(vctxt,
24341 		"re-allocating the element info array", NULL);
24342 	    return (NULL);
24343 	}
24344 	/*
24345 	* We need the new memory to be NULLed.
24346 	* TODO: Use memset instead?
24347 	*/
24348 	for (; i < vctxt->sizeElemInfos; i++)
24349 	    vctxt->elemInfos[i] = NULL;
24350     } else
24351 	info = vctxt->elemInfos[vctxt->depth];
24352 
24353     if (info == NULL) {
24354 	info = (xmlSchemaNodeInfoPtr)
24355 	    xmlMalloc(sizeof(xmlSchemaNodeInfo));
24356 	if (info == NULL) {
24357 	    xmlSchemaVErrMemory(vctxt,
24358 		"allocating an element info", NULL);
24359 	    return (NULL);
24360 	}
24361 	vctxt->elemInfos[vctxt->depth] = info;
24362     } else {
24363 	if (info->localName != NULL) {
24364 	    VERROR_INT("xmlSchemaGetFreshElemInfo",
24365 		"elem info has not been cleared");
24366 	    return (NULL);
24367 	}
24368     }
24369     memset(info, 0, sizeof(xmlSchemaNodeInfo));
24370     info->nodeType = XML_ELEMENT_NODE;
24371     info->depth = vctxt->depth;
24372 
24373     return (info);
24374 }
24375 
24376 #define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
24377 #define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
24378 #define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
24379 
24380 static int
xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,xmlNodePtr node,xmlSchemaTypePtr type,xmlSchemaValType valType,const xmlChar * value,xmlSchemaValPtr val,unsigned long length,int fireErrors)24381 xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
24382 			xmlNodePtr node,
24383 			xmlSchemaTypePtr type,
24384 			xmlSchemaValType valType,
24385 			const xmlChar * value,
24386 			xmlSchemaValPtr val,
24387 			unsigned long length,
24388 			int fireErrors)
24389 {
24390     int ret, error = 0, found;
24391 
24392     xmlSchemaTypePtr tmpType;
24393     xmlSchemaFacetLinkPtr facetLink;
24394     xmlSchemaFacetPtr facet;
24395     unsigned long len = 0;
24396     xmlSchemaWhitespaceValueType ws;
24397 
24398     /*
24399     * In Libxml2, derived built-in types have currently no explicit facets.
24400     */
24401     if (type->type == XML_SCHEMA_TYPE_BASIC)
24402 	return (0);
24403 
24404     /*
24405     * NOTE: Do not jump away, if the facetSet of the given type is
24406     * empty: until now, "pattern" and "enumeration" facets of the
24407     * *base types* need to be checked as well.
24408     */
24409     if (type->facetSet == NULL)
24410 	goto pattern_and_enum;
24411 
24412     if (! WXS_IS_ATOMIC(type)) {
24413 	if (WXS_IS_LIST(type))
24414 	    goto WXS_IS_LIST;
24415 	else
24416 	    goto pattern_and_enum;
24417     }
24418 
24419     /*
24420     * Whitespace handling is only of importance for string-based
24421     * types.
24422     */
24423     tmpType = xmlSchemaGetPrimitiveType(type);
24424     if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
24425 	WXS_IS_ANY_SIMPLE_TYPE(tmpType)) {
24426 	ws = xmlSchemaGetWhiteSpaceFacetValue(type);
24427     } else
24428 	ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
24429 
24430     /*
24431     * If the value was not computed (for string or
24432     * anySimpleType based types), then use the provided
24433     * type.
24434     */
24435     if (val != NULL)
24436 	valType = xmlSchemaGetValType(val);
24437 
24438     ret = 0;
24439     for (facetLink = type->facetSet; facetLink != NULL;
24440 	facetLink = facetLink->next) {
24441 	/*
24442 	* Skip the pattern "whiteSpace": it is used to
24443 	* format the character content beforehand.
24444 	*/
24445 	switch (facetLink->facet->type) {
24446 	    case XML_SCHEMA_FACET_WHITESPACE:
24447 	    case XML_SCHEMA_FACET_PATTERN:
24448 	    case XML_SCHEMA_FACET_ENUMERATION:
24449 		continue;
24450 	    case XML_SCHEMA_FACET_LENGTH:
24451 	    case XML_SCHEMA_FACET_MINLENGTH:
24452 	    case XML_SCHEMA_FACET_MAXLENGTH:
24453 		ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
24454 		    valType, value, val, &len, ws);
24455 		break;
24456 	    default:
24457 		ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
24458 		    valType, value, val, ws);
24459 		break;
24460 	}
24461 	if (ret < 0) {
24462 	    AERROR_INT("xmlSchemaValidateFacets",
24463 		"validating against a atomic type facet");
24464 	    return (-1);
24465 	} else if (ret > 0) {
24466 	    if (fireErrors)
24467 		xmlSchemaFacetErr(actxt, ret, node,
24468 		value, len, type, facetLink->facet, NULL, NULL, NULL);
24469 	    else
24470 		return (ret);
24471 	    if (error == 0)
24472 		error = ret;
24473 	}
24474 	ret = 0;
24475     }
24476 
24477 WXS_IS_LIST:
24478     if (! WXS_IS_LIST(type))
24479 	goto pattern_and_enum;
24480     /*
24481     * "length", "minLength" and "maxLength" of list types.
24482     */
24483     ret = 0;
24484     for (facetLink = type->facetSet; facetLink != NULL;
24485 	facetLink = facetLink->next) {
24486 
24487 	switch (facetLink->facet->type) {
24488 	    case XML_SCHEMA_FACET_LENGTH:
24489 	    case XML_SCHEMA_FACET_MINLENGTH:
24490 	    case XML_SCHEMA_FACET_MAXLENGTH:
24491 		ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
24492 		    value, length, NULL);
24493 		break;
24494 	    default:
24495 		continue;
24496 	}
24497 	if (ret < 0) {
24498 	    AERROR_INT("xmlSchemaValidateFacets",
24499 		"validating against a list type facet");
24500 	    return (-1);
24501 	} else if (ret > 0) {
24502 	    if (fireErrors)
24503 		xmlSchemaFacetErr(actxt, ret, node,
24504 		value, length, type, facetLink->facet, NULL, NULL, NULL);
24505 	    else
24506 		return (ret);
24507 	    if (error == 0)
24508 		error = ret;
24509 	}
24510 	ret = 0;
24511     }
24512 
24513 pattern_and_enum:
24514     found = 0;
24515     /*
24516     * Process enumerations. Facet values are in the value space
24517     * of the defining type's base type. This seems to be a bug in the
24518     * XML Schema 1.0 spec. Use the whitespace type of the base type.
24519     * Only the first set of enumerations in the ancestor-or-self axis
24520     * is used for validation.
24521     */
24522     ret = 0;
24523     tmpType = type;
24524     do {
24525         for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
24526             if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
24527                 continue;
24528             found = 1;
24529             ret = xmlSchemaAreValuesEqual(facet->val, val);
24530             if (ret == 1)
24531                 break;
24532             else if (ret < 0) {
24533                 AERROR_INT("xmlSchemaValidateFacets",
24534                     "validating against an enumeration facet");
24535                 return (-1);
24536             }
24537         }
24538         if (ret != 0)
24539             break;
24540         /*
24541         * Break on the first set of enumerations. Any additional
24542         *  enumerations which might be existent on the ancestors
24543         *  of the current type are restricted by this set; thus
24544         *  *must* *not* be taken into account.
24545         */
24546         if (found)
24547             break;
24548         tmpType = tmpType->baseType;
24549     } while ((tmpType != NULL) &&
24550         (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24551     if (found && (ret == 0)) {
24552         ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
24553         if (fireErrors) {
24554             xmlSchemaFacetErr(actxt, ret, node,
24555                 value, 0, type, NULL, NULL, NULL, NULL);
24556         } else
24557             return (ret);
24558         if (error == 0)
24559             error = ret;
24560     }
24561 
24562     /*
24563     * Process patters. Pattern facets are ORed at type level
24564     * and ANDed if derived. Walk the base type axis.
24565     */
24566     tmpType = type;
24567     facet = NULL;
24568     do {
24569         found = 0;
24570         for (facetLink = tmpType->facetSet; facetLink != NULL;
24571             facetLink = facetLink->next) {
24572             if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
24573                 continue;
24574             found = 1;
24575             /*
24576             * NOTE that for patterns, @value needs to be the
24577             * normalized value.
24578             */
24579             ret = xmlRegexpExec(facetLink->facet->regexp, value);
24580             if (ret == 1)
24581                 break;
24582             else if (ret < 0) {
24583                 AERROR_INT("xmlSchemaValidateFacets",
24584                     "validating against a pattern facet");
24585                 return (-1);
24586             } else {
24587                 /*
24588                 * Save the last non-validating facet.
24589                 */
24590                 facet = facetLink->facet;
24591             }
24592         }
24593         if (found && (ret != 1)) {
24594             ret = XML_SCHEMAV_CVC_PATTERN_VALID;
24595             if (fireErrors) {
24596                 xmlSchemaFacetErr(actxt, ret, node,
24597                     value, 0, type, facet, NULL, NULL, NULL);
24598             } else
24599                 return (ret);
24600             if (error == 0)
24601                 error = ret;
24602             break;
24603         }
24604         tmpType = tmpType->baseType;
24605     } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24606 
24607     return (error);
24608 }
24609 
24610 static xmlChar *
xmlSchemaNormalizeValue(xmlSchemaTypePtr type,const xmlChar * value)24611 xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
24612 			const xmlChar *value)
24613 {
24614     switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
24615 	case XML_SCHEMA_WHITESPACE_COLLAPSE:
24616 	    return (xmlSchemaCollapseString(value));
24617 	case XML_SCHEMA_WHITESPACE_REPLACE:
24618 	    return (xmlSchemaWhiteSpaceReplace(value));
24619 	default:
24620 	    return (NULL);
24621     }
24622 }
24623 
24624 static int
xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,const xmlChar * value,xmlSchemaValPtr * val,int valNeeded)24625 xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
24626 		       const xmlChar *value,
24627 		       xmlSchemaValPtr *val,
24628 		       int valNeeded)
24629 {
24630     int ret;
24631     const xmlChar *nsName;
24632     xmlChar *local, *prefix = NULL;
24633 
24634     ret = xmlValidateQName(value, 1);
24635     if (ret != 0) {
24636 	if (ret == -1) {
24637 	    VERROR_INT("xmlSchemaValidateQName",
24638 		"calling xmlValidateQName()");
24639 	    return (-1);
24640 	}
24641 	return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
24642     }
24643     /*
24644     * NOTE: xmlSplitQName2 will always return a duplicated
24645     * strings.
24646     */
24647     local = xmlSplitQName2(value, &prefix);
24648     if (local == NULL)
24649 	local = xmlStrdup(value);
24650     /*
24651     * OPTIMIZE TODO: Use flags for:
24652     *  - is there any namespace binding?
24653     *  - is there a default namespace?
24654     */
24655     nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24656 
24657     if (prefix != NULL) {
24658 	xmlFree(prefix);
24659 	/*
24660 	* A namespace must be found if the prefix is
24661 	* NOT NULL.
24662 	*/
24663 	if (nsName == NULL) {
24664 	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24665 	    xmlSchemaCustomErr(ACTXT_CAST vctxt, ret, NULL,
24666 		WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24667 		"The QName value '%s' has no "
24668 		"corresponding namespace declaration in "
24669 		"scope", value, NULL);
24670 	    if (local != NULL)
24671 		xmlFree(local);
24672 	    return (ret);
24673 	}
24674     }
24675     if (valNeeded && val) {
24676 	if (nsName != NULL)
24677 	    *val = xmlSchemaNewQNameValue(
24678 		BAD_CAST xmlStrdup(nsName), BAD_CAST local);
24679 	else
24680 	    *val = xmlSchemaNewQNameValue(NULL,
24681 		BAD_CAST local);
24682     } else
24683 	xmlFree(local);
24684     return (0);
24685 }
24686 
24687 /*
24688 * cvc-simple-type
24689 */
24690 static int
xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,xmlNodePtr node,xmlSchemaTypePtr type,const xmlChar * value,xmlSchemaValPtr * retVal,int fireErrors,int normalize,int isNormalized)24691 xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
24692 			     xmlNodePtr node,
24693 			     xmlSchemaTypePtr type,
24694 			     const xmlChar *value,
24695 			     xmlSchemaValPtr *retVal,
24696 			     int fireErrors,
24697 			     int normalize,
24698 			     int isNormalized)
24699 {
24700     int ret = 0, valNeeded = (retVal) ? 1 : 0;
24701     xmlSchemaValPtr val = NULL;
24702     /* xmlSchemaWhitespaceValueType ws; */
24703     xmlChar *normValue = NULL;
24704 
24705 #define NORMALIZE(atype) \
24706     if ((! isNormalized) && \
24707     (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
24708 	normValue = xmlSchemaNormalizeValue(atype, value); \
24709 	if (normValue != NULL) \
24710 	    value = normValue; \
24711 	isNormalized = 1; \
24712     }
24713 
24714     if ((retVal != NULL) && (*retVal != NULL)) {
24715 	xmlSchemaFreeValue(*retVal);
24716 	*retVal = NULL;
24717     }
24718     /*
24719     * 3.14.4 Simple Type Definition Validation Rules
24720     * Validation Rule: String Valid
24721     */
24722     /*
24723     * 1 It is schema-valid with respect to that definition as defined
24724     * by Datatype Valid in [XML Schemas: Datatypes].
24725     */
24726     /*
24727     * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
24728     * the empty set, as defined in Type Derivation OK (Simple) ($3.14.6), then
24729     * the string must be a `declared entity name`.
24730     */
24731     /*
24732     * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
24733     * given the empty set, as defined in Type Derivation OK (Simple) ($3.14.6),
24734     * then every whitespace-delimited substring of the string must be a `declared
24735     * entity name`.
24736     */
24737     /*
24738     * 2.3 otherwise no further condition applies.
24739     */
24740     if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
24741 	valNeeded = 1;
24742     if (value == NULL)
24743 	value = BAD_CAST "";
24744     if (WXS_IS_ANY_SIMPLE_TYPE(type) || WXS_IS_ATOMIC(type)) {
24745 	xmlSchemaTypePtr biType; /* The built-in type. */
24746 	/*
24747 	* SPEC (1.2.1) "if {variety} is `atomic` then the string must `match`
24748 	* a literal in the `lexical space` of {base type definition}"
24749 	*/
24750 	/*
24751 	* Whitespace-normalize.
24752 	*/
24753 	NORMALIZE(type);
24754 	if (type->type != XML_SCHEMA_TYPE_BASIC) {
24755 	    /*
24756 	    * Get the built-in type.
24757 	    */
24758 	    biType = type->baseType;
24759 	    while ((biType != NULL) &&
24760 		(biType->type != XML_SCHEMA_TYPE_BASIC))
24761 		biType = biType->baseType;
24762 
24763 	    if (biType == NULL) {
24764 		AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24765 		    "could not get the built-in type");
24766 		goto internal_error;
24767 	    }
24768 	} else
24769 	    biType = type;
24770 	/*
24771 	* NOTATIONs need to be processed here, since they need
24772 	* to lookup in the hashtable of NOTATION declarations of the schema.
24773 	*/
24774 	if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
24775 	    switch (biType->builtInType) {
24776 		case XML_SCHEMAS_NOTATION:
24777 		    ret = xmlSchemaValidateNotation(
24778 			(xmlSchemaValidCtxtPtr) actxt,
24779 			((xmlSchemaValidCtxtPtr) actxt)->schema,
24780 			NULL, value, &val, valNeeded);
24781 		    break;
24782 		case XML_SCHEMAS_QNAME:
24783 		    ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
24784 			value, &val, valNeeded);
24785 		    break;
24786 		default:
24787 		    /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24788 		    if (valNeeded)
24789 			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24790 			    value, &val, node);
24791 		    else
24792 			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24793 			    value, NULL, node);
24794 		    break;
24795 	    }
24796 	} else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
24797 	    switch (biType->builtInType) {
24798 		case XML_SCHEMAS_NOTATION:
24799 		    ret = xmlSchemaValidateNotation(NULL,
24800 			((xmlSchemaParserCtxtPtr) actxt)->schema, node,
24801 			value, &val, valNeeded);
24802 		    break;
24803 		default:
24804 		    /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24805 		    if (valNeeded)
24806 			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24807 			    value, &val, node);
24808 		    else
24809 			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24810 			    value, NULL, node);
24811 		    break;
24812 	    }
24813 	} else {
24814 	    /*
24815 	    * Validation via a public API is not implemented yet.
24816 	    */
24817 	    TODO
24818 	    goto internal_error;
24819 	}
24820 	if (ret != 0) {
24821 	    if (ret < 0) {
24822 		AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24823 		    "validating against a built-in type");
24824 		goto internal_error;
24825 	    }
24826 	    if (WXS_IS_LIST(type))
24827 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24828 	    else
24829 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24830 	}
24831 	if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24832 	    /*
24833 	    * Check facets.
24834 	    */
24835 	    ret = xmlSchemaValidateFacets(actxt, node, type,
24836 		(xmlSchemaValType) biType->builtInType, value, val,
24837 		0, fireErrors);
24838 	    if (ret != 0) {
24839 		if (ret < 0) {
24840 		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24841 			"validating facets of atomic simple type");
24842 		    goto internal_error;
24843 		}
24844 		if (WXS_IS_LIST(type))
24845 		    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24846 		else
24847 		    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24848 	    }
24849 	}
24850 	else if (fireErrors && (ret > 0))
24851 	    xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24852     } else if (WXS_IS_LIST(type)) {
24853 
24854 	xmlSchemaTypePtr itemType;
24855 	const xmlChar *cur, *end;
24856 	xmlChar *tmpValue = NULL;
24857 	unsigned long len = 0;
24858 	xmlSchemaValPtr prevVal = NULL, curVal = NULL;
24859 	/* 1.2.2 if {variety} is `list` then the string must be a sequence
24860 	* of white space separated tokens, each of which `match`es a literal
24861 	* in the `lexical space` of {item type definition}
24862 	*/
24863 	/*
24864 	* Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
24865 	* the list type has an enum or pattern facet.
24866 	*/
24867 	NORMALIZE(type);
24868 	/*
24869 	* VAL TODO: Optimize validation of empty values.
24870 	* VAL TODO: We do not have computed values for lists.
24871 	*/
24872 	itemType = WXS_LIST_ITEMTYPE(type);
24873 	cur = value;
24874 	do {
24875 	    while (IS_BLANK_CH(*cur))
24876 		cur++;
24877 	    end = cur;
24878 	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
24879 		end++;
24880 	    if (end == cur)
24881 		break;
24882 	    tmpValue = xmlStrndup(cur, end - cur);
24883 	    len++;
24884 
24885 	    if (valNeeded)
24886 		ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24887 		    tmpValue, &curVal, fireErrors, 0, 1);
24888 	    else
24889 		ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24890 		    tmpValue, NULL, fireErrors, 0, 1);
24891 	    FREE_AND_NULL(tmpValue);
24892 	    if (curVal != NULL) {
24893 		/*
24894 		* Add to list of computed values.
24895 		*/
24896 		if (val == NULL)
24897 		    val = curVal;
24898 		else
24899 		    xmlSchemaValueAppend(prevVal, curVal);
24900 		prevVal = curVal;
24901 		curVal = NULL;
24902 	    }
24903 	    if (ret != 0) {
24904 		if (ret < 0) {
24905 		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24906 			"validating an item of list simple type");
24907 		    goto internal_error;
24908 		}
24909 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24910 		break;
24911 	    }
24912 	    cur = end;
24913 	} while (*cur != 0);
24914 	FREE_AND_NULL(tmpValue);
24915 	if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24916 	    /*
24917 	    * Apply facets (pattern, enumeration).
24918 	    */
24919 	    ret = xmlSchemaValidateFacets(actxt, node, type,
24920 		XML_SCHEMAS_UNKNOWN, value, val,
24921 		len, fireErrors);
24922 	    if (ret != 0) {
24923 		if (ret < 0) {
24924 		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24925 			"validating facets of list simple type");
24926 		    goto internal_error;
24927 		}
24928 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24929 	    }
24930 	}
24931 	if (fireErrors && (ret > 0)) {
24932 	    /*
24933 	    * Report the normalized value.
24934 	    */
24935 	    normalize = 1;
24936 	    NORMALIZE(type);
24937 	    xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24938 	}
24939     } else if (WXS_IS_UNION(type)) {
24940 	xmlSchemaTypeLinkPtr memberLink;
24941 	/*
24942 	* TODO: For all datatypes `derived` by `union`  whiteSpace does
24943 	* not apply directly; however, the normalization behavior of `union`
24944 	* types is controlled by the value of whiteSpace on that one of the
24945 	* `memberTypes` against which the `union` is successfully validated.
24946 	*
24947 	* This means that the value is normalized by the first validating
24948 	* member type, then the facets of the union type are applied. This
24949 	* needs changing of the value!
24950 	*/
24951 
24952 	/*
24953 	* 1.2.3 if {variety} is `union` then the string must `match` a
24954 	* literal in the `lexical space` of at least one member of
24955 	* {member type definitions}
24956 	*/
24957 	memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
24958 	if (memberLink == NULL) {
24959 	    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24960 		"union simple type has no member types");
24961 	    goto internal_error;
24962 	}
24963 	/*
24964 	* Always normalize union type values, since we currently
24965 	* cannot store the whitespace information with the value
24966 	* itself; otherwise a later value-comparison would be
24967 	* not possible.
24968 	*/
24969 	while (memberLink != NULL) {
24970 	    if (valNeeded)
24971 		ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24972 		    memberLink->type, value, &val, 0, 1, 0);
24973 	    else
24974 		ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24975 		    memberLink->type, value, NULL, 0, 1, 0);
24976 	    if (ret <= 0)
24977 		break;
24978 	    memberLink = memberLink->next;
24979 	}
24980 	if (ret != 0) {
24981 	    if (ret < 0) {
24982 		AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24983 		    "validating members of union simple type");
24984 		goto internal_error;
24985 	    }
24986 	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24987 	}
24988 	/*
24989 	* Apply facets (pattern, enumeration).
24990 	*/
24991 	if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24992 	    /*
24993 	    * The normalization behavior of `union` types is controlled by
24994 	    * the value of whiteSpace on that one of the `memberTypes`
24995 	    * against which the `union` is successfully validated.
24996 	    */
24997 	    NORMALIZE(memberLink->type);
24998 	    ret = xmlSchemaValidateFacets(actxt, node, type,
24999 		XML_SCHEMAS_UNKNOWN, value, val,
25000 		0, fireErrors);
25001 	    if (ret != 0) {
25002 		if (ret < 0) {
25003 		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
25004 			"validating facets of union simple type");
25005 		    goto internal_error;
25006 		}
25007 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
25008 	    }
25009 	}
25010 	if (fireErrors && (ret > 0))
25011 	    xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
25012     }
25013 
25014     if (normValue != NULL)
25015 	xmlFree(normValue);
25016     if (ret == 0) {
25017 	if (retVal != NULL)
25018 	    *retVal = val;
25019 	else if (val != NULL)
25020 	    xmlSchemaFreeValue(val);
25021     } else if (val != NULL)
25022 	xmlSchemaFreeValue(val);
25023     return (ret);
25024 internal_error:
25025     if (normValue != NULL)
25026 	xmlFree(normValue);
25027     if (val != NULL)
25028 	xmlSchemaFreeValue(val);
25029     return (-1);
25030 }
25031 
25032 static int
xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,const xmlChar * value,const xmlChar ** nsName,const xmlChar ** localName)25033 xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
25034 			   const xmlChar *value,
25035 			   const xmlChar **nsName,
25036 			   const xmlChar **localName)
25037 {
25038     int ret = 0;
25039 
25040     if ((nsName == NULL) || (localName == NULL))
25041 	return (-1);
25042     *nsName = NULL;
25043     *localName = NULL;
25044 
25045     ret = xmlValidateQName(value, 1);
25046     if (ret == -1)
25047 	return (-1);
25048     if (ret > 0) {
25049 	xmlSchemaSimpleTypeErr(ACTXT_CAST vctxt,
25050 	    XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
25051 	    value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
25052 	return (1);
25053     }
25054     {
25055 	xmlChar *local = NULL;
25056 	xmlChar *prefix;
25057 
25058 	/*
25059 	* NOTE: xmlSplitQName2 will return a duplicated
25060 	* string.
25061 	*/
25062 	local = xmlSplitQName2(value, &prefix);
25063 	if (local == NULL)
25064 	    *localName = xmlDictLookup(vctxt->dict, value, -1);
25065 	else {
25066 	    *localName = xmlDictLookup(vctxt->dict, local, -1);
25067 	    xmlFree(local);
25068 	}
25069 
25070 	*nsName = xmlSchemaLookupNamespace(vctxt, prefix);
25071 
25072 	if (prefix != NULL) {
25073 	    xmlFree(prefix);
25074 	    /*
25075 	    * A namespace must be found if the prefix is NOT NULL.
25076 	    */
25077 	    if (*nsName == NULL) {
25078 		xmlSchemaCustomErr(ACTXT_CAST vctxt,
25079 		    XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
25080 		    WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
25081 		    "The QName value '%s' has no "
25082 		    "corresponding namespace declaration in scope",
25083 		    value, NULL);
25084 		return (2);
25085 	    }
25086 	}
25087     }
25088     return (0);
25089 }
25090 
25091 static int
xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,xmlSchemaAttrInfoPtr iattr,xmlSchemaTypePtr * localType,xmlSchemaElementPtr elemDecl)25092 xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
25093 			xmlSchemaAttrInfoPtr iattr,
25094 			xmlSchemaTypePtr *localType,
25095 			xmlSchemaElementPtr elemDecl)
25096 {
25097     int ret = 0;
25098     /*
25099     * cvc-elt (3.3.4) : (4)
25100     * AND
25101     * Schema-Validity Assessment (Element) (cvc-assess-elt)
25102     *   (1.2.1.2.1) - (1.2.1.2.4)
25103     * Handle 'xsi:type'.
25104     */
25105     if (localType == NULL)
25106 	return (-1);
25107     *localType = NULL;
25108     if (iattr == NULL)
25109 	return (0);
25110     else {
25111 	const xmlChar *nsName = NULL, *local = NULL;
25112 	/*
25113 	* TODO: We should report a *warning* that the type was overridden
25114 	* by the instance.
25115 	*/
25116 	ACTIVATE_ATTRIBUTE(iattr);
25117 	/*
25118 	* (cvc-elt) (3.3.4) : (4.1)
25119 	* (cvc-assess-elt) (1.2.1.2.2)
25120 	*/
25121 	ret = xmlSchemaVExpandQName(vctxt, iattr->value,
25122 	    &nsName, &local);
25123 	if (ret != 0) {
25124 	    if (ret < 0) {
25125 		VERROR_INT("xmlSchemaValidateElementByDeclaration",
25126 		    "calling xmlSchemaQNameExpand() to validate the "
25127 		    "attribute 'xsi:type'");
25128 		goto internal_error;
25129 	    }
25130 	    goto exit;
25131 	}
25132 	/*
25133 	* (cvc-elt) (3.3.4) : (4.2)
25134 	* (cvc-assess-elt) (1.2.1.2.3)
25135 	*/
25136 	*localType = xmlSchemaGetType(vctxt->schema, local, nsName);
25137 	if (*localType == NULL) {
25138 	    xmlChar *str = NULL;
25139 
25140 	    xmlSchemaCustomErr(ACTXT_CAST vctxt,
25141 		XML_SCHEMAV_CVC_ELT_4_2, NULL,
25142 		WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
25143 		"The QName value '%s' of the xsi:type attribute does not "
25144 		"resolve to a type definition",
25145 		xmlSchemaFormatQName(&str, nsName, local), NULL);
25146 	    FREE_AND_NULL(str);
25147 	    ret = vctxt->err;
25148 	    goto exit;
25149 	}
25150 	if (elemDecl != NULL) {
25151 	    int set = 0;
25152 
25153 	    /*
25154 	    * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
25155 	    * "The `local type definition` must be validly
25156 	    * derived from the {type definition} given the union of
25157 	    * the {disallowed substitutions} and the {type definition}'s
25158 	    * {prohibited substitutions}, as defined in
25159 	    * Type Derivation OK (Complex) ($3.4.6)
25160 	    * (if it is a complex type definition),
25161 	    * or given {disallowed substitutions} as defined in Type
25162 	    * Derivation OK (Simple) ($3.14.6) (if it is a simple type
25163 	    * definition)."
25164 	    *
25165 	    * {disallowed substitutions}: the "block" on the element decl.
25166 	    * {prohibited substitutions}: the "block" on the type def.
25167 	    */
25168 	    /*
25169 	    * OPTIMIZE TODO: We could map types already evaluated
25170 	    * to be validly derived from other types to avoid checking
25171 	    * this over and over for the same types.
25172 	    */
25173 	    if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
25174 		(elemDecl->subtypes->flags &
25175 		    XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
25176 		set |= SUBSET_EXTENSION;
25177 
25178 	    if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
25179 		(elemDecl->subtypes->flags &
25180 		    XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
25181 		set |= SUBSET_RESTRICTION;
25182 
25183 	    /*
25184 	    * REMOVED and CHANGED since this produced a parser context
25185 	    * which adds to the string dict of the schema. So this would
25186 	    * change the schema and we don't want this. We don't need
25187 	    * the parser context anymore.
25188 	    *
25189 	    * if ((vctxt->pctxt == NULL) &&
25190 	    *	(xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
25191 	    *	    return (-1);
25192 	    */
25193 
25194 	    if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST vctxt, *localType,
25195 		elemDecl->subtypes, set) != 0) {
25196 		xmlChar *str = NULL;
25197 
25198 		xmlSchemaCustomErr(ACTXT_CAST vctxt,
25199 		    XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
25200 		    "The type definition '%s', specified by xsi:type, is "
25201 		    "blocked or not validly derived from the type definition "
25202 		    "of the element declaration",
25203 		    xmlSchemaFormatQName(&str,
25204 			(*localType)->targetNamespace,
25205 			(*localType)->name),
25206 		    NULL);
25207 		FREE_AND_NULL(str);
25208 		ret = vctxt->err;
25209 		*localType = NULL;
25210 	    }
25211 	}
25212     }
25213 exit:
25214     ACTIVATE_ELEM;
25215     return (ret);
25216 internal_error:
25217     ACTIVATE_ELEM;
25218     return (-1);
25219 }
25220 
25221 static int
xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)25222 xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
25223 {
25224     xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
25225     xmlSchemaTypePtr actualType;
25226 
25227     /*
25228     * cvc-elt (3.3.4) : 1
25229     */
25230     if (elemDecl == NULL) {
25231 	VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
25232 	    "No matching declaration available");
25233         return (vctxt->err);
25234     }
25235     actualType = WXS_ELEM_TYPEDEF(elemDecl);
25236     /*
25237     * cvc-elt (3.3.4) : 2
25238     */
25239     if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
25240 	VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
25241 	    "The element declaration is abstract");
25242         return (vctxt->err);
25243     }
25244     if (actualType == NULL) {
25245 	VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
25246 	    "The type definition is absent");
25247 	return (XML_SCHEMAV_CVC_TYPE_1);
25248     }
25249     if (vctxt->nbAttrInfos != 0) {
25250 	int ret;
25251 	xmlSchemaAttrInfoPtr iattr;
25252 	/*
25253 	* cvc-elt (3.3.4) : 3
25254 	* Handle 'xsi:nil'.
25255 	*/
25256 	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25257 	    XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
25258 	if (iattr) {
25259 	    ACTIVATE_ATTRIBUTE(iattr);
25260 	    /*
25261 	    * Validate the value.
25262 	    */
25263 	    ret = xmlSchemaVCheckCVCSimpleType(
25264 		ACTXT_CAST vctxt, NULL,
25265 		xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
25266 		iattr->value, &(iattr->val), 1, 0, 0);
25267 	    ACTIVATE_ELEM;
25268 	    if (ret < 0) {
25269 		VERROR_INT("xmlSchemaValidateElemDecl",
25270 		    "calling xmlSchemaVCheckCVCSimpleType() to "
25271 		    "validate the attribute 'xsi:nil'");
25272 		return (-1);
25273 	    }
25274 	    if (ret == 0) {
25275 		if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
25276 		    /*
25277 		    * cvc-elt (3.3.4) : 3.1
25278 		    */
25279 		    VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
25280 			"The element is not 'nillable'");
25281 		    /* Does not return an error on purpose. */
25282 		} else {
25283 		    if (xmlSchemaValueGetAsBoolean(iattr->val)) {
25284 			/*
25285 			* cvc-elt (3.3.4) : 3.2.2
25286 			*/
25287 			if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
25288 			    (elemDecl->value != NULL)) {
25289 			    VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
25290 				"The element cannot be 'nilled' because "
25291 				"there is a fixed value constraint defined "
25292 				"for it");
25293 			     /* Does not return an error on purpose. */
25294 			} else
25295 			    vctxt->inode->flags |=
25296 				XML_SCHEMA_ELEM_INFO_NILLED;
25297 		    }
25298 		}
25299 	    }
25300 	}
25301 	/*
25302 	* cvc-elt (3.3.4) : 4
25303 	* Handle 'xsi:type'.
25304 	*/
25305 	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25306 	    XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25307 	if (iattr) {
25308 	    xmlSchemaTypePtr localType = NULL;
25309 
25310 	    ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
25311 		elemDecl);
25312 	    if (ret != 0) {
25313 		if (ret == -1) {
25314 		    VERROR_INT("xmlSchemaValidateElemDecl",
25315 			"calling xmlSchemaProcessXSIType() to "
25316 			"process the attribute 'xsi:type'");
25317 		    return (-1);
25318 		}
25319 		/* Does not return an error on purpose. */
25320 	    }
25321 	    if (localType != NULL) {
25322 		vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
25323 		actualType = localType;
25324 	    }
25325 	}
25326     }
25327     /*
25328     * IDC: Register identity-constraint XPath matchers.
25329     */
25330     if ((elemDecl->idcs != NULL) &&
25331 	(xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
25332 	    return (-1);
25333     /*
25334     * No actual type definition.
25335     */
25336     if (actualType == NULL) {
25337 	VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
25338 	    "The type definition is absent");
25339 	return (XML_SCHEMAV_CVC_TYPE_1);
25340     }
25341     /*
25342     * Remember the actual type definition.
25343     */
25344     vctxt->inode->typeDef = actualType;
25345 
25346     return (0);
25347 }
25348 
25349 static int
xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)25350 xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
25351 {
25352     xmlSchemaAttrInfoPtr iattr;
25353     int ret = 0, i;
25354 
25355     /*
25356     * SPEC cvc-type (3.1.1)
25357     * "The attributes of must be empty, excepting those whose namespace
25358     * name is identical to http://www.w3.org/2001/XMLSchema-instance and
25359     * whose local name is one of type, nil, schemaLocation or
25360     * noNamespaceSchemaLocation."
25361     */
25362     if (vctxt->nbAttrInfos == 0)
25363 	return (0);
25364     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25365 	iattr = vctxt->attrInfos[i];
25366 	if (! iattr->metaType) {
25367 	    ACTIVATE_ATTRIBUTE(iattr)
25368 	    xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25369 		XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
25370 	    ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
25371         }
25372     }
25373     ACTIVATE_ELEM
25374     return (ret);
25375 }
25376 
25377 /*
25378 * Cleanup currently used attribute infos.
25379 */
25380 static void
xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)25381 xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
25382 {
25383     int i;
25384     xmlSchemaAttrInfoPtr attr;
25385 
25386     if (vctxt->nbAttrInfos == 0)
25387 	return;
25388     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25389 	attr = vctxt->attrInfos[i];
25390 	if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
25391 	    if (attr->localName != NULL)
25392 		xmlFree((xmlChar *) attr->localName);
25393 	    if (attr->nsName != NULL)
25394 		xmlFree((xmlChar *) attr->nsName);
25395 	}
25396 	if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
25397 	    if (attr->value != NULL)
25398 		xmlFree((xmlChar *) attr->value);
25399 	}
25400 	if (attr->val != NULL) {
25401 	    xmlSchemaFreeValue(attr->val);
25402 	    attr->val = NULL;
25403 	}
25404 	memset(attr, 0, sizeof(xmlSchemaAttrInfo));
25405     }
25406     vctxt->nbAttrInfos = 0;
25407 }
25408 
25409 /*
25410 * 3.4.4 Complex Type Definition Validation Rules
25411 *   Element Locally Valid (Complex Type) (cvc-complex-type)
25412 * 3.2.4 Attribute Declaration Validation Rules
25413 *   Validation Rule: Attribute Locally Valid (cvc-attribute)
25414 *   Attribute Locally Valid (Use) (cvc-au)
25415 *
25416 * Only "assessed" attribute information items will be visible to
25417 * IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
25418 */
25419 static int
xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)25420 xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
25421 {
25422     xmlSchemaTypePtr type = vctxt->inode->typeDef;
25423     xmlSchemaItemListPtr attrUseList;
25424     xmlSchemaAttributeUsePtr attrUse = NULL;
25425     xmlSchemaAttributePtr attrDecl = NULL;
25426     xmlSchemaAttrInfoPtr iattr, tmpiattr;
25427     int i, j, found, nbAttrs, nbUses;
25428     int xpathRes = 0, res, wildIDs = 0, fixed;
25429     xmlNodePtr defAttrOwnerElem = NULL;
25430 
25431     /*
25432     * SPEC (cvc-attribute)
25433     * (1) "The declaration must not be `absent` (see Missing
25434     * Sub-components ($5.3) for how this can fail to be
25435     * the case)."
25436     * (2) "Its {type definition} must not be absent."
25437     *
25438     * NOTE (1) + (2): This is not handled here, since we currently do not
25439     * allow validation against schemas which have missing sub-components.
25440     *
25441     * SPEC (cvc-complex-type)
25442     * (3) "For each attribute information item in the element information
25443     * item's [attributes] excepting those whose [namespace name] is
25444     * identical to http://www.w3.org/2001/XMLSchema-instance and whose
25445     * [local name] is one of type, nil, schemaLocation or
25446     * noNamespaceSchemaLocation, the appropriate case among the following
25447     * must be true:
25448     *
25449     */
25450     attrUseList = (xmlSchemaItemListPtr) type->attrUses;
25451     /*
25452     * @nbAttrs is the number of attributes present in the instance.
25453     */
25454     nbAttrs = vctxt->nbAttrInfos;
25455     if (attrUseList != NULL)
25456 	nbUses = attrUseList->nbItems;
25457     else
25458 	nbUses = 0;
25459     for (i = 0; i < nbUses; i++) {
25460         found = 0;
25461 	attrUse = attrUseList->items[i];
25462 	attrDecl = WXS_ATTRUSE_DECL(attrUse);
25463         for (j = 0; j < nbAttrs; j++) {
25464 	    iattr = vctxt->attrInfos[j];
25465 	    /*
25466 	    * SPEC (cvc-complex-type) (3)
25467 	    * Skip meta attributes.
25468 	    */
25469 	    if (iattr->metaType)
25470 		continue;
25471 	    if (iattr->localName[0] != attrDecl->name[0])
25472 		continue;
25473 	    if (!xmlStrEqual(iattr->localName, attrDecl->name))
25474 		continue;
25475 	    if (!xmlStrEqual(iattr->nsName, attrDecl->targetNamespace))
25476 		continue;
25477 	    found = 1;
25478 	    /*
25479 	    * SPEC (cvc-complex-type)
25480 	    * (3.1) "If there is among the {attribute uses} an attribute
25481 	    * use with an {attribute declaration} whose {name} matches
25482 	    * the attribute information item's [local name] and whose
25483 	    * {target namespace} is identical to the attribute information
25484 	    * item's [namespace name] (where an `absent` {target namespace}
25485 	    * is taken to be identical to a [namespace name] with no value),
25486 	    * then the attribute information must be `valid` with respect
25487 	    * to that attribute use as per Attribute Locally Valid (Use)
25488 	    * ($3.5.4). In this case the {attribute declaration} of that
25489 	    * attribute use is the `context-determined declaration` for the
25490 	    * attribute information item with respect to Schema-Validity
25491 	    * Assessment (Attribute) ($3.2.4) and
25492 	    * Assessment Outcome (Attribute) ($3.2.5).
25493 	    */
25494 	    iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25495 	    iattr->use = attrUse;
25496 	    /*
25497 	    * Context-determined declaration.
25498 	    */
25499 	    iattr->decl = attrDecl;
25500 	    iattr->typeDef = attrDecl->subtypes;
25501 	    break;
25502 	}
25503 
25504 	if (found)
25505 	    continue;
25506 
25507 	if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
25508 	    /*
25509 	    * Handle non-existent, required attributes.
25510 	    *
25511 	    * SPEC (cvc-complex-type)
25512 	    * (4) "The {attribute declaration} of each attribute use in
25513 	    * the {attribute uses} whose {required} is true matches one
25514 	    * of the attribute information items in the element information
25515 	    * item's [attributes] as per clause 3.1 above."
25516 	    */
25517 	    tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25518 	    if (tmpiattr == NULL) {
25519 		VERROR_INT(
25520 		    "xmlSchemaVAttributesComplex",
25521 		    "calling xmlSchemaGetFreshAttrInfo()");
25522 		return (-1);
25523 	    }
25524 	    tmpiattr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
25525 	    tmpiattr->use = attrUse;
25526 	    tmpiattr->decl = attrDecl;
25527 	} else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
25528 	    ((attrUse->defValue != NULL) ||
25529 	     (attrDecl->defValue != NULL))) {
25530 	    /*
25531 	    * Handle non-existent, optional, default/fixed attributes.
25532 	    */
25533 	    tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25534 	    if (tmpiattr == NULL) {
25535 		VERROR_INT(
25536 		    "xmlSchemaVAttributesComplex",
25537 		    "calling xmlSchemaGetFreshAttrInfo()");
25538 		return (-1);
25539 	    }
25540 	    tmpiattr->state = XML_SCHEMAS_ATTR_DEFAULT;
25541 	    tmpiattr->use = attrUse;
25542 	    tmpiattr->decl = attrDecl;
25543 	    tmpiattr->typeDef = attrDecl->subtypes;
25544 	    tmpiattr->localName = attrDecl->name;
25545 	    tmpiattr->nsName = attrDecl->targetNamespace;
25546 	}
25547     }
25548 
25549     if (vctxt->nbAttrInfos == 0)
25550 	return (0);
25551     /*
25552     * Validate against the wildcard.
25553     */
25554     if (type->attributeWildcard != NULL) {
25555 	/*
25556 	* SPEC (cvc-complex-type)
25557 	* (3.2.1) "There must be an {attribute wildcard}."
25558 	*/
25559 	for (i = 0; i < nbAttrs; i++) {
25560 	    iattr = vctxt->attrInfos[i];
25561 	    /*
25562 	    * SPEC (cvc-complex-type) (3)
25563 	    * Skip meta attributes.
25564 	    */
25565 	    if (iattr->state != XML_SCHEMAS_ATTR_UNKNOWN)
25566 		continue;
25567 	    /*
25568 	    * SPEC (cvc-complex-type)
25569 	    * (3.2.2) "The attribute information item must be `valid` with
25570 	    * respect to it as defined in Item Valid (Wildcard) ($3.10.4)."
25571 	    *
25572 	    * SPEC Item Valid (Wildcard) (cvc-wildcard)
25573 	    * "... its [namespace name] must be `valid` with respect to
25574 	    * the wildcard constraint, as defined in Wildcard allows
25575 	    * Namespace Name ($3.10.4)."
25576 	    */
25577 	    if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
25578 		    iattr->nsName) == 0) {
25579 		/*
25580 		* Handle processContents.
25581 		*
25582 		* SPEC (cvc-wildcard):
25583 		* processContents | context-determined declaration:
25584 		* "strict"          "mustFind"
25585 		* "lax"             "none"
25586 		* "skip"            "skip"
25587 		*/
25588 		if (type->attributeWildcard->processContents ==
25589 		    XML_SCHEMAS_ANY_SKIP) {
25590 		     /*
25591 		    * context-determined declaration = "skip"
25592 		    *
25593 		    * SPEC PSVI Assessment Outcome (Attribute)
25594 		    * [validity] = "notKnown"
25595 		    * [validation attempted] = "none"
25596 		    */
25597 		    iattr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
25598 		    continue;
25599 		}
25600 		/*
25601 		* Find an attribute declaration.
25602 		*/
25603 		iattr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
25604 		    iattr->localName, iattr->nsName);
25605 		if (iattr->decl != NULL) {
25606 		    iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25607 		    /*
25608 		    * SPEC (cvc-complex-type)
25609 		    * (5) "Let [Definition:]  the wild IDs be the set of
25610 		    * all attribute information item to which clause 3.2
25611 		    * applied and whose `validation` resulted in a
25612 		    * `context-determined declaration` of mustFind or no
25613 		    * `context-determined declaration` at all, and whose
25614 		    * [local name] and [namespace name] resolve (as
25615 		    * defined by QName resolution (Instance) ($3.15.4)) to
25616 		    * an attribute declaration whose {type definition} is
25617 		    * or is derived from ID. Then all of the following
25618 		    * must be true:"
25619 		    */
25620 		    iattr->typeDef = WXS_ATTR_TYPEDEF(iattr->decl);
25621 		    if (xmlSchemaIsDerivedFromBuiltInType(
25622 			iattr->typeDef, XML_SCHEMAS_ID)) {
25623 			/*
25624 			* SPEC (5.1) "There must be no more than one
25625 			* item in `wild IDs`."
25626 			*/
25627 			if (wildIDs != 0) {
25628 			    /* VAL TODO */
25629 			    iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
25630 			    TODO
25631 			    continue;
25632 			}
25633 			wildIDs++;
25634 			/*
25635 			* SPEC (cvc-complex-type)
25636 			* (5.2) "If `wild IDs` is non-empty, there must not
25637 			* be any attribute uses among the {attribute uses}
25638 			* whose {attribute declaration}'s {type definition}
25639 			* is or is derived from ID."
25640 			*/
25641                         if (attrUseList != NULL) {
25642                             for (j = 0; j < attrUseList->nbItems; j++) {
25643                                 if (xmlSchemaIsDerivedFromBuiltInType(
25644                                     WXS_ATTRUSE_TYPEDEF(attrUseList->items[j]),
25645                                     XML_SCHEMAS_ID)) {
25646                                     /* URGENT VAL TODO: implement */
25647                             iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
25648                                     TODO
25649                                     break;
25650                                 }
25651                             }
25652                         }
25653 		    }
25654 		} else if (type->attributeWildcard->processContents ==
25655 		    XML_SCHEMAS_ANY_LAX) {
25656 		    iattr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
25657 		    /*
25658 		    * SPEC PSVI Assessment Outcome (Attribute)
25659 		    * [validity] = "notKnown"
25660 		    * [validation attempted] = "none"
25661 		    */
25662 		} else {
25663 		    iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
25664 		}
25665 	    }
25666 	}
25667     }
25668 
25669     if (vctxt->nbAttrInfos == 0)
25670 	return (0);
25671 
25672     /*
25673     * Get the owner element; needed for creation of default attributes.
25674     * This fixes bug #341337, reported by David Grohmann.
25675     */
25676     if (vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
25677 	xmlSchemaNodeInfoPtr ielem = vctxt->elemInfos[vctxt->depth];
25678 	if (ielem && ielem->node && ielem->node->doc)
25679 	    defAttrOwnerElem = ielem->node;
25680     }
25681     /*
25682     * Validate values, create default attributes, evaluate IDCs.
25683     */
25684     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25685 	iattr = vctxt->attrInfos[i];
25686 	/*
25687 	* VAL TODO: Note that we won't try to resolve IDCs to
25688 	* "lax" and "skip" validated attributes. Check what to
25689 	* do in this case.
25690 	*/
25691 	if ((iattr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
25692 	    (iattr->state != XML_SCHEMAS_ATTR_DEFAULT))
25693 	    continue;
25694 	/*
25695 	* VAL TODO: What to do if the type definition is missing?
25696 	*/
25697 	if (iattr->typeDef == NULL) {
25698 	    iattr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
25699 	    continue;
25700 	}
25701 
25702 	ACTIVATE_ATTRIBUTE(iattr);
25703 	fixed = 0;
25704 	xpathRes = 0;
25705 
25706 	if (vctxt->xpathStates != NULL) {
25707 	    /*
25708 	    * Evaluate IDCs.
25709 	    */
25710 	    xpathRes = xmlSchemaXPathEvaluate(vctxt,
25711 		XML_ATTRIBUTE_NODE);
25712 	    if (xpathRes == -1) {
25713 		VERROR_INT("xmlSchemaVAttributesComplex",
25714 		    "calling xmlSchemaXPathEvaluate()");
25715 		goto internal_error;
25716 	    }
25717 	}
25718 
25719 	if (iattr->state == XML_SCHEMAS_ATTR_DEFAULT) {
25720 	    /*
25721 	    * Default/fixed attributes.
25722 	    * We need the value only if we need to resolve IDCs or
25723 	    * will create default attributes.
25724 	    */
25725 	    if ((xpathRes) || (defAttrOwnerElem)) {
25726 		if (iattr->use->defValue != NULL) {
25727 		    iattr->value = (xmlChar *) iattr->use->defValue;
25728 		    iattr->val = iattr->use->defVal;
25729 		} else {
25730 		    iattr->value = (xmlChar *) iattr->decl->defValue;
25731 		    iattr->val = iattr->decl->defVal;
25732 		}
25733 		/*
25734 		* IDCs will consume the precomputed default value,
25735 		* so we need to clone it.
25736 		*/
25737 		if (iattr->val == NULL) {
25738 		    VERROR_INT("xmlSchemaVAttributesComplex",
25739 			"default/fixed value on an attribute use was "
25740 			"not precomputed");
25741 		    goto internal_error;
25742 		}
25743 		iattr->val = xmlSchemaCopyValue(iattr->val);
25744 		if (iattr->val == NULL) {
25745 		    VERROR_INT("xmlSchemaVAttributesComplex",
25746 			"calling xmlSchemaCopyValue()");
25747 		    goto internal_error;
25748 		}
25749 	    }
25750 	    /*
25751 	    * PSVI: Add the default attribute to the current element.
25752 	    * VAL TODO: Should we use the *normalized* value? This currently
25753 	    *   uses the *initial* value.
25754 	    */
25755 
25756 	    if (defAttrOwnerElem) {
25757 		xmlChar *normValue;
25758 		const xmlChar *value;
25759 
25760 		value = iattr->value;
25761 		/*
25762 		* Normalize the value.
25763 		*/
25764 		normValue = xmlSchemaNormalizeValue(iattr->typeDef,
25765 		    iattr->value);
25766 		if (normValue != NULL)
25767 		    value = BAD_CAST normValue;
25768 
25769 		if (iattr->nsName == NULL) {
25770 		    if (xmlNewProp(defAttrOwnerElem,
25771 			iattr->localName, value) == NULL) {
25772 			VERROR_INT("xmlSchemaVAttributesComplex",
25773 			    "calling xmlNewProp()");
25774 			if (normValue != NULL)
25775 			    xmlFree(normValue);
25776 			goto internal_error;
25777 		    }
25778 		} else {
25779 		    xmlNsPtr ns;
25780 
25781 		    ns = xmlSearchNsByHref(defAttrOwnerElem->doc,
25782 			defAttrOwnerElem, iattr->nsName);
25783 		    if (ns == NULL) {
25784 			xmlChar prefix[12];
25785 			int counter = 0;
25786 
25787 			/*
25788 			* Create a namespace declaration on the validation
25789 			* root node if no namespace declaration is in scope.
25790 			*/
25791 			do {
25792 			    snprintf((char *) prefix, 12, "p%d", counter++);
25793 			    ns = xmlSearchNs(defAttrOwnerElem->doc,
25794 				defAttrOwnerElem, BAD_CAST prefix);
25795 			    if (counter > 1000) {
25796 				VERROR_INT(
25797 				    "xmlSchemaVAttributesComplex",
25798 				    "could not compute a ns prefix for a "
25799 				    "default/fixed attribute");
25800 				if (normValue != NULL)
25801 				    xmlFree(normValue);
25802 				goto internal_error;
25803 			    }
25804 			} while (ns != NULL);
25805 			ns = xmlNewNs(vctxt->validationRoot,
25806 			    iattr->nsName, BAD_CAST prefix);
25807 		    }
25808 		    /*
25809 		    * TODO:
25810 		    * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0406.html
25811 		    * If we have QNames: do we need to ensure there's a
25812 		    * prefix defined for the QName?
25813 		    */
25814 		    xmlNewNsProp(defAttrOwnerElem, ns, iattr->localName, value);
25815 		}
25816 		if (normValue != NULL)
25817 		    xmlFree(normValue);
25818 	    }
25819 	    /*
25820 	    * Go directly to IDC evaluation.
25821 	    */
25822 	    goto eval_idcs;
25823 	}
25824 	/*
25825 	* Validate the value.
25826 	*/
25827 	if (vctxt->value != NULL) {
25828 	    /*
25829 	    * Free last computed value; just for safety reasons.
25830 	    */
25831 	    xmlSchemaFreeValue(vctxt->value);
25832 	    vctxt->value = NULL;
25833 	}
25834 	/*
25835 	* Note that the attribute *use* can be unavailable, if
25836 	* the attribute was a wild attribute.
25837 	*/
25838 	if ((iattr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
25839 	    ((iattr->use != NULL) &&
25840 	     (iattr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
25841 	    fixed = 1;
25842 	else
25843 	    fixed = 0;
25844 	/*
25845 	* SPEC (cvc-attribute)
25846 	* (3) "The item's `normalized value` must be locally `valid`
25847 	* with respect to that {type definition} as per
25848 	* String Valid ($3.14.4)."
25849 	*
25850 	* VAL TODO: Do we already have the
25851 	* "normalized attribute value" here?
25852 	*/
25853 	if (xpathRes || fixed) {
25854 	    iattr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
25855 	    /*
25856 	    * Request a computed value.
25857 	    */
25858 	    res = xmlSchemaVCheckCVCSimpleType(
25859 		ACTXT_CAST vctxt,
25860 		iattr->node, iattr->typeDef, iattr->value, &(iattr->val),
25861 		1, 1, 0);
25862 	} else {
25863 	    res = xmlSchemaVCheckCVCSimpleType(
25864 		ACTXT_CAST vctxt,
25865 		iattr->node, iattr->typeDef, iattr->value, NULL,
25866 		1, 0, 0);
25867 	}
25868 
25869 	if (res != 0) {
25870 	    if (res == -1) {
25871 		VERROR_INT("xmlSchemaVAttributesComplex",
25872 		    "calling xmlSchemaStreamValidateSimpleTypeValue()");
25873 		goto internal_error;
25874 	    }
25875 	    iattr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
25876 	    /*
25877 	    * SPEC PSVI Assessment Outcome (Attribute)
25878 	    * [validity] = "invalid"
25879 	    */
25880 	    goto eval_idcs;
25881 	}
25882 
25883 	if (fixed) {
25884 	    /*
25885 	    * SPEC Attribute Locally Valid (Use) (cvc-au)
25886 	    * "For an attribute information item to be `valid`
25887 	    * with respect to an attribute use its *normalized*
25888 	    * value must match the *canonical* lexical
25889 	    * representation of the attribute use's {value
25890 	    * constraint}value, if it is present and fixed."
25891 	    *
25892 	    * VAL TODO: The requirement for the *canonical* value
25893 	    * will be removed in XML Schema 1.1.
25894 	    */
25895 	    /*
25896 	    * SPEC Attribute Locally Valid (cvc-attribute)
25897 	    * (4) "The item's *actual* value must match the *value* of
25898 	    * the {value constraint}, if it is present and fixed."
25899 	    */
25900 	    if (iattr->val == NULL) {
25901 		/* VAL TODO: A value was not precomputed. */
25902 		TODO
25903 		goto eval_idcs;
25904 	    }
25905 	    if ((iattr->use != NULL) &&
25906 		(iattr->use->defValue != NULL)) {
25907 		if (iattr->use->defVal == NULL) {
25908 		    /* VAL TODO: A default value was not precomputed. */
25909 		    TODO
25910 		    goto eval_idcs;
25911 		}
25912 		iattr->vcValue = iattr->use->defValue;
25913 		/*
25914 		if (xmlSchemaCompareValuesWhtsp(attr->val,
25915 		    (xmlSchemaWhitespaceValueType) ws,
25916 		    attr->use->defVal,
25917 		    (xmlSchemaWhitespaceValueType) ws) != 0) {
25918 		*/
25919 		if (! xmlSchemaAreValuesEqual(iattr->val, iattr->use->defVal))
25920 		    iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25921 	    } else {
25922 		if (iattr->decl->defVal == NULL) {
25923 		    /* VAL TODO: A default value was not precomputed. */
25924 		    TODO
25925 		    goto eval_idcs;
25926 		}
25927 		iattr->vcValue = iattr->decl->defValue;
25928 		/*
25929 		if (xmlSchemaCompareValuesWhtsp(attr->val,
25930 		    (xmlSchemaWhitespaceValueType) ws,
25931 		    attrDecl->defVal,
25932 		    (xmlSchemaWhitespaceValueType) ws) != 0) {
25933 		*/
25934 		if (! xmlSchemaAreValuesEqual(iattr->val, iattr->decl->defVal))
25935 		    iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25936 	    }
25937 	    /*
25938 	    * [validity] = "valid"
25939 	    */
25940 	}
25941 eval_idcs:
25942 	/*
25943 	* Evaluate IDCs.
25944 	*/
25945 	if (xpathRes) {
25946 	    if (xmlSchemaXPathProcessHistory(vctxt,
25947 		vctxt->depth +1) == -1) {
25948 		VERROR_INT("xmlSchemaVAttributesComplex",
25949 		    "calling xmlSchemaXPathEvaluate()");
25950 		goto internal_error;
25951 	    }
25952 	} else if (vctxt->xpathStates != NULL)
25953 	    xmlSchemaXPathPop(vctxt);
25954     }
25955 
25956     /*
25957     * Report errors.
25958     */
25959     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25960 	iattr = vctxt->attrInfos[i];
25961 	if ((iattr->state == XML_SCHEMAS_ATTR_META) ||
25962 	    (iattr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
25963 	    (iattr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
25964 	    (iattr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
25965 	    continue;
25966 	ACTIVATE_ATTRIBUTE(iattr);
25967 	switch (iattr->state) {
25968 	    case XML_SCHEMAS_ATTR_ERR_MISSING: {
25969 		    xmlChar *str = NULL;
25970 		    ACTIVATE_ELEM;
25971 		    xmlSchemaCustomErr(ACTXT_CAST vctxt,
25972 			XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
25973 			"The attribute '%s' is required but missing",
25974 			xmlSchemaFormatQName(&str,
25975 			    iattr->decl->targetNamespace,
25976 			    iattr->decl->name),
25977 			NULL);
25978 		    FREE_AND_NULL(str)
25979 		    break;
25980 		}
25981 	    case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
25982 		VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
25983 		    "The type definition is absent");
25984 		break;
25985 	    case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
25986 		xmlSchemaCustomErr(ACTXT_CAST vctxt,
25987 		    XML_SCHEMAV_CVC_AU, NULL, NULL,
25988 		    "The value '%s' does not match the fixed "
25989 		    "value constraint '%s'",
25990 		    iattr->value, iattr->vcValue);
25991 		break;
25992 	    case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
25993 		VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
25994 		    "No matching global attribute declaration available, but "
25995 		    "demanded by the strict wildcard");
25996 		break;
25997 	    case XML_SCHEMAS_ATTR_UNKNOWN:
25998 		if (iattr->metaType)
25999 		    break;
26000 		/*
26001 		* MAYBE VAL TODO: One might report different error messages
26002 		* for the following errors.
26003 		*/
26004 		if (type->attributeWildcard == NULL) {
26005 		    xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
26006 			XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, iattr, NULL);
26007 		} else {
26008 		    xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
26009 			XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, iattr, NULL);
26010 		}
26011 		break;
26012 	    default:
26013 		break;
26014 	}
26015     }
26016 
26017     ACTIVATE_ELEM;
26018     return (0);
26019 internal_error:
26020     ACTIVATE_ELEM;
26021     return (-1);
26022 }
26023 
26024 static int
xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,int * skip)26025 xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
26026 			      int *skip)
26027 {
26028     xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
26029     /*
26030     * The namespace of the element was already identified to be
26031     * matching the wildcard.
26032     */
26033     if ((skip == NULL) || (wild == NULL) ||
26034 	(wild->type != XML_SCHEMA_TYPE_ANY)) {
26035 	VERROR_INT("xmlSchemaValidateElemWildcard",
26036 	    "bad arguments");
26037 	return (-1);
26038     }
26039     *skip = 0;
26040     if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
26041 	/*
26042 	* URGENT VAL TODO: Either we need to position the stream to the
26043 	* next sibling, or walk the whole subtree.
26044 	*/
26045 	*skip = 1;
26046 	return (0);
26047     }
26048     {
26049 	xmlSchemaElementPtr decl = NULL;
26050 
26051 	decl = xmlSchemaGetElem(vctxt->schema,
26052 	    vctxt->inode->localName, vctxt->inode->nsName);
26053 	if (decl != NULL) {
26054 	    vctxt->inode->decl = decl;
26055 	    return (0);
26056 	}
26057     }
26058     if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
26059 	/* VAL TODO: Change to proper error code. */
26060 	VERROR(XML_SCHEMAV_CVC_ELT_1, NULL, /* WXS_BASIC_CAST wild */
26061 	    "No matching global element declaration available, but "
26062 	    "demanded by the strict wildcard");
26063 	return (vctxt->err);
26064     }
26065     if (vctxt->nbAttrInfos != 0) {
26066 	xmlSchemaAttrInfoPtr iattr;
26067 	/*
26068 	* SPEC Validation Rule: Schema-Validity Assessment (Element)
26069 	* (1.2.1.2.1) - (1.2.1.2.3 )
26070 	*
26071 	* Use the xsi:type attribute for the type definition.
26072 	*/
26073 	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
26074 	    XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
26075 	if (iattr != NULL) {
26076 	    if (xmlSchemaProcessXSIType(vctxt, iattr,
26077 		&(vctxt->inode->typeDef), NULL) == -1) {
26078 		VERROR_INT("xmlSchemaValidateElemWildcard",
26079 		    "calling xmlSchemaProcessXSIType() to "
26080 		    "process the attribute 'xsi:nil'");
26081 		return (-1);
26082 	    }
26083 	    /*
26084 	    * Don't return an error on purpose.
26085 	    */
26086 	    return (0);
26087 	}
26088     }
26089     /*
26090     * SPEC Validation Rule: Schema-Validity Assessment (Element)
26091     *
26092     * Fallback to "anyType".
26093     */
26094     vctxt->inode->typeDef =
26095 	xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
26096     return (0);
26097 }
26098 
26099 /*
26100 * xmlSchemaCheckCOSValidDefault:
26101 *
26102 * This will be called if: not nilled, no content and a default/fixed
26103 * value is provided.
26104 */
26105 
26106 static int
xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,const xmlChar * value,xmlSchemaValPtr * val)26107 xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
26108 			      const xmlChar *value,
26109 			      xmlSchemaValPtr *val)
26110 {
26111     int ret = 0;
26112     xmlSchemaNodeInfoPtr inode = vctxt->inode;
26113 
26114     /*
26115     * cos-valid-default:
26116     * Schema Component Constraint: Element Default Valid (Immediate)
26117     * For a string to be a valid default with respect to a type
26118     * definition the appropriate case among the following must be true:
26119     */
26120     if WXS_IS_COMPLEX(inode->typeDef) {
26121 	/*
26122 	* Complex type.
26123 	*
26124 	* SPEC (2.1) "its {content type} must be a simple type definition
26125 	* or mixed."
26126 	* SPEC (2.2.2) "If the {content type} is mixed, then the {content
26127 	* type}'s particle must be `emptiable` as defined by
26128 	* Particle Emptiable ($3.9.6)."
26129 	*/
26130 	if ((! WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) &&
26131 	    ((! WXS_HAS_MIXED_CONTENT(inode->typeDef)) ||
26132 	     (! WXS_EMPTIABLE(inode->typeDef)))) {
26133 	    ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
26134 	    /* NOTE that this covers (2.2.2) as well. */
26135 	    VERROR(ret, NULL,
26136 		"For a string to be a valid default, the type definition "
26137 		"must be a simple type or a complex type with simple content "
26138 		"or mixed content and a particle emptiable");
26139 	    return(ret);
26140 	}
26141     }
26142     /*
26143     * 1 If the type definition is a simple type definition, then the string
26144     * must be `valid` with respect to that definition as defined by String
26145     * Valid ($3.14.4).
26146     *
26147     * AND
26148     *
26149     * 2.2.1 If the {content type} is a simple type definition, then the
26150     * string must be `valid` with respect to that simple type definition
26151     * as defined by String Valid ($3.14.4).
26152     */
26153     if (WXS_IS_SIMPLE(inode->typeDef)) {
26154 
26155 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
26156 	    NULL, inode->typeDef, value, val, 1, 1, 0);
26157 
26158     } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26159 
26160 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
26161 	    NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
26162     }
26163     if (ret < 0) {
26164 	VERROR_INT("xmlSchemaCheckCOSValidDefault",
26165 	    "calling xmlSchemaVCheckCVCSimpleType()");
26166     }
26167     return (ret);
26168 }
26169 
26170 static void
xmlSchemaVContentModelCallback(xmlRegExecCtxtPtr exec ATTRIBUTE_UNUSED,const xmlChar * name ATTRIBUTE_UNUSED,void * transdata,void * inputdata)26171 xmlSchemaVContentModelCallback(xmlRegExecCtxtPtr exec ATTRIBUTE_UNUSED,
26172 			       const xmlChar * name ATTRIBUTE_UNUSED,
26173 			       void *transdata, void *inputdata)
26174 {
26175     xmlSchemaElementPtr item = (xmlSchemaElementPtr) transdata;
26176     xmlSchemaNodeInfoPtr inode = (xmlSchemaNodeInfoPtr) inputdata;
26177     inode->decl = item;
26178 #ifdef DEBUG_CONTENT
26179     {
26180 	xmlChar *str = NULL;
26181 
26182 	if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
26183 	    xmlGenericError(xmlGenericErrorContext,
26184 		"AUTOMATON callback for '%s' [declaration]\n",
26185 		xmlSchemaFormatQName(&str,
26186 		inode->localName, inode->nsName));
26187 	} else {
26188 	    xmlGenericError(xmlGenericErrorContext,
26189 		    "AUTOMATON callback for '%s' [wildcard]\n",
26190 		    xmlSchemaFormatQName(&str,
26191 		    inode->localName, inode->nsName));
26192 
26193 	}
26194 	FREE_AND_NULL(str)
26195     }
26196 #endif
26197 }
26198 
26199 static int
xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)26200 xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
26201 {
26202     vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
26203     if (vctxt->inode == NULL) {
26204 	VERROR_INT("xmlSchemaValidatorPushElem",
26205 	    "calling xmlSchemaGetFreshElemInfo()");
26206 	return (-1);
26207     }
26208     vctxt->nbAttrInfos = 0;
26209     return (0);
26210 }
26211 
26212 static int
xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,xmlSchemaNodeInfoPtr inode,xmlSchemaTypePtr type,const xmlChar * value)26213 xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
26214 			     xmlSchemaNodeInfoPtr inode,
26215 			     xmlSchemaTypePtr type,
26216 			     const xmlChar *value)
26217 {
26218     if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
26219 	return (xmlSchemaVCheckCVCSimpleType(
26220 	    ACTXT_CAST vctxt, NULL,
26221 	    type, value, &(inode->val), 1, 1, 0));
26222     else
26223 	return (xmlSchemaVCheckCVCSimpleType(
26224 	    ACTXT_CAST vctxt, NULL,
26225 	    type, value, NULL, 1, 0, 0));
26226 }
26227 
26228 
26229 
26230 /*
26231 * Process END of element.
26232 */
26233 static int
xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)26234 xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
26235 {
26236     int ret = 0;
26237     xmlSchemaNodeInfoPtr inode = vctxt->inode;
26238 
26239     if (vctxt->nbAttrInfos != 0)
26240 	xmlSchemaClearAttrInfos(vctxt);
26241     if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
26242 	/*
26243 	* This element was not expected;
26244 	* we will not validate child elements of broken parents.
26245 	* Skip validation of all content of the parent.
26246 	*/
26247 	vctxt->skipDepth = vctxt->depth -1;
26248 	goto end_elem;
26249     }
26250     if ((inode->typeDef == NULL) ||
26251 	(inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
26252 	/*
26253 	* 1. the type definition might be missing if the element was
26254 	*    error prone
26255 	* 2. it might be abstract.
26256 	*/
26257 	goto end_elem;
26258     }
26259     /*
26260     * Check the content model.
26261     */
26262     if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
26263 	(inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
26264 
26265 	/*
26266 	* Workaround for "anyType".
26267 	*/
26268 	if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
26269 	    goto character_content;
26270 
26271 	if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
26272 	    xmlChar *values[10];
26273 	    int terminal, nbval = 10, nbneg;
26274 
26275 	    if (inode->regexCtxt == NULL) {
26276 		/*
26277 		* Create the regex context.
26278 		*/
26279 		inode->regexCtxt =
26280 		    xmlRegNewExecCtxt(inode->typeDef->contModel,
26281 		    xmlSchemaVContentModelCallback, vctxt);
26282 		if (inode->regexCtxt == NULL) {
26283 		    VERROR_INT("xmlSchemaValidatorPopElem",
26284 			"failed to create a regex context");
26285 		    goto internal_error;
26286 		}
26287 #ifdef DEBUG_AUTOMATA
26288 		xmlGenericError(xmlGenericErrorContext,
26289 		    "AUTOMATON create on '%s'\n", inode->localName);
26290 #endif
26291 	    }
26292 
26293 	    /*
26294 	     * Do not check further content if the node has been nilled
26295 	     */
26296 	    if (INODE_NILLED(inode)) {
26297 		ret = 0;
26298 #ifdef DEBUG_AUTOMATA
26299 		xmlGenericError(xmlGenericErrorContext,
26300 		    "AUTOMATON succeeded on nilled '%s'\n",
26301 		    inode->localName);
26302 #endif
26303                 goto skip_nilled;
26304 	    }
26305 
26306 	    /*
26307 	    * Get hold of the still expected content, since a further
26308 	    * call to xmlRegExecPushString() will lose this information.
26309 	    */
26310 	    xmlRegExecNextValues(inode->regexCtxt,
26311 		&nbval, &nbneg, &values[0], &terminal);
26312 	    ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
26313 	    if ((ret<0) || ((ret==0) && (!INODE_NILLED(inode)))) {
26314 		/*
26315 		* Still missing something.
26316 		*/
26317 		ret = 1;
26318 		inode->flags |=
26319 		    XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26320 		xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26321 		    XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
26322 		    "Missing child element(s)",
26323 		    nbval, nbneg, values);
26324 #ifdef DEBUG_AUTOMATA
26325 		xmlGenericError(xmlGenericErrorContext,
26326 		    "AUTOMATON missing ERROR on '%s'\n",
26327 		    inode->localName);
26328 #endif
26329 	    } else {
26330 		/*
26331 		* Content model is satisfied.
26332 		*/
26333 		ret = 0;
26334 #ifdef DEBUG_AUTOMATA
26335 		xmlGenericError(xmlGenericErrorContext,
26336 		    "AUTOMATON succeeded on '%s'\n",
26337 		    inode->localName);
26338 #endif
26339 	    }
26340 
26341 	}
26342     }
26343 
26344 skip_nilled:
26345 
26346     if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
26347 	goto end_elem;
26348 
26349 character_content:
26350 
26351     if (vctxt->value != NULL) {
26352 	xmlSchemaFreeValue(vctxt->value);
26353 	vctxt->value = NULL;
26354     }
26355     /*
26356     * Check character content.
26357     */
26358     if (inode->decl == NULL) {
26359 	/*
26360 	* Speedup if no declaration exists.
26361 	*/
26362 	if (WXS_IS_SIMPLE(inode->typeDef)) {
26363 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26364 		inode, inode->typeDef, inode->value);
26365 	} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26366 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26367 		inode, inode->typeDef->contentTypeDef,
26368 		inode->value);
26369 	}
26370 	if (ret < 0) {
26371 	    VERROR_INT("xmlSchemaValidatorPopElem",
26372 		"calling xmlSchemaVCheckCVCSimpleType()");
26373 	    goto internal_error;
26374 	}
26375 	goto end_elem;
26376     }
26377     /*
26378     * cvc-elt (3.3.4) : 5
26379     * The appropriate case among the following must be true:
26380     */
26381     /*
26382     * cvc-elt (3.3.4) : 5.1
26383     * If the declaration has a {value constraint},
26384     * the item has neither element nor character [children] and
26385     * clause 3.2 has not applied, then all of the following must be true:
26386     */
26387     if ((inode->decl->value != NULL) &&
26388 	(inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
26389 	(! INODE_NILLED(inode))) {
26390 	/*
26391 	* cvc-elt (3.3.4) : 5.1.1
26392 	* If the `actual type definition` is a `local type definition`
26393 	* then the canonical lexical representation of the {value constraint}
26394 	* value must be a valid default for the `actual type definition` as
26395 	* defined in Element Default Valid (Immediate) ($3.3.6).
26396 	*/
26397 	/*
26398 	* NOTE: 'local' above means types acquired by xsi:type.
26399 	* NOTE: Although the *canonical* value is stated, it is not
26400 	* relevant if canonical or not. Additionally XML Schema 1.1
26401 	* will removed this requirement as well.
26402 	*/
26403 	if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
26404 
26405 	    ret = xmlSchemaCheckCOSValidDefault(vctxt,
26406 		inode->decl->value, &(inode->val));
26407 	    if (ret != 0) {
26408 		if (ret < 0) {
26409 		    VERROR_INT("xmlSchemaValidatorPopElem",
26410 			"calling xmlSchemaCheckCOSValidDefault()");
26411 		    goto internal_error;
26412 		}
26413 		goto end_elem;
26414 	    }
26415 	    /*
26416 	    * Stop here, to avoid redundant validation of the value
26417 	    * (see following).
26418 	    */
26419 	    goto default_psvi;
26420 	}
26421 	/*
26422 	* cvc-elt (3.3.4) : 5.1.2
26423 	* The element information item with the canonical lexical
26424 	* representation of the {value constraint} value used as its
26425 	* `normalized value` must be `valid` with respect to the
26426 	* `actual type definition` as defined by Element Locally Valid (Type)
26427 	* ($3.3.4).
26428 	*/
26429 	if (WXS_IS_SIMPLE(inode->typeDef)) {
26430 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26431 		inode, inode->typeDef, inode->decl->value);
26432 	} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26433 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26434 		inode, inode->typeDef->contentTypeDef,
26435 		inode->decl->value);
26436 	}
26437 	if (ret != 0) {
26438 	    if (ret < 0) {
26439 		VERROR_INT("xmlSchemaValidatorPopElem",
26440 		    "calling xmlSchemaVCheckCVCSimpleType()");
26441 		goto internal_error;
26442 	    }
26443 	    goto end_elem;
26444 	}
26445 
26446 default_psvi:
26447 	/*
26448 	* PSVI: Create a text node on the instance element.
26449 	*/
26450 	if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
26451 	    (inode->node != NULL)) {
26452 	    xmlNodePtr textChild;
26453 	    xmlChar *normValue;
26454 	    /*
26455 	    * VAL TODO: Normalize the value.
26456 	    */
26457 	    normValue = xmlSchemaNormalizeValue(inode->typeDef,
26458 		inode->decl->value);
26459 	    if (normValue != NULL) {
26460 		textChild = xmlNewText(BAD_CAST normValue);
26461 		xmlFree(normValue);
26462 	    } else
26463 		textChild = xmlNewText(inode->decl->value);
26464 	    if (textChild == NULL) {
26465 		VERROR_INT("xmlSchemaValidatorPopElem",
26466 		    "calling xmlNewText()");
26467 		goto internal_error;
26468 	    } else
26469 		xmlAddChild(inode->node, textChild);
26470 	}
26471 
26472     } else if (! INODE_NILLED(inode)) {
26473 	/*
26474 	* 5.2.1 The element information item must be `valid` with respect
26475 	* to the `actual type definition` as defined by Element Locally
26476 	* Valid (Type) ($3.3.4).
26477 	*/
26478 	if (WXS_IS_SIMPLE(inode->typeDef)) {
26479 	     /*
26480 	    * SPEC (cvc-type) (3.1)
26481 	    * "If the type definition is a simple type definition, ..."
26482 	    * (3.1.3) "If clause 3.2 of Element Locally Valid
26483 	    * (Element) ($3.3.4) did not apply, then the `normalized value`
26484 	    * must be `valid` with respect to the type definition as defined
26485 	    * by String Valid ($3.14.4).
26486 	    */
26487 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26488 		    inode, inode->typeDef, inode->value);
26489 	} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26490 	    /*
26491 	    * SPEC (cvc-type) (3.2) "If the type definition is a complex type
26492 	    * definition, then the element information item must be
26493 	    * `valid` with respect to the type definition as per
26494 	    * Element Locally Valid (Complex Type) ($3.4.4);"
26495 	    *
26496 	    * SPEC (cvc-complex-type) (2.2)
26497 	    * "If the {content type} is a simple type definition, ...
26498 	    * the `normalized value` of the element information item is
26499 	    * `valid` with respect to that simple type definition as
26500 	    * defined by String Valid ($3.14.4)."
26501 	    */
26502 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26503 		inode, inode->typeDef->contentTypeDef, inode->value);
26504 	}
26505 	if (ret != 0) {
26506 	    if (ret < 0) {
26507 		VERROR_INT("xmlSchemaValidatorPopElem",
26508 		    "calling xmlSchemaVCheckCVCSimpleType()");
26509 		goto internal_error;
26510 	    }
26511 	    goto end_elem;
26512 	}
26513 	/*
26514 	* 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
26515 	* not applied, all of the following must be true:
26516 	*/
26517 	if ((inode->decl->value != NULL) &&
26518 	    (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
26519 
26520 	    /*
26521 	    * TODO: We will need a computed value, when comparison is
26522 	    * done on computed values.
26523 	    */
26524 	    /*
26525 	    * 5.2.2.1 The element information item must have no element
26526 	    * information item [children].
26527 	    */
26528 	    if (inode->flags &
26529 		    XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
26530 		ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
26531 		VERROR(ret, NULL,
26532 		    "The content must not contain element nodes since "
26533 		    "there is a fixed value constraint");
26534 		goto end_elem;
26535 	    } else {
26536 		/*
26537 		* 5.2.2.2 The appropriate case among the following must
26538 		* be true:
26539 		*/
26540 		if (WXS_HAS_MIXED_CONTENT(inode->typeDef)) {
26541 		    /*
26542 		    * 5.2.2.2.1 If the {content type} of the `actual type
26543 		    * definition` is mixed, then the *initial value* of the
26544 		    * item must match the canonical lexical representation
26545 		    * of the {value constraint} value.
26546 		    *
26547 		    * ... the *initial value* of an element information
26548 		    * item is the string composed of, in order, the
26549 		    * [character code] of each character information item in
26550 		    * the [children] of that element information item.
26551 		    */
26552 		    if (! xmlStrEqual(inode->value, inode->decl->value)){
26553 			/*
26554 			* VAL TODO: Report invalid & expected values as well.
26555 			* VAL TODO: Implement the canonical stuff.
26556 			*/
26557 			ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
26558 			xmlSchemaCustomErr(ACTXT_CAST vctxt,
26559 			    ret, NULL, NULL,
26560 			    "The initial value '%s' does not match the fixed "
26561 			    "value constraint '%s'",
26562 			    inode->value, inode->decl->value);
26563 			goto end_elem;
26564 		    }
26565 		} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26566 		    /*
26567 		    * 5.2.2.2.2 If the {content type} of the `actual type
26568 		    * definition` is a simple type definition, then the
26569 		    * *actual value* of the item must match the canonical
26570 		    * lexical representation of the {value constraint} value.
26571 		    */
26572 		    /*
26573 		    * VAL TODO: *actual value* is the normalized value, impl.
26574 		    *           this.
26575 		    * VAL TODO: Report invalid & expected values as well.
26576 		    * VAL TODO: Implement a comparison with the computed values.
26577 		    */
26578 		    if (! xmlStrEqual(inode->value,
26579 			    inode->decl->value)) {
26580 			ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
26581 			xmlSchemaCustomErr(ACTXT_CAST vctxt,
26582 			    ret, NULL, NULL,
26583 			    "The actual value '%s' does not match the fixed "
26584 			    "value constraint '%s'",
26585 			    inode->value,
26586 			    inode->decl->value);
26587 			goto end_elem;
26588 		    }
26589 		}
26590 	    }
26591 	}
26592     }
26593 
26594 end_elem:
26595     if (vctxt->depth < 0) {
26596 	/* TODO: raise error? */
26597 	return (0);
26598     }
26599     if (vctxt->depth == vctxt->skipDepth)
26600 	vctxt->skipDepth = -1;
26601     /*
26602     * Evaluate the history of XPath state objects.
26603     */
26604     if (inode->appliedXPath &&
26605 	(xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1))
26606 	goto internal_error;
26607     /*
26608     * MAYBE TODO:
26609     * SPEC (6) "The element information item must be `valid` with
26610     * respect to each of the {identity-constraint definitions} as per
26611     * Identity-constraint Satisfied ($3.11.4)."
26612     */
26613     /*
26614     * PSVI TODO: If we expose IDC node-tables via PSVI then the tables
26615     *   need to be built in any case.
26616     *   We will currently build IDC node-tables and bubble them only if
26617     *   keyrefs do exist.
26618     */
26619 
26620     /*
26621     * Add the current IDC target-nodes to the IDC node-tables.
26622     */
26623     if ((inode->idcMatchers != NULL) &&
26624 	(vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26625     {
26626 	if (xmlSchemaIDCFillNodeTables(vctxt, inode) == -1)
26627 	    goto internal_error;
26628     }
26629     /*
26630     * Validate IDC keyrefs.
26631     */
26632     if (vctxt->inode->hasKeyrefs)
26633 	if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
26634 	    goto internal_error;
26635     /*
26636     * Merge/free the IDC table.
26637     */
26638     if (inode->idcTable != NULL) {
26639 #ifdef DEBUG_IDC_NODE_TABLE
26640 	xmlSchemaDebugDumpIDCTable(stdout,
26641 	    inode->nsName,
26642 	    inode->localName,
26643 	    inode->idcTable);
26644 #endif
26645 	if ((vctxt->depth > 0) &&
26646 	    (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26647 	{
26648 	    /*
26649 	    * Merge the IDC node table with the table of the parent node.
26650 	    */
26651 	    if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
26652 		goto internal_error;
26653 	}
26654     }
26655     /*
26656     * Clear the current ielem.
26657     * VAL TODO: Don't free the PSVI IDC tables if they are
26658     * requested for the PSVI.
26659     */
26660     xmlSchemaClearElemInfo(vctxt, inode);
26661     /*
26662     * Skip further processing if we are on the validation root.
26663     */
26664     if (vctxt->depth == 0) {
26665 	vctxt->depth--;
26666 	vctxt->inode = NULL;
26667 	return (0);
26668     }
26669     /*
26670     * Reset the keyrefDepth if needed.
26671     */
26672     if (vctxt->aidcs != NULL) {
26673 	xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
26674 	do {
26675 	    if (aidc->keyrefDepth == vctxt->depth) {
26676 		/*
26677 		* A 'keyrefDepth' of a key/unique IDC matches the current
26678 		* depth, this means that we are leaving the scope of the
26679 		* top-most keyref IDC which refers to this IDC.
26680 		*/
26681 		aidc->keyrefDepth = -1;
26682 	    }
26683 	    aidc = aidc->next;
26684 	} while (aidc != NULL);
26685     }
26686     vctxt->depth--;
26687     vctxt->inode = vctxt->elemInfos[vctxt->depth];
26688     /*
26689     * VAL TODO: 7 If the element information item is the `validation root`, it must be
26690     * `valid` per Validation Root Valid (ID/IDREF) ($3.3.4).
26691     */
26692     return (ret);
26693 
26694 internal_error:
26695     vctxt->err = -1;
26696     return (-1);
26697 }
26698 
26699 /*
26700 * 3.4.4 Complex Type Definition Validation Rules
26701 * Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
26702 */
26703 static int
xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)26704 xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
26705 {
26706     xmlSchemaNodeInfoPtr pielem;
26707     xmlSchemaTypePtr ptype;
26708     int ret = 0;
26709 
26710     if (vctxt->depth <= 0) {
26711 	VERROR_INT("xmlSchemaValidateChildElem",
26712 	    "not intended for the validation root");
26713 	return (-1);
26714     }
26715     pielem = vctxt->elemInfos[vctxt->depth -1];
26716     if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26717 	pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26718     /*
26719     * Handle 'nilled' elements.
26720     */
26721     if (INODE_NILLED(pielem)) {
26722 	/*
26723 	* SPEC (cvc-elt) (3.3.4) : (3.2.1)
26724 	*/
26725 	ACTIVATE_PARENT_ELEM;
26726 	ret = XML_SCHEMAV_CVC_ELT_3_2_1;
26727 	VERROR(ret, NULL,
26728 	    "Neither character nor element content is allowed, "
26729 	    "because the element was 'nilled'");
26730 	ACTIVATE_ELEM;
26731 	goto unexpected_elem;
26732     }
26733 
26734     ptype = pielem->typeDef;
26735 
26736     if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
26737 	/*
26738 	* Workaround for "anyType": we have currently no content model
26739 	* assigned for "anyType", so handle it explicitly.
26740 	* "anyType" has an unbounded, lax "any" wildcard.
26741 	*/
26742 	vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26743 	    vctxt->inode->localName,
26744 	    vctxt->inode->nsName);
26745 
26746 	if (vctxt->inode->decl == NULL) {
26747 	    xmlSchemaAttrInfoPtr iattr;
26748 	    /*
26749 	    * Process "xsi:type".
26750 	    * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
26751 	    */
26752 	    iattr = xmlSchemaGetMetaAttrInfo(vctxt,
26753 		XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
26754 	    if (iattr != NULL) {
26755 		ret = xmlSchemaProcessXSIType(vctxt, iattr,
26756 		    &(vctxt->inode->typeDef), NULL);
26757 		if (ret != 0) {
26758 		    if (ret == -1) {
26759 			VERROR_INT("xmlSchemaValidateChildElem",
26760 			    "calling xmlSchemaProcessXSIType() to "
26761 			    "process the attribute 'xsi:nil'");
26762 			return (-1);
26763 		    }
26764 		    return (ret);
26765 		}
26766 	    } else {
26767 		 /*
26768 		 * Fallback to "anyType".
26769 		 *
26770 		 * SPEC (cvc-assess-elt)
26771 		 * "If the item cannot be `strictly assessed`, [...]
26772 		 * an element information item's schema validity may be laxly
26773 		 * assessed if its `context-determined declaration` is not
26774 		 * skip by `validating` with respect to the `ur-type
26775 		 * definition` as per Element Locally Valid (Type) ($3.3.4)."
26776 		*/
26777 		vctxt->inode->typeDef =
26778 		    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
26779 	    }
26780 	}
26781 	return (0);
26782     }
26783 
26784     switch (ptype->contentType) {
26785 	case XML_SCHEMA_CONTENT_EMPTY:
26786 	    /*
26787 	    * SPEC (2.1) "If the {content type} is empty, then the
26788 	    * element information item has no character or element
26789 	    * information item [children]."
26790 	    */
26791 	    ACTIVATE_PARENT_ELEM
26792 	    ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
26793 	    VERROR(ret, NULL,
26794 		"Element content is not allowed, "
26795 		"because the content type is empty");
26796 	    ACTIVATE_ELEM
26797 	    goto unexpected_elem;
26798 	    break;
26799 
26800 	case XML_SCHEMA_CONTENT_MIXED:
26801         case XML_SCHEMA_CONTENT_ELEMENTS: {
26802 	    xmlRegExecCtxtPtr regexCtxt;
26803 	    xmlChar *values[10];
26804 	    int terminal, nbval = 10, nbneg;
26805 
26806 	    /* VAL TODO: Optimized "anyType" validation.*/
26807 
26808 	    if (ptype->contModel == NULL) {
26809 		VERROR_INT("xmlSchemaValidateChildElem",
26810 		    "type has elem content but no content model");
26811 		return (-1);
26812 	    }
26813 	    /*
26814 	    * Safety belt for evaluation if the cont. model was already
26815 	    * examined to be invalid.
26816 	    */
26817 	    if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
26818 		VERROR_INT("xmlSchemaValidateChildElem",
26819 		    "validating elem, but elem content is already invalid");
26820 		return (-1);
26821 	    }
26822 
26823 	    regexCtxt = pielem->regexCtxt;
26824 	    if (regexCtxt == NULL) {
26825 		/*
26826 		* Create the regex context.
26827 		*/
26828 		regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
26829 		    xmlSchemaVContentModelCallback, vctxt);
26830 		if (regexCtxt == NULL) {
26831 		    VERROR_INT("xmlSchemaValidateChildElem",
26832 			"failed to create a regex context");
26833 		    return (-1);
26834 		}
26835 		pielem->regexCtxt = regexCtxt;
26836 #ifdef DEBUG_AUTOMATA
26837 		xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
26838 		    pielem->localName);
26839 #endif
26840 	    }
26841 
26842 	    /*
26843 	    * SPEC (2.4) "If the {content type} is element-only or mixed,
26844 	    * then the sequence of the element information item's
26845 	    * element information item [children], if any, taken in
26846 	    * order, is `valid` with respect to the {content type}'s
26847 	    * particle, as defined in Element Sequence Locally Valid
26848 	    * (Particle) ($3.9.4)."
26849 	    */
26850 	    ret = xmlRegExecPushString2(regexCtxt,
26851 		vctxt->inode->localName,
26852 		vctxt->inode->nsName,
26853 		vctxt->inode);
26854 #ifdef DEBUG_AUTOMATA
26855 	    if (ret < 0)
26856 		xmlGenericError(xmlGenericErrorContext,
26857 		"AUTOMATON push ERROR for '%s' on '%s'\n",
26858 		vctxt->inode->localName, pielem->localName);
26859 	    else
26860 		xmlGenericError(xmlGenericErrorContext,
26861 		"AUTOMATON push OK for '%s' on '%s'\n",
26862 		vctxt->inode->localName, pielem->localName);
26863 #endif
26864 	    if (vctxt->err == XML_SCHEMAV_INTERNAL) {
26865 		VERROR_INT("xmlSchemaValidateChildElem",
26866 		    "calling xmlRegExecPushString2()");
26867 		return (-1);
26868 	    }
26869 	    if (ret < 0) {
26870 		xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
26871 		    &values[0], &terminal);
26872 		xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26873 		    XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
26874 		    "This element is not expected",
26875 		    nbval, nbneg, values);
26876 		ret = vctxt->err;
26877 		goto unexpected_elem;
26878 	    } else
26879 		ret = 0;
26880 	}
26881 	    break;
26882 	case XML_SCHEMA_CONTENT_SIMPLE:
26883 	case XML_SCHEMA_CONTENT_BASIC:
26884 	    ACTIVATE_PARENT_ELEM
26885 	    if (WXS_IS_COMPLEX(ptype)) {
26886 		/*
26887 		* SPEC (cvc-complex-type) (2.2)
26888 		* "If the {content type} is a simple type definition, then
26889 		* the element information item has no element information
26890 		* item [children], ..."
26891 		*/
26892 		ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
26893 		VERROR(ret, NULL, "Element content is not allowed, "
26894 		    "because the content type is a simple type definition");
26895 	    } else {
26896 		/*
26897 		* SPEC (cvc-type) (3.1.2) "The element information item must
26898 		* have no element information item [children]."
26899 		*/
26900 		ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
26901 		VERROR(ret, NULL, "Element content is not allowed, "
26902 		    "because the type definition is simple");
26903 	    }
26904 	    ACTIVATE_ELEM
26905 	    ret = vctxt->err;
26906 	    goto unexpected_elem;
26907 	    break;
26908 
26909 	default:
26910 	    break;
26911     }
26912     return (ret);
26913 unexpected_elem:
26914     /*
26915     * Pop this element and set the skipDepth to skip
26916     * all further content of the parent element.
26917     */
26918     vctxt->skipDepth = vctxt->depth;
26919     vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
26920     pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26921     return (ret);
26922 }
26923 
26924 #define XML_SCHEMA_PUSH_TEXT_PERSIST 1
26925 #define XML_SCHEMA_PUSH_TEXT_CREATED 2
26926 #define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
26927 
26928 static int
xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,int nodeType,const xmlChar * value,int len,int mode,int * consumed)26929 xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
26930 		  int nodeType, const xmlChar *value, int len,
26931 		  int mode, int *consumed)
26932 {
26933     /*
26934     * Unfortunately we have to duplicate the text sometimes.
26935     * OPTIMIZE: Maybe we could skip it, if:
26936     *   1. content type is simple
26937     *   2. whitespace is "collapse"
26938     *   3. it consists of whitespace only
26939     *
26940     * Process character content.
26941     */
26942     if (consumed != NULL)
26943 	*consumed = 0;
26944     if (INODE_NILLED(vctxt->inode)) {
26945 	/*
26946 	* SPEC cvc-elt (3.3.4 - 3.2.1)
26947 	* "The element information item must have no character or
26948 	* element information item [children]."
26949 	*/
26950 	VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
26951 	    "Neither character nor element content is allowed "
26952 	    "because the element is 'nilled'");
26953 	return (vctxt->err);
26954     }
26955     /*
26956     * SPEC (2.1) "If the {content type} is empty, then the
26957     * element information item has no character or element
26958     * information item [children]."
26959     */
26960     if (vctxt->inode->typeDef->contentType ==
26961 	    XML_SCHEMA_CONTENT_EMPTY) {
26962 	VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
26963 	    "Character content is not allowed, "
26964 	    "because the content type is empty");
26965 	return (vctxt->err);
26966     }
26967 
26968     if (vctxt->inode->typeDef->contentType ==
26969 	    XML_SCHEMA_CONTENT_ELEMENTS) {
26970 	if ((nodeType != XML_TEXT_NODE) ||
26971 	    (! xmlSchemaIsBlank((xmlChar *) value, len))) {
26972 	    /*
26973 	    * SPEC cvc-complex-type (2.3)
26974 	    * "If the {content type} is element-only, then the
26975 	    * element information item has no character information
26976 	    * item [children] other than those whose [character
26977 	    * code] is defined as a white space in [XML 1.0 (Second
26978 	    * Edition)]."
26979 	    */
26980 	    VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
26981 		"Character content other than whitespace is not allowed "
26982 		"because the content type is 'element-only'");
26983 	    return (vctxt->err);
26984 	}
26985 	return (0);
26986     }
26987 
26988     if ((value == NULL) || (value[0] == 0))
26989 	return (0);
26990     /*
26991     * Save the value.
26992     * NOTE that even if the content type is *mixed*, we need the
26993     * *initial value* for default/fixed value constraints.
26994     */
26995     if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
26996 	((vctxt->inode->decl == NULL) ||
26997 	(vctxt->inode->decl->value == NULL)))
26998 	return (0);
26999 
27000     if (vctxt->inode->value == NULL) {
27001 	/*
27002 	* Set the value.
27003 	*/
27004 	switch (mode) {
27005 	    case XML_SCHEMA_PUSH_TEXT_PERSIST:
27006 		/*
27007 		* When working on a tree.
27008 		*/
27009 		vctxt->inode->value = value;
27010 		break;
27011 	    case XML_SCHEMA_PUSH_TEXT_CREATED:
27012 		/*
27013 		* When working with the reader.
27014 		* The value will be freed by the element info.
27015 		*/
27016 		vctxt->inode->value = value;
27017 		if (consumed != NULL)
27018 		    *consumed = 1;
27019 		vctxt->inode->flags |=
27020 		    XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
27021 		break;
27022 	    case XML_SCHEMA_PUSH_TEXT_VOLATILE:
27023 		/*
27024 		* When working with SAX.
27025 		* The value will be freed by the element info.
27026 		*/
27027 		if (len != -1)
27028 		    vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
27029 		else
27030 		    vctxt->inode->value = BAD_CAST xmlStrdup(value);
27031 		vctxt->inode->flags |=
27032 		    XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
27033 		break;
27034 	    default:
27035 		break;
27036 	}
27037     } else {
27038 	if (len < 0)
27039 	    len = xmlStrlen(value);
27040 	/*
27041 	* Concat the value.
27042 	*/
27043 	if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
27044 	    vctxt->inode->value = BAD_CAST xmlStrncat(
27045 		(xmlChar *) vctxt->inode->value, value, len);
27046 	} else {
27047 	    vctxt->inode->value =
27048 		BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
27049 	    vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
27050 	}
27051     }
27052 
27053     return (0);
27054 }
27055 
27056 static int
xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)27057 xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
27058 {
27059     int ret = 0;
27060 
27061     if ((vctxt->skipDepth != -1) &&
27062 	(vctxt->depth >= vctxt->skipDepth)) {
27063 	VERROR_INT("xmlSchemaValidateElem",
27064 	    "in skip-state");
27065 	goto internal_error;
27066     }
27067     if (vctxt->xsiAssemble) {
27068 	/*
27069 	* We will stop validation if there was an error during
27070 	* dynamic schema construction.
27071 	* Note that we simply set @skipDepth to 0, this could
27072 	* mean that a streaming document via SAX would be
27073 	* still read to the end but it won't be validated any more.
27074 	* TODO: If we are sure how to stop the validation at once
27075 	*   for all input scenarios, then this should be changed to
27076 	*   instantly stop the validation.
27077 	*/
27078 	ret = xmlSchemaAssembleByXSI(vctxt);
27079 	if (ret != 0) {
27080 	    if (ret == -1)
27081 		goto internal_error;
27082 	    vctxt->skipDepth = 0;
27083 	    return(ret);
27084 	}
27085         /*
27086          * Augment the IDC definitions for the main schema and all imported ones
27087          * NOTE: main schema is the first in the imported list
27088          */
27089         xmlHashScan(vctxt->schema->schemasImports, xmlSchemaAugmentImportedIDC,
27090                     vctxt);
27091     }
27092     if (vctxt->depth > 0) {
27093 	/*
27094 	* Validate this element against the content model
27095 	* of the parent.
27096 	*/
27097 	ret = xmlSchemaValidateChildElem(vctxt);
27098 	if (ret != 0) {
27099 	    if (ret < 0) {
27100 		VERROR_INT("xmlSchemaValidateElem",
27101 		    "calling xmlSchemaStreamValidateChildElement()");
27102 		goto internal_error;
27103 	    }
27104 	    goto exit;
27105 	}
27106 	if (vctxt->depth == vctxt->skipDepth)
27107 	    goto exit;
27108 	if ((vctxt->inode->decl == NULL) &&
27109 	    (vctxt->inode->typeDef == NULL)) {
27110 	    VERROR_INT("xmlSchemaValidateElem",
27111 		"the child element was valid but neither the "
27112 		"declaration nor the type was set");
27113 	    goto internal_error;
27114 	}
27115     } else {
27116 	/*
27117 	* Get the declaration of the validation root.
27118 	*/
27119 	vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
27120 	    vctxt->inode->localName,
27121 	    vctxt->inode->nsName);
27122 	if (vctxt->inode->decl == NULL) {
27123 	    ret = XML_SCHEMAV_CVC_ELT_1;
27124 	    VERROR(ret, NULL,
27125 		"No matching global declaration available "
27126 		"for the validation root");
27127 	    goto exit;
27128 	}
27129     }
27130 
27131     if (vctxt->inode->decl == NULL)
27132 	goto type_validation;
27133 
27134     if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
27135 	int skip;
27136 	/*
27137 	* Wildcards.
27138 	*/
27139 	ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
27140 	if (ret != 0) {
27141 	    if (ret < 0) {
27142 		VERROR_INT("xmlSchemaValidateElem",
27143 		    "calling xmlSchemaValidateElemWildcard()");
27144 		goto internal_error;
27145 	    }
27146 	    goto exit;
27147 	}
27148 	if (skip) {
27149 	    vctxt->skipDepth = vctxt->depth;
27150 	    goto exit;
27151 	}
27152 	/*
27153 	* The declaration might be set by the wildcard validation,
27154 	* when the processContents is "lax" or "strict".
27155 	*/
27156 	if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
27157 	    /*
27158 	    * Clear the "decl" field to not confuse further processing.
27159 	    */
27160 	    vctxt->inode->decl = NULL;
27161 	    goto type_validation;
27162 	}
27163     }
27164     /*
27165     * Validate against the declaration.
27166     */
27167     ret = xmlSchemaValidateElemDecl(vctxt);
27168     if (ret != 0) {
27169 	if (ret < 0) {
27170 	    VERROR_INT("xmlSchemaValidateElem",
27171 		"calling xmlSchemaValidateElemDecl()");
27172 	    goto internal_error;
27173 	}
27174 	goto exit;
27175     }
27176     /*
27177     * Validate against the type definition.
27178     */
27179 type_validation:
27180 
27181     if (vctxt->inode->typeDef == NULL) {
27182 	vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
27183 	ret = XML_SCHEMAV_CVC_TYPE_1;
27184 	VERROR(ret, NULL,
27185 	    "The type definition is absent");
27186 	goto exit;
27187     }
27188     if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
27189 	vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
27190 	ret = XML_SCHEMAV_CVC_TYPE_2;
27191 	    VERROR(ret, NULL,
27192 	    "The type definition is abstract");
27193 	goto exit;
27194     }
27195     /*
27196     * Evaluate IDCs. Do it here, since new IDC matchers are registered
27197     * during validation against the declaration. This must be done
27198     * _before_ attribute validation.
27199     */
27200     if (vctxt->xpathStates != NULL) {
27201 	ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
27202 	vctxt->inode->appliedXPath = 1;
27203 	if (ret == -1) {
27204 	    VERROR_INT("xmlSchemaValidateElem",
27205 		"calling xmlSchemaXPathEvaluate()");
27206 	    goto internal_error;
27207 	}
27208     }
27209     /*
27210     * Validate attributes.
27211     */
27212     if (WXS_IS_COMPLEX(vctxt->inode->typeDef)) {
27213 	if ((vctxt->nbAttrInfos != 0) ||
27214 	    (vctxt->inode->typeDef->attrUses != NULL)) {
27215 
27216 	    ret = xmlSchemaVAttributesComplex(vctxt);
27217 	}
27218     } else if (vctxt->nbAttrInfos != 0) {
27219 
27220 	ret = xmlSchemaVAttributesSimple(vctxt);
27221     }
27222     /*
27223     * Clear registered attributes.
27224     */
27225     if (vctxt->nbAttrInfos != 0)
27226 	xmlSchemaClearAttrInfos(vctxt);
27227     if (ret == -1) {
27228 	VERROR_INT("xmlSchemaValidateElem",
27229 	    "calling attributes validation");
27230 	goto internal_error;
27231     }
27232     /*
27233     * Don't return an error if attributes are invalid on purpose.
27234     */
27235     ret = 0;
27236 
27237 exit:
27238     if (ret != 0)
27239 	vctxt->skipDepth = vctxt->depth;
27240     return (ret);
27241 internal_error:
27242     return (-1);
27243 }
27244 
27245 #ifdef XML_SCHEMA_READER_ENABLED
27246 static int
xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)27247 xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
27248 {
27249     const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
27250     int depth, nodeType, ret = 0, consumed;
27251     xmlSchemaNodeInfoPtr ielem;
27252 
27253     vctxt->depth = -1;
27254     ret = xmlTextReaderRead(vctxt->reader);
27255     /*
27256     * Move to the document element.
27257     */
27258     while (ret == 1) {
27259 	nodeType = xmlTextReaderNodeType(vctxt->reader);
27260 	if (nodeType == XML_ELEMENT_NODE)
27261 	    goto root_found;
27262 	ret = xmlTextReaderRead(vctxt->reader);
27263     }
27264     goto exit;
27265 
27266 root_found:
27267 
27268     do {
27269 	depth = xmlTextReaderDepth(vctxt->reader);
27270 	nodeType = xmlTextReaderNodeType(vctxt->reader);
27271 
27272 	if (nodeType == XML_ELEMENT_NODE) {
27273 
27274 	    vctxt->depth++;
27275 	    if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27276 		VERROR_INT("xmlSchemaVReaderWalk",
27277 		    "calling xmlSchemaValidatorPushElem()");
27278 		goto internal_error;
27279 	    }
27280 	    ielem = vctxt->inode;
27281 	    ielem->localName = xmlTextReaderLocalName(vctxt->reader);
27282 	    ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
27283 	    ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
27284 	    /*
27285 	    * Is the element empty?
27286 	    */
27287 	    ret = xmlTextReaderIsEmptyElement(vctxt->reader);
27288 	    if (ret == -1) {
27289 		VERROR_INT("xmlSchemaVReaderWalk",
27290 		    "calling xmlTextReaderIsEmptyElement()");
27291 		goto internal_error;
27292 	    }
27293 	    if (ret) {
27294 		ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27295 	    }
27296 	    /*
27297 	    * Register attributes.
27298 	    */
27299 	    vctxt->nbAttrInfos = 0;
27300 	    ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
27301 	    if (ret == -1) {
27302 		VERROR_INT("xmlSchemaVReaderWalk",
27303 		    "calling xmlTextReaderMoveToFirstAttribute()");
27304 		goto internal_error;
27305 	    }
27306 	    if (ret == 1) {
27307 		do {
27308 		    /*
27309 		    * VAL TODO: How do we know that the reader works on a
27310 		    * node tree, to be able to pass a node here?
27311 		    */
27312 		    if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
27313 			(const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
27314 			xmlTextReaderNamespaceUri(vctxt->reader), 1,
27315 			xmlTextReaderValue(vctxt->reader), 1) == -1) {
27316 
27317 			VERROR_INT("xmlSchemaVReaderWalk",
27318 			    "calling xmlSchemaValidatorPushAttribute()");
27319 			goto internal_error;
27320 		    }
27321 		    ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
27322 		    if (ret == -1) {
27323 			VERROR_INT("xmlSchemaVReaderWalk",
27324 			    "calling xmlTextReaderMoveToFirstAttribute()");
27325 			goto internal_error;
27326 		    }
27327 		} while (ret == 1);
27328 		/*
27329 		* Back to element position.
27330 		*/
27331 		ret = xmlTextReaderMoveToElement(vctxt->reader);
27332 		if (ret == -1) {
27333 		    VERROR_INT("xmlSchemaVReaderWalk",
27334 			"calling xmlTextReaderMoveToElement()");
27335 		    goto internal_error;
27336 		}
27337 	    }
27338 	    /*
27339 	    * Validate the element.
27340 	    */
27341 	    ret= xmlSchemaValidateElem(vctxt);
27342 	    if (ret != 0) {
27343 		if (ret == -1) {
27344 		    VERROR_INT("xmlSchemaVReaderWalk",
27345 			"calling xmlSchemaValidateElem()");
27346 		    goto internal_error;
27347 		}
27348 		goto exit;
27349 	    }
27350 	    if (vctxt->depth == vctxt->skipDepth) {
27351 		int curDepth;
27352 		/*
27353 		* Skip all content.
27354 		*/
27355 		if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
27356 		    ret = xmlTextReaderRead(vctxt->reader);
27357 		    curDepth = xmlTextReaderDepth(vctxt->reader);
27358 		    while ((ret == 1) && (curDepth != depth)) {
27359 			ret = xmlTextReaderRead(vctxt->reader);
27360 			curDepth = xmlTextReaderDepth(vctxt->reader);
27361 		    }
27362 		    if (ret < 0) {
27363 			/*
27364 			* VAL TODO: A reader error occurred; what to do here?
27365 			*/
27366 			ret = 1;
27367 			goto exit;
27368 		    }
27369 		}
27370 		goto leave_elem;
27371 	    }
27372 	    /*
27373 	    * READER VAL TODO: Is an END_ELEM really never called
27374 	    * if the elem is empty?
27375 	    */
27376 	    if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27377 		goto leave_elem;
27378 	} else if (nodeType == END_ELEM) {
27379 	    /*
27380 	    * Process END of element.
27381 	    */
27382 leave_elem:
27383 	    ret = xmlSchemaValidatorPopElem(vctxt);
27384 	    if (ret != 0) {
27385 		if (ret < 0) {
27386 		    VERROR_INT("xmlSchemaVReaderWalk",
27387 			"calling xmlSchemaValidatorPopElem()");
27388 		    goto internal_error;
27389 		}
27390 		goto exit;
27391 	    }
27392 	    if (vctxt->depth >= 0)
27393 		ielem = vctxt->inode;
27394 	    else
27395 		ielem = NULL;
27396 	} else if ((nodeType == XML_TEXT_NODE) ||
27397 	    (nodeType == XML_CDATA_SECTION_NODE) ||
27398 	    (nodeType == WHTSP) ||
27399 	    (nodeType == SIGN_WHTSP)) {
27400 	    /*
27401 	    * Process character content.
27402 	    */
27403 	    xmlChar *value;
27404 
27405 	    if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
27406 		nodeType = XML_TEXT_NODE;
27407 
27408 	    value = xmlTextReaderValue(vctxt->reader);
27409 	    ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
27410 		-1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
27411 	    if (! consumed)
27412 		xmlFree(value);
27413 	    if (ret == -1) {
27414 		VERROR_INT("xmlSchemaVReaderWalk",
27415 		    "calling xmlSchemaVPushText()");
27416 		goto internal_error;
27417 	    }
27418 	} else if ((nodeType == XML_ENTITY_NODE) ||
27419 	    (nodeType == XML_ENTITY_REF_NODE)) {
27420 	    /*
27421 	    * VAL TODO: What to do with entities?
27422 	    */
27423 	    TODO
27424 	}
27425 	/*
27426 	* Read next node.
27427 	*/
27428 	ret = xmlTextReaderRead(vctxt->reader);
27429     } while (ret == 1);
27430 
27431 exit:
27432     return (ret);
27433 internal_error:
27434     return (-1);
27435 }
27436 #endif
27437 
27438 /************************************************************************
27439  *									*
27440  *			SAX validation handlers				*
27441  *									*
27442  ************************************************************************/
27443 
27444 /*
27445 * Process text content.
27446 */
27447 static void
xmlSchemaSAXHandleText(void * ctx,const xmlChar * ch,int len)27448 xmlSchemaSAXHandleText(void *ctx,
27449 		       const xmlChar * ch,
27450 		       int len)
27451 {
27452     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27453 
27454     if (vctxt->depth < 0)
27455 	return;
27456     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27457 	return;
27458     if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27459 	vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27460     if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
27461 	XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27462 	VERROR_INT("xmlSchemaSAXHandleCDataSection",
27463 	    "calling xmlSchemaVPushText()");
27464 	vctxt->err = -1;
27465 	xmlStopParser(vctxt->parserCtxt);
27466     }
27467 }
27468 
27469 /*
27470 * Process CDATA content.
27471 */
27472 static void
xmlSchemaSAXHandleCDataSection(void * ctx,const xmlChar * ch,int len)27473 xmlSchemaSAXHandleCDataSection(void *ctx,
27474 			     const xmlChar * ch,
27475 			     int len)
27476 {
27477     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27478 
27479     if (vctxt->depth < 0)
27480 	return;
27481     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27482 	return;
27483     if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27484 	vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27485     if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
27486 	XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27487 	VERROR_INT("xmlSchemaSAXHandleCDataSection",
27488 	    "calling xmlSchemaVPushText()");
27489 	vctxt->err = -1;
27490 	xmlStopParser(vctxt->parserCtxt);
27491     }
27492 }
27493 
27494 static void
xmlSchemaSAXHandleReference(void * ctx ATTRIBUTE_UNUSED,const xmlChar * name ATTRIBUTE_UNUSED)27495 xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
27496 			    const xmlChar * name ATTRIBUTE_UNUSED)
27497 {
27498     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27499 
27500     if (vctxt->depth < 0)
27501 	return;
27502     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27503 	return;
27504     /* SAX VAL TODO: What to do here? */
27505     TODO
27506 }
27507 
27508 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)27509 xmlSchemaSAXHandleStartElementNs(void *ctx,
27510 				 const xmlChar * localname,
27511 				 const xmlChar * prefix ATTRIBUTE_UNUSED,
27512 				 const xmlChar * URI,
27513 				 int nb_namespaces,
27514 				 const xmlChar ** namespaces,
27515 				 int nb_attributes,
27516 				 int nb_defaulted ATTRIBUTE_UNUSED,
27517 				 const xmlChar ** attributes)
27518 {
27519     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27520     int ret;
27521     xmlSchemaNodeInfoPtr ielem;
27522     int i, j;
27523 
27524     /*
27525     * SAX VAL TODO: What to do with nb_defaulted?
27526     */
27527     /*
27528     * Skip elements if inside a "skip" wildcard or invalid.
27529     */
27530     vctxt->depth++;
27531     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27532 	return;
27533     /*
27534     * Push the element.
27535     */
27536     if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27537 	VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27538 	    "calling xmlSchemaValidatorPushElem()");
27539 	goto internal_error;
27540     }
27541     ielem = vctxt->inode;
27542     /*
27543     * TODO: Is this OK?
27544     */
27545     ielem->nodeLine = xmlSAX2GetLineNumber(vctxt->parserCtxt);
27546     ielem->localName = localname;
27547     ielem->nsName = URI;
27548     ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27549     /*
27550     * Register namespaces on the elem info.
27551     */
27552     if (nb_namespaces != 0) {
27553 	/*
27554 	* Although the parser builds its own namespace list,
27555 	* we have no access to it, so we'll use an own one.
27556 	*/
27557         for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
27558 	    /*
27559 	    * Store prefix and namespace name.
27560 	    */
27561 	    if (ielem->nsBindings == NULL) {
27562 		ielem->nsBindings =
27563 		    (const xmlChar **) xmlMalloc(10 *
27564 			sizeof(const xmlChar *));
27565 		if (ielem->nsBindings == NULL) {
27566 		    xmlSchemaVErrMemory(vctxt,
27567 			"allocating namespace bindings for SAX validation",
27568 			NULL);
27569 		    goto internal_error;
27570 		}
27571 		ielem->nbNsBindings = 0;
27572 		ielem->sizeNsBindings = 5;
27573 	    } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
27574 		ielem->sizeNsBindings *= 2;
27575 		ielem->nsBindings =
27576 		    (const xmlChar **) xmlRealloc(
27577 			(void *) ielem->nsBindings,
27578 			ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
27579 		if (ielem->nsBindings == NULL) {
27580 		    xmlSchemaVErrMemory(vctxt,
27581 			"re-allocating namespace bindings for SAX validation",
27582 			NULL);
27583 		    goto internal_error;
27584 		}
27585 	    }
27586 
27587 	    ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
27588 	    if (namespaces[j+1][0] == 0) {
27589 		/*
27590 		* Handle xmlns="".
27591 		*/
27592 		ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
27593 	    } else
27594 		ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
27595 		    namespaces[j+1];
27596 	    ielem->nbNsBindings++;
27597 	}
27598     }
27599     /*
27600     * Register attributes.
27601     * SAX VAL TODO: We are not adding namespace declaration
27602     * attributes yet.
27603     */
27604     if (nb_attributes != 0) {
27605 	int valueLen, k, l;
27606 	xmlChar *value;
27607 
27608         for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
27609 	    /*
27610 	    * Duplicate the value, changing any &#38; to a literal ampersand.
27611 	    *
27612 	    * libxml2 differs from normal SAX here in that it escapes all ampersands
27613 	    * as &#38; instead of delivering the raw converted string. Changing the
27614 	    * behavior at this point would break applications that use this API, so
27615 	    * we are forced to work around it.
27616 	    */
27617 	    valueLen = attributes[j+4] - attributes[j+3];
27618 	    value = xmlMallocAtomic(valueLen + 1);
27619 	    if (value == NULL) {
27620 		xmlSchemaVErrMemory(vctxt,
27621 		    "allocating string for decoded attribute",
27622 		    NULL);
27623 		goto internal_error;
27624 	    }
27625 	    for (k = 0, l = 0; k < valueLen; l++) {
27626 		if (k < valueLen - 4 &&
27627 		    attributes[j+3][k+0] == '&' &&
27628 		    attributes[j+3][k+1] == '#' &&
27629 		    attributes[j+3][k+2] == '3' &&
27630 		    attributes[j+3][k+3] == '8' &&
27631 		    attributes[j+3][k+4] == ';') {
27632 		    value[l] = '&';
27633 		    k += 5;
27634 		} else {
27635 		    value[l] = attributes[j+3][k];
27636 		    k++;
27637 		}
27638 	    }
27639 	    value[l] = '\0';
27640 	    /*
27641 	    * TODO: Set the node line.
27642 	    */
27643 	    ret = xmlSchemaValidatorPushAttribute(vctxt,
27644 		NULL, ielem->nodeLine, attributes[j], attributes[j+2], 0,
27645 		value, 1);
27646 	    if (ret == -1) {
27647 		VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27648 		    "calling xmlSchemaValidatorPushAttribute()");
27649 		goto internal_error;
27650 	    }
27651 	}
27652     }
27653     /*
27654     * Validate the element.
27655     */
27656     ret = xmlSchemaValidateElem(vctxt);
27657     if (ret != 0) {
27658 	if (ret == -1) {
27659 	    VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27660 		"calling xmlSchemaValidateElem()");
27661 	    goto internal_error;
27662 	}
27663 	goto exit;
27664     }
27665 
27666 exit:
27667     return;
27668 internal_error:
27669     vctxt->err = -1;
27670     xmlStopParser(vctxt->parserCtxt);
27671     return;
27672 }
27673 
27674 static void
xmlSchemaSAXHandleEndElementNs(void * ctx,const xmlChar * localname ATTRIBUTE_UNUSED,const xmlChar * prefix ATTRIBUTE_UNUSED,const xmlChar * URI ATTRIBUTE_UNUSED)27675 xmlSchemaSAXHandleEndElementNs(void *ctx,
27676 			       const xmlChar * localname ATTRIBUTE_UNUSED,
27677 			       const xmlChar * prefix ATTRIBUTE_UNUSED,
27678 			       const xmlChar * URI ATTRIBUTE_UNUSED)
27679 {
27680     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27681     int res;
27682 
27683     /*
27684     * Skip elements if inside a "skip" wildcard or if invalid.
27685     */
27686     if (vctxt->skipDepth != -1) {
27687 	if (vctxt->depth > vctxt->skipDepth) {
27688 	    vctxt->depth--;
27689 	    return;
27690 	} else
27691 	    vctxt->skipDepth = -1;
27692     }
27693     /*
27694     * SAX VAL TODO: Just a temporary check.
27695     */
27696     if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
27697 	(!xmlStrEqual(vctxt->inode->nsName, URI))) {
27698 	VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27699 	    "elem pop mismatch");
27700     }
27701     res = xmlSchemaValidatorPopElem(vctxt);
27702     if (res != 0) {
27703 	if (res < 0) {
27704 	    VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27705 		"calling xmlSchemaValidatorPopElem()");
27706 	    goto internal_error;
27707 	}
27708 	goto exit;
27709     }
27710 exit:
27711     return;
27712 internal_error:
27713     vctxt->err = -1;
27714     xmlStopParser(vctxt->parserCtxt);
27715     return;
27716 }
27717 
27718 /************************************************************************
27719  *									*
27720  *			Validation interfaces				*
27721  *									*
27722  ************************************************************************/
27723 
27724 /**
27725  * xmlSchemaNewValidCtxt:
27726  * @schema:  a precompiled XML Schemas
27727  *
27728  * Create an XML Schemas validation context based on the given schema.
27729  *
27730  * Returns the validation context or NULL in case of error
27731  */
27732 xmlSchemaValidCtxtPtr
xmlSchemaNewValidCtxt(xmlSchemaPtr schema)27733 xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
27734 {
27735     xmlSchemaValidCtxtPtr ret;
27736 
27737     ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
27738     if (ret == NULL) {
27739         xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
27740         return (NULL);
27741     }
27742     memset(ret, 0, sizeof(xmlSchemaValidCtxt));
27743     ret->type = XML_SCHEMA_CTXT_VALIDATOR;
27744     ret->dict = xmlDictCreate();
27745     ret->nodeQNames = xmlSchemaItemListCreate();
27746     ret->schema = schema;
27747     return (ret);
27748 }
27749 
27750 /**
27751  * xmlSchemaValidateSetFilename:
27752  * @vctxt: the schema validation context
27753  * @filename: the file name
27754  *
27755  * Workaround to provide file error reporting information when this is
27756  * not provided by current APIs
27757  */
27758 void
xmlSchemaValidateSetFilename(xmlSchemaValidCtxtPtr vctxt,const char * filename)27759 xmlSchemaValidateSetFilename(xmlSchemaValidCtxtPtr vctxt, const char *filename) {
27760     if (vctxt == NULL)
27761         return;
27762     if (vctxt->filename != NULL)
27763         xmlFree(vctxt->filename);
27764     if (filename != NULL)
27765         vctxt->filename = (char *) xmlStrdup((const xmlChar *) filename);
27766     else
27767         vctxt->filename = NULL;
27768 }
27769 
27770 /**
27771  * xmlSchemaClearValidCtxt:
27772  * @vctxt: the schema validation context
27773  *
27774  * Free the resources associated to the schema validation context;
27775  * leaves some fields alive intended for reuse of the context.
27776  */
27777 static void
xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)27778 xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
27779 {
27780     if (vctxt == NULL)
27781         return;
27782 
27783     /*
27784     * TODO: Should we clear the flags?
27785     *   Might be problematic if one reuses the context
27786     *   and assumes that the options remain the same.
27787     */
27788     vctxt->flags = 0;
27789     vctxt->validationRoot = NULL;
27790     vctxt->doc = NULL;
27791 #ifdef LIBXML_READER_ENABLED
27792     vctxt->reader = NULL;
27793 #endif
27794     vctxt->hasKeyrefs = 0;
27795 
27796     if (vctxt->value != NULL) {
27797         xmlSchemaFreeValue(vctxt->value);
27798 	vctxt->value = NULL;
27799     }
27800     /*
27801     * Augmented IDC information.
27802     */
27803     if (vctxt->aidcs != NULL) {
27804 	xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
27805 	do {
27806 	    next = cur->next;
27807 	    xmlFree(cur);
27808 	    cur = next;
27809 	} while (cur != NULL);
27810 	vctxt->aidcs = NULL;
27811     }
27812     if (vctxt->idcMatcherCache != NULL) {
27813 	xmlSchemaIDCMatcherPtr matcher = vctxt->idcMatcherCache, tmp;
27814 
27815 	while (matcher) {
27816 	    tmp = matcher;
27817 	    matcher = matcher->nextCached;
27818 	    xmlSchemaIDCFreeMatcherList(tmp);
27819 	}
27820 	vctxt->idcMatcherCache = NULL;
27821     }
27822 
27823 
27824     if (vctxt->idcNodes != NULL) {
27825 	int i;
27826 	xmlSchemaPSVIIDCNodePtr item;
27827 
27828 	for (i = 0; i < vctxt->nbIdcNodes; i++) {
27829 	    item = vctxt->idcNodes[i];
27830 	    xmlFree(item->keys);
27831 	    xmlFree(item);
27832 	}
27833 	xmlFree(vctxt->idcNodes);
27834 	vctxt->idcNodes = NULL;
27835 	vctxt->nbIdcNodes = 0;
27836 	vctxt->sizeIdcNodes = 0;
27837     }
27838 
27839     if (vctxt->idcKeys != NULL) {
27840 	int i;
27841 	for (i = 0; i < vctxt->nbIdcKeys; i++)
27842 	    xmlSchemaIDCFreeKey(vctxt->idcKeys[i]);
27843 	xmlFree(vctxt->idcKeys);
27844 	vctxt->idcKeys = NULL;
27845 	vctxt->nbIdcKeys = 0;
27846 	vctxt->sizeIdcKeys = 0;
27847     }
27848 
27849     /*
27850     * Note that we won't delete the XPath state pool here.
27851     */
27852     if (vctxt->xpathStates != NULL) {
27853 	xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
27854 	vctxt->xpathStates = NULL;
27855     }
27856     /*
27857     * Attribute info.
27858     */
27859     if (vctxt->nbAttrInfos != 0) {
27860 	xmlSchemaClearAttrInfos(vctxt);
27861     }
27862     /*
27863     * Element info.
27864     */
27865     if (vctxt->elemInfos != NULL) {
27866 	int i;
27867 	xmlSchemaNodeInfoPtr ei;
27868 
27869 	for (i = 0; i < vctxt->sizeElemInfos; i++) {
27870 	    ei = vctxt->elemInfos[i];
27871 	    if (ei == NULL)
27872 		break;
27873 	    xmlSchemaClearElemInfo(vctxt, ei);
27874 	}
27875     }
27876     xmlSchemaItemListClear(vctxt->nodeQNames);
27877     /* Recreate the dict. */
27878     xmlDictFree(vctxt->dict);
27879     /*
27880     * TODO: Is is save to recreate it? Do we have a scenario
27881     * where the user provides the dict?
27882     */
27883     vctxt->dict = xmlDictCreate();
27884 
27885     if (vctxt->filename != NULL) {
27886         xmlFree(vctxt->filename);
27887 	vctxt->filename = NULL;
27888     }
27889 }
27890 
27891 /**
27892  * xmlSchemaFreeValidCtxt:
27893  * @ctxt:  the schema validation context
27894  *
27895  * Free the resources associated to the schema validation context
27896  */
27897 void
xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)27898 xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
27899 {
27900     if (ctxt == NULL)
27901         return;
27902     if (ctxt->value != NULL)
27903         xmlSchemaFreeValue(ctxt->value);
27904     if (ctxt->pctxt != NULL)
27905 	xmlSchemaFreeParserCtxt(ctxt->pctxt);
27906     if (ctxt->idcNodes != NULL) {
27907 	int i;
27908 	xmlSchemaPSVIIDCNodePtr item;
27909 
27910 	for (i = 0; i < ctxt->nbIdcNodes; i++) {
27911 	    item = ctxt->idcNodes[i];
27912 	    xmlFree(item->keys);
27913 	    xmlFree(item);
27914 	}
27915 	xmlFree(ctxt->idcNodes);
27916     }
27917     if (ctxt->idcKeys != NULL) {
27918 	int i;
27919 	for (i = 0; i < ctxt->nbIdcKeys; i++)
27920 	    xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
27921 	xmlFree(ctxt->idcKeys);
27922     }
27923 
27924     if (ctxt->xpathStates != NULL) {
27925 	xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
27926 	ctxt->xpathStates = NULL;
27927     }
27928     if (ctxt->xpathStatePool != NULL) {
27929 	xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
27930 	ctxt->xpathStatePool = NULL;
27931     }
27932 
27933     /*
27934     * Augmented IDC information.
27935     */
27936     if (ctxt->aidcs != NULL) {
27937 	xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
27938 	do {
27939 	    next = cur->next;
27940 	    xmlFree(cur);
27941 	    cur = next;
27942 	} while (cur != NULL);
27943     }
27944     if (ctxt->attrInfos != NULL) {
27945 	int i;
27946 	xmlSchemaAttrInfoPtr attr;
27947 
27948 	/* Just a paranoid call to the cleanup. */
27949 	if (ctxt->nbAttrInfos != 0)
27950 	    xmlSchemaClearAttrInfos(ctxt);
27951 	for (i = 0; i < ctxt->sizeAttrInfos; i++) {
27952 	    attr = ctxt->attrInfos[i];
27953 	    xmlFree(attr);
27954 	}
27955 	xmlFree(ctxt->attrInfos);
27956     }
27957     if (ctxt->elemInfos != NULL) {
27958 	int i;
27959 	xmlSchemaNodeInfoPtr ei;
27960 
27961 	for (i = 0; i < ctxt->sizeElemInfos; i++) {
27962 	    ei = ctxt->elemInfos[i];
27963 	    if (ei == NULL)
27964 		break;
27965 	    xmlSchemaClearElemInfo(ctxt, ei);
27966 	    xmlFree(ei);
27967 	}
27968 	xmlFree(ctxt->elemInfos);
27969     }
27970     if (ctxt->nodeQNames != NULL)
27971 	xmlSchemaItemListFree(ctxt->nodeQNames);
27972     if (ctxt->dict != NULL)
27973 	xmlDictFree(ctxt->dict);
27974     if (ctxt->filename != NULL)
27975 	xmlFree(ctxt->filename);
27976     xmlFree(ctxt);
27977 }
27978 
27979 /**
27980  * xmlSchemaIsValid:
27981  * @ctxt: the schema validation context
27982  *
27983  * Check if any error was detected during validation.
27984  *
27985  * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
27986  *         of internal error.
27987  */
27988 int
xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)27989 xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
27990 {
27991     if (ctxt == NULL)
27992         return(-1);
27993     return(ctxt->err == 0);
27994 }
27995 
27996 /**
27997  * xmlSchemaSetValidErrors:
27998  * @ctxt:  a schema validation context
27999  * @err:  the error function
28000  * @warn: the warning function
28001  * @ctx: the functions context
28002  *
28003  * Set the error and warning callback information
28004  */
28005 void
xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,xmlSchemaValidityErrorFunc err,xmlSchemaValidityWarningFunc warn,void * ctx)28006 xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
28007                         xmlSchemaValidityErrorFunc err,
28008                         xmlSchemaValidityWarningFunc warn, void *ctx)
28009 {
28010     if (ctxt == NULL)
28011         return;
28012     ctxt->error = err;
28013     ctxt->warning = warn;
28014     ctxt->errCtxt = ctx;
28015     if (ctxt->pctxt != NULL)
28016 	xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
28017 }
28018 
28019 /**
28020  * xmlSchemaSetValidStructuredErrors:
28021  * @ctxt:  a schema validation context
28022  * @serror:  the structured error function
28023  * @ctx: the functions context
28024  *
28025  * Set the structured error callback
28026  */
28027 void
xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,xmlStructuredErrorFunc serror,void * ctx)28028 xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
28029 				  xmlStructuredErrorFunc serror, void *ctx)
28030 {
28031     if (ctxt == NULL)
28032         return;
28033     ctxt->serror = serror;
28034     ctxt->error = NULL;
28035     ctxt->warning = NULL;
28036     ctxt->errCtxt = ctx;
28037     if (ctxt->pctxt != NULL)
28038 	xmlSchemaSetParserStructuredErrors(ctxt->pctxt, serror, ctx);
28039 }
28040 
28041 /**
28042  * xmlSchemaGetValidErrors:
28043  * @ctxt: a XML-Schema validation context
28044  * @err: the error function result
28045  * @warn: the warning function result
28046  * @ctx: the functions context result
28047  *
28048  * Get the error and warning callback information
28049  *
28050  * Returns -1 in case of error and 0 otherwise
28051  */
28052 int
xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,xmlSchemaValidityErrorFunc * err,xmlSchemaValidityWarningFunc * warn,void ** ctx)28053 xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
28054 			xmlSchemaValidityErrorFunc * err,
28055 			xmlSchemaValidityWarningFunc * warn, void **ctx)
28056 {
28057 	if (ctxt == NULL)
28058 		return (-1);
28059 	if (err != NULL)
28060 		*err = ctxt->error;
28061 	if (warn != NULL)
28062 		*warn = ctxt->warning;
28063 	if (ctx != NULL)
28064 		*ctx = ctxt->errCtxt;
28065 	return (0);
28066 }
28067 
28068 
28069 /**
28070  * xmlSchemaSetValidOptions:
28071  * @ctxt:	a schema validation context
28072  * @options: a combination of xmlSchemaValidOption
28073  *
28074  * Sets the options to be used during the validation.
28075  *
28076  * Returns 0 in case of success, -1 in case of an
28077  * API error.
28078  */
28079 int
xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,int options)28080 xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
28081 			 int options)
28082 
28083 {
28084     int i;
28085 
28086     if (ctxt == NULL)
28087 	return (-1);
28088     /*
28089     * WARNING: Change the start value if adding to the
28090     * xmlSchemaValidOption.
28091     * TODO: Is there an other, more easy to maintain,
28092     * way?
28093     */
28094     for (i = 1; i < (int) sizeof(int) * 8; i++) {
28095         if (options & 1<<i)
28096 	    return (-1);
28097     }
28098     ctxt->options = options;
28099     return (0);
28100 }
28101 
28102 /**
28103  * xmlSchemaValidCtxtGetOptions:
28104  * @ctxt: a schema validation context
28105  *
28106  * Get the validation context options.
28107  *
28108  * Returns the option combination or -1 on error.
28109  */
28110 int
xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)28111 xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
28112 
28113 {
28114     if (ctxt == NULL)
28115 	return (-1);
28116     else
28117 	return (ctxt->options);
28118 }
28119 
28120 static int
xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)28121 xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
28122 {
28123     xmlAttrPtr attr;
28124     int ret = 0;
28125     xmlSchemaNodeInfoPtr ielem = NULL;
28126     xmlNodePtr node, valRoot;
28127     const xmlChar *nsName;
28128 
28129     /* DOC VAL TODO: Move this to the start function. */
28130     if (vctxt->validationRoot != NULL)
28131         valRoot = vctxt->validationRoot;
28132     else
28133 	valRoot = xmlDocGetRootElement(vctxt->doc);
28134     if (valRoot == NULL) {
28135 	/* VAL TODO: Error code? */
28136 	VERROR(1, NULL, "The document has no document element");
28137 	return (1);
28138     }
28139     for (node = valRoot->next; node != NULL; node = node->next) {
28140         if (node->type == XML_ELEMENT_NODE)
28141             VERROR(1, NULL, "The document has more than one top element");
28142     }
28143     vctxt->depth = -1;
28144     vctxt->validationRoot = valRoot;
28145     node = valRoot;
28146     while (node != NULL) {
28147 	if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
28148 	    goto next_sibling;
28149 	if (node->type == XML_ELEMENT_NODE) {
28150 
28151 	    /*
28152 	    * Init the node-info.
28153 	    */
28154 	    vctxt->depth++;
28155 	    if (xmlSchemaValidatorPushElem(vctxt) == -1)
28156 		goto internal_error;
28157 	    ielem = vctxt->inode;
28158 	    ielem->node = node;
28159 	    ielem->nodeLine = node->line;
28160 	    ielem->localName = node->name;
28161 	    if (node->ns != NULL)
28162 		ielem->nsName = node->ns->href;
28163 	    ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
28164 	    /*
28165 	    * Register attributes.
28166 	    * DOC VAL TODO: We do not register namespace declaration
28167 	    * attributes yet.
28168 	    */
28169 	    vctxt->nbAttrInfos = 0;
28170 	    if (node->properties != NULL) {
28171 		attr = node->properties;
28172 		do {
28173 		    if (attr->ns != NULL)
28174 			nsName = attr->ns->href;
28175 		    else
28176 			nsName = NULL;
28177 		    ret = xmlSchemaValidatorPushAttribute(vctxt,
28178 			(xmlNodePtr) attr,
28179 			/*
28180 			* Note that we give it the line number of the
28181 			* parent element.
28182 			*/
28183 			ielem->nodeLine,
28184 			attr->name, nsName, 0,
28185 			xmlNodeListGetString(attr->doc, attr->children, 1), 1);
28186 		    if (ret == -1) {
28187 			VERROR_INT("xmlSchemaDocWalk",
28188 			    "calling xmlSchemaValidatorPushAttribute()");
28189 			goto internal_error;
28190 		    }
28191 		    attr = attr->next;
28192 		} while (attr);
28193 	    }
28194 	    /*
28195 	    * Validate the element.
28196 	    */
28197 	    ret = xmlSchemaValidateElem(vctxt);
28198 	    if (ret != 0) {
28199 		if (ret == -1) {
28200 		    VERROR_INT("xmlSchemaDocWalk",
28201 			"calling xmlSchemaValidateElem()");
28202 		    goto internal_error;
28203 		}
28204 		/*
28205 		* Don't stop validation; just skip the content
28206 		* of this element.
28207 		*/
28208 		goto leave_node;
28209 	    }
28210 	    if ((vctxt->skipDepth != -1) &&
28211 		(vctxt->depth >= vctxt->skipDepth))
28212 		goto leave_node;
28213 	} else if ((node->type == XML_TEXT_NODE) ||
28214 	    (node->type == XML_CDATA_SECTION_NODE)) {
28215 	    /*
28216 	    * Process character content.
28217 	    */
28218 	    if ((ielem != NULL) && (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY))
28219 		ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
28220 	    ret = xmlSchemaVPushText(vctxt, node->type, node->content,
28221 		-1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
28222 	    if (ret < 0) {
28223 		VERROR_INT("xmlSchemaVDocWalk",
28224 		    "calling xmlSchemaVPushText()");
28225 		goto internal_error;
28226 	    }
28227 	    /*
28228 	    * DOC VAL TODO: Should we skip further validation of the
28229 	    * element content here?
28230 	    */
28231 	} else if ((node->type == XML_ENTITY_NODE) ||
28232 	    (node->type == XML_ENTITY_REF_NODE)) {
28233 	    /*
28234 	    * DOC VAL TODO: What to do with entities?
28235 	    */
28236 	    VERROR_INT("xmlSchemaVDocWalk",
28237 		"there is at least one entity reference in the node-tree "
28238 		"currently being validated. Processing of entities with "
28239 		"this XML Schema processor is not supported (yet). Please "
28240 		"substitute entities before validation.");
28241 	    goto internal_error;
28242 	} else {
28243 	    goto leave_node;
28244 	    /*
28245 	    * DOC VAL TODO: XInclude nodes, etc.
28246 	    */
28247 	}
28248 	/*
28249 	* Walk the doc.
28250 	*/
28251 	if (node->children != NULL) {
28252 	    node = node->children;
28253 	    continue;
28254 	}
28255 leave_node:
28256 	if (node->type == XML_ELEMENT_NODE) {
28257 	    /*
28258 	    * Leaving the scope of an element.
28259 	    */
28260 	    if (node != vctxt->inode->node) {
28261 		VERROR_INT("xmlSchemaVDocWalk",
28262 		    "element position mismatch");
28263 		goto internal_error;
28264 	    }
28265 	    ret = xmlSchemaValidatorPopElem(vctxt);
28266 	    if (ret != 0) {
28267 		if (ret < 0) {
28268 		    VERROR_INT("xmlSchemaVDocWalk",
28269 			"calling xmlSchemaValidatorPopElem()");
28270 		    goto internal_error;
28271 		}
28272 	    }
28273 	    if (node == valRoot)
28274 		goto exit;
28275 	}
28276 next_sibling:
28277 	if (node->next != NULL)
28278 	    node = node->next;
28279 	else {
28280 	    node = node->parent;
28281 	    goto leave_node;
28282 	}
28283     }
28284 
28285 exit:
28286     return (ret);
28287 internal_error:
28288     return (-1);
28289 }
28290 
28291 static int
xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt)28292 xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
28293     /*
28294     * Some initialization.
28295     */
28296     vctxt->err = 0;
28297     vctxt->nberrors = 0;
28298     vctxt->depth = -1;
28299     vctxt->skipDepth = -1;
28300     vctxt->hasKeyrefs = 0;
28301 #ifdef ENABLE_IDC_NODE_TABLES_TEST
28302     vctxt->createIDCNodeTables = 1;
28303 #else
28304     vctxt->createIDCNodeTables = 0;
28305 #endif
28306     /*
28307     * Create a schema + parser if necessary.
28308     */
28309     if (vctxt->schema == NULL) {
28310 	xmlSchemaParserCtxtPtr pctxt;
28311 
28312 	vctxt->xsiAssemble = 1;
28313 	/*
28314 	* If not schema was given then we will create a schema
28315 	* dynamically using XSI schema locations.
28316 	*
28317 	* Create the schema parser context.
28318 	*/
28319 	if ((vctxt->pctxt == NULL) &&
28320 	   (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
28321 	   return (-1);
28322 	pctxt = vctxt->pctxt;
28323 	pctxt->xsiAssemble = 1;
28324 	/*
28325 	* Create the schema.
28326 	*/
28327 	vctxt->schema = xmlSchemaNewSchema(pctxt);
28328 	if (vctxt->schema == NULL)
28329 	    return (-1);
28330 	/*
28331 	* Create the schema construction context.
28332 	*/
28333 	pctxt->constructor = xmlSchemaConstructionCtxtCreate(pctxt->dict);
28334 	if (pctxt->constructor == NULL)
28335 	    return(-1);
28336 	pctxt->constructor->mainSchema = vctxt->schema;
28337 	/*
28338 	* Take ownership of the constructor to be able to free it.
28339 	*/
28340 	pctxt->ownsConstructor = 1;
28341     }
28342     /*
28343     * Augment the IDC definitions for the main schema and all imported ones
28344     * NOTE: main schema if the first in the imported list
28345     */
28346     xmlHashScan(vctxt->schema->schemasImports, xmlSchemaAugmentImportedIDC,
28347                 vctxt);
28348 
28349     return(0);
28350 }
28351 
28352 static void
xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt)28353 xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
28354     if (vctxt->xsiAssemble) {
28355 	if (vctxt->schema != NULL) {
28356 	    xmlSchemaFree(vctxt->schema);
28357 	    vctxt->schema = NULL;
28358 	}
28359     }
28360     xmlSchemaClearValidCtxt(vctxt);
28361 }
28362 
28363 static int
xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)28364 xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
28365 {
28366     int ret = 0;
28367 
28368     if (xmlSchemaPreRun(vctxt) < 0)
28369         return(-1);
28370 
28371     if (vctxt->doc != NULL) {
28372 	/*
28373 	 * Tree validation.
28374 	 */
28375 	ret = xmlSchemaVDocWalk(vctxt);
28376 #ifdef LIBXML_READER_ENABLED
28377     } else if (vctxt->reader != NULL) {
28378 	/*
28379 	 * XML Reader validation.
28380 	 */
28381 #ifdef XML_SCHEMA_READER_ENABLED
28382 	ret = xmlSchemaVReaderWalk(vctxt);
28383 #endif
28384 #endif
28385     } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
28386 	/*
28387 	 * SAX validation.
28388 	 */
28389 	ret = xmlParseDocument(vctxt->parserCtxt);
28390     } else {
28391 	VERROR_INT("xmlSchemaVStart",
28392 	    "no instance to validate");
28393 	ret = -1;
28394     }
28395 
28396     xmlSchemaPostRun(vctxt);
28397     if (ret == 0)
28398 	ret = vctxt->err;
28399     return (ret);
28400 }
28401 
28402 /**
28403  * xmlSchemaValidateOneElement:
28404  * @ctxt:  a schema validation context
28405  * @elem:  an element node
28406  *
28407  * Validate a branch of a tree, starting with the given @elem.
28408  *
28409  * Returns 0 if the element and its subtree is valid, a positive error
28410  * code number otherwise and -1 in case of an internal or API error.
28411  */
28412 int
xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt,xmlNodePtr elem)28413 xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
28414 {
28415     if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
28416 	return (-1);
28417 
28418     if (ctxt->schema == NULL)
28419 	return (-1);
28420 
28421     ctxt->doc = elem->doc;
28422     ctxt->node = elem;
28423     ctxt->validationRoot = elem;
28424     return(xmlSchemaVStart(ctxt));
28425 }
28426 
28427 /**
28428  * xmlSchemaValidateDoc:
28429  * @ctxt:  a schema validation context
28430  * @doc:  a parsed document tree
28431  *
28432  * Validate a document tree in memory.
28433  *
28434  * Returns 0 if the document is schemas valid, a positive error code
28435  *     number otherwise and -1 in case of internal or API error.
28436  */
28437 int
xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt,xmlDocPtr doc)28438 xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
28439 {
28440     if ((ctxt == NULL) || (doc == NULL))
28441         return (-1);
28442 
28443     ctxt->doc = doc;
28444     ctxt->node = xmlDocGetRootElement(doc);
28445     if (ctxt->node == NULL) {
28446         xmlSchemaCustomErr(ACTXT_CAST ctxt,
28447 	    XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
28448 	    (xmlNodePtr) doc, NULL,
28449 	    "The document has no document element", NULL, NULL);
28450         return (ctxt->err);
28451     }
28452     ctxt->validationRoot = ctxt->node;
28453     return (xmlSchemaVStart(ctxt));
28454 }
28455 
28456 
28457 /************************************************************************
28458  *									*
28459  *		Function and data for SAX streaming API			*
28460  *									*
28461  ************************************************************************/
28462 typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
28463 typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
28464 
28465 struct _xmlSchemaSplitSAXData {
28466     xmlSAXHandlerPtr      user_sax;
28467     void                 *user_data;
28468     xmlSchemaValidCtxtPtr ctxt;
28469     xmlSAXHandlerPtr      schemas_sax;
28470 };
28471 
28472 #define XML_SAX_PLUG_MAGIC 0xdc43ba21
28473 
28474 struct _xmlSchemaSAXPlug {
28475     unsigned int magic;
28476 
28477     /* the original callbacks information */
28478     xmlSAXHandlerPtr     *user_sax_ptr;
28479     xmlSAXHandlerPtr      user_sax;
28480     void                **user_data_ptr;
28481     void                 *user_data;
28482 
28483     /* the block plugged back and validation information */
28484     xmlSAXHandler         schemas_sax;
28485     xmlSchemaValidCtxtPtr ctxt;
28486 };
28487 
28488 /* All those functions just bounces to the user provided SAX handlers */
28489 static void
internalSubsetSplit(void * ctx,const xmlChar * name,const xmlChar * ExternalID,const xmlChar * SystemID)28490 internalSubsetSplit(void *ctx, const xmlChar *name,
28491 	       const xmlChar *ExternalID, const xmlChar *SystemID)
28492 {
28493     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28494     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28495         (ctxt->user_sax->internalSubset != NULL))
28496 	ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
28497 	                               SystemID);
28498 }
28499 
28500 static int
isStandaloneSplit(void * ctx)28501 isStandaloneSplit(void *ctx)
28502 {
28503     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28504     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28505         (ctxt->user_sax->isStandalone != NULL))
28506 	return(ctxt->user_sax->isStandalone(ctxt->user_data));
28507     return(0);
28508 }
28509 
28510 static int
hasInternalSubsetSplit(void * ctx)28511 hasInternalSubsetSplit(void *ctx)
28512 {
28513     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28514     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28515         (ctxt->user_sax->hasInternalSubset != NULL))
28516 	return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
28517     return(0);
28518 }
28519 
28520 static int
hasExternalSubsetSplit(void * ctx)28521 hasExternalSubsetSplit(void *ctx)
28522 {
28523     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28524     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28525         (ctxt->user_sax->hasExternalSubset != NULL))
28526 	return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
28527     return(0);
28528 }
28529 
28530 static void
externalSubsetSplit(void * ctx,const xmlChar * name,const xmlChar * ExternalID,const xmlChar * SystemID)28531 externalSubsetSplit(void *ctx, const xmlChar *name,
28532 	       const xmlChar *ExternalID, const xmlChar *SystemID)
28533 {
28534     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28535     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28536         (ctxt->user_sax->externalSubset != NULL))
28537 	ctxt->user_sax->externalSubset(ctxt->user_data, name, ExternalID,
28538 	                               SystemID);
28539 }
28540 
28541 static xmlParserInputPtr
resolveEntitySplit(void * ctx,const xmlChar * publicId,const xmlChar * systemId)28542 resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
28543 {
28544     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28545     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28546         (ctxt->user_sax->resolveEntity != NULL))
28547 	return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
28548 	                                     systemId));
28549     return(NULL);
28550 }
28551 
28552 static xmlEntityPtr
getEntitySplit(void * ctx,const xmlChar * name)28553 getEntitySplit(void *ctx, const xmlChar *name)
28554 {
28555     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28556     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28557         (ctxt->user_sax->getEntity != NULL))
28558 	return(ctxt->user_sax->getEntity(ctxt->user_data, name));
28559     return(NULL);
28560 }
28561 
28562 static xmlEntityPtr
getParameterEntitySplit(void * ctx,const xmlChar * name)28563 getParameterEntitySplit(void *ctx, const xmlChar *name)
28564 {
28565     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28566     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28567         (ctxt->user_sax->getParameterEntity != NULL))
28568 	return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
28569     return(NULL);
28570 }
28571 
28572 
28573 static void
entityDeclSplit(void * ctx,const xmlChar * name,int type,const xmlChar * publicId,const xmlChar * systemId,xmlChar * content)28574 entityDeclSplit(void *ctx, const xmlChar *name, int type,
28575           const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
28576 {
28577     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28578     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28579         (ctxt->user_sax->entityDecl != NULL))
28580 	ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
28581 	                           systemId, content);
28582 }
28583 
28584 static void
attributeDeclSplit(void * ctx,const xmlChar * elem,const xmlChar * name,int type,int def,const xmlChar * defaultValue,xmlEnumerationPtr tree)28585 attributeDeclSplit(void *ctx, const xmlChar * elem,
28586                    const xmlChar * name, int type, int def,
28587                    const xmlChar * defaultValue, xmlEnumerationPtr tree)
28588 {
28589     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28590     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28591         (ctxt->user_sax->attributeDecl != NULL)) {
28592 	ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
28593 	                              def, defaultValue, tree);
28594     } else {
28595 	xmlFreeEnumeration(tree);
28596     }
28597 }
28598 
28599 static void
elementDeclSplit(void * ctx,const xmlChar * name,int type,xmlElementContentPtr content)28600 elementDeclSplit(void *ctx, const xmlChar *name, int type,
28601 	    xmlElementContentPtr content)
28602 {
28603     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28604     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28605         (ctxt->user_sax->elementDecl != NULL))
28606 	ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
28607 }
28608 
28609 static void
notationDeclSplit(void * ctx,const xmlChar * name,const xmlChar * publicId,const xmlChar * systemId)28610 notationDeclSplit(void *ctx, const xmlChar *name,
28611 	     const xmlChar *publicId, const xmlChar *systemId)
28612 {
28613     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28614     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28615         (ctxt->user_sax->notationDecl != NULL))
28616 	ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
28617 	                             systemId);
28618 }
28619 
28620 static void
unparsedEntityDeclSplit(void * ctx,const xmlChar * name,const xmlChar * publicId,const xmlChar * systemId,const xmlChar * notationName)28621 unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
28622 		   const xmlChar *publicId, const xmlChar *systemId,
28623 		   const xmlChar *notationName)
28624 {
28625     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28626     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28627         (ctxt->user_sax->unparsedEntityDecl != NULL))
28628 	ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
28629 	                                   systemId, notationName);
28630 }
28631 
28632 static void
setDocumentLocatorSplit(void * ctx,xmlSAXLocatorPtr loc)28633 setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
28634 {
28635     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28636     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28637         (ctxt->user_sax->setDocumentLocator != NULL))
28638 	ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
28639 }
28640 
28641 static void
startDocumentSplit(void * ctx)28642 startDocumentSplit(void *ctx)
28643 {
28644     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28645     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28646         (ctxt->user_sax->startDocument != NULL))
28647 	ctxt->user_sax->startDocument(ctxt->user_data);
28648 }
28649 
28650 static void
endDocumentSplit(void * ctx)28651 endDocumentSplit(void *ctx)
28652 {
28653     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28654     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28655         (ctxt->user_sax->endDocument != NULL))
28656 	ctxt->user_sax->endDocument(ctxt->user_data);
28657 }
28658 
28659 static void
processingInstructionSplit(void * ctx,const xmlChar * target,const xmlChar * data)28660 processingInstructionSplit(void *ctx, const xmlChar *target,
28661                       const xmlChar *data)
28662 {
28663     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28664     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28665         (ctxt->user_sax->processingInstruction != NULL))
28666 	ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
28667 }
28668 
28669 static void
commentSplit(void * ctx,const xmlChar * value)28670 commentSplit(void *ctx, const xmlChar *value)
28671 {
28672     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28673     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28674         (ctxt->user_sax->comment != NULL))
28675 	ctxt->user_sax->comment(ctxt->user_data, value);
28676 }
28677 
28678 /*
28679  * Varargs error callbacks to the user application, harder ...
28680  */
28681 
28682 static void XMLCDECL
warningSplit(void * ctx,const char * msg ATTRIBUTE_UNUSED,...)28683 warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28684     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28685     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28686         (ctxt->user_sax->warning != NULL)) {
28687 	TODO
28688     }
28689 }
28690 static void XMLCDECL
errorSplit(void * ctx,const char * msg ATTRIBUTE_UNUSED,...)28691 errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28692     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28693     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28694         (ctxt->user_sax->error != NULL)) {
28695 	TODO
28696     }
28697 }
28698 static void XMLCDECL
fatalErrorSplit(void * ctx,const char * msg ATTRIBUTE_UNUSED,...)28699 fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28700     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28701     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28702         (ctxt->user_sax->fatalError != NULL)) {
28703 	TODO
28704     }
28705 }
28706 
28707 /*
28708  * Those are function where both the user handler and the schemas handler
28709  * need to be called.
28710  */
28711 static void
charactersSplit(void * ctx,const xmlChar * ch,int len)28712 charactersSplit(void *ctx, const xmlChar *ch, int len)
28713 {
28714     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28715     if (ctxt == NULL)
28716         return;
28717     if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
28718 	ctxt->user_sax->characters(ctxt->user_data, ch, len);
28719     if (ctxt->ctxt != NULL)
28720 	xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28721 }
28722 
28723 static void
ignorableWhitespaceSplit(void * ctx,const xmlChar * ch,int len)28724 ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
28725 {
28726     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28727     if (ctxt == NULL)
28728         return;
28729     if ((ctxt->user_sax != NULL) &&
28730         (ctxt->user_sax->ignorableWhitespace != NULL))
28731 	ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
28732     if (ctxt->ctxt != NULL)
28733 	xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28734 }
28735 
28736 static void
cdataBlockSplit(void * ctx,const xmlChar * value,int len)28737 cdataBlockSplit(void *ctx, const xmlChar *value, int len)
28738 {
28739     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28740     if (ctxt == NULL)
28741         return;
28742     if ((ctxt->user_sax != NULL) &&
28743         (ctxt->user_sax->cdataBlock != NULL))
28744 	ctxt->user_sax->cdataBlock(ctxt->user_data, value, len);
28745     if (ctxt->ctxt != NULL)
28746 	xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
28747 }
28748 
28749 static void
referenceSplit(void * ctx,const xmlChar * name)28750 referenceSplit(void *ctx, const xmlChar *name)
28751 {
28752     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28753     if (ctxt == NULL)
28754         return;
28755     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28756         (ctxt->user_sax->reference != NULL))
28757 	ctxt->user_sax->reference(ctxt->user_data, name);
28758     if (ctxt->ctxt != NULL)
28759         xmlSchemaSAXHandleReference(ctxt->user_data, name);
28760 }
28761 
28762 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)28763 startElementNsSplit(void *ctx, const xmlChar * localname,
28764 		    const xmlChar * prefix, const xmlChar * URI,
28765 		    int nb_namespaces, const xmlChar ** namespaces,
28766 		    int nb_attributes, int nb_defaulted,
28767 		    const xmlChar ** attributes) {
28768     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28769     if (ctxt == NULL)
28770         return;
28771     if ((ctxt->user_sax != NULL) &&
28772         (ctxt->user_sax->startElementNs != NULL))
28773 	ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
28774 	                               URI, nb_namespaces, namespaces,
28775 				       nb_attributes, nb_defaulted,
28776 				       attributes);
28777     if (ctxt->ctxt != NULL)
28778 	xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
28779 	                                 URI, nb_namespaces, namespaces,
28780 					 nb_attributes, nb_defaulted,
28781 					 attributes);
28782 }
28783 
28784 static void
endElementNsSplit(void * ctx,const xmlChar * localname,const xmlChar * prefix,const xmlChar * URI)28785 endElementNsSplit(void *ctx, const xmlChar * localname,
28786 		    const xmlChar * prefix, const xmlChar * URI) {
28787     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28788     if (ctxt == NULL)
28789         return;
28790     if ((ctxt->user_sax != NULL) &&
28791         (ctxt->user_sax->endElementNs != NULL))
28792 	ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
28793     if (ctxt->ctxt != NULL)
28794 	xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
28795 }
28796 
28797 /**
28798  * xmlSchemaSAXPlug:
28799  * @ctxt:  a schema validation context
28800  * @sax:  a pointer to the original xmlSAXHandlerPtr
28801  * @user_data:  a pointer to the original SAX user data pointer
28802  *
28803  * Plug a SAX based validation layer in a SAX parsing event flow.
28804  * The original @saxptr and @dataptr data are replaced by new pointers
28805  * but the calls to the original will be maintained.
28806  *
28807  * Returns a pointer to a data structure needed to unplug the validation layer
28808  *         or NULL in case of errors.
28809  */
28810 xmlSchemaSAXPlugPtr
xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,xmlSAXHandlerPtr * sax,void ** user_data)28811 xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
28812 		 xmlSAXHandlerPtr *sax, void **user_data)
28813 {
28814     xmlSchemaSAXPlugPtr ret;
28815     xmlSAXHandlerPtr old_sax;
28816 
28817     if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
28818         return(NULL);
28819 
28820     /*
28821      * We only allow to plug into SAX2 event streams
28822      */
28823     old_sax = *sax;
28824     if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
28825         return(NULL);
28826     if ((old_sax != NULL) &&
28827         (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
28828         ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
28829         return(NULL);
28830 
28831     /*
28832      * everything seems right allocate the local data needed for that layer
28833      */
28834     ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
28835     if (ret == NULL) {
28836         return(NULL);
28837     }
28838     memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
28839     ret->magic = XML_SAX_PLUG_MAGIC;
28840     ret->schemas_sax.initialized = XML_SAX2_MAGIC;
28841     ret->ctxt = ctxt;
28842     ret->user_sax_ptr = sax;
28843     ret->user_sax = old_sax;
28844     if (old_sax == NULL) {
28845         /*
28846 	 * go direct, no need for the split block and functions.
28847 	 */
28848 	ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
28849 	ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
28850 	/*
28851 	 * Note that we use the same text-function for both, to prevent
28852 	 * the parser from testing for ignorable whitespace.
28853 	 */
28854 	ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
28855 	ret->schemas_sax.characters = xmlSchemaSAXHandleText;
28856 
28857 	ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
28858 	ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
28859 
28860 	ret->user_data = ctxt;
28861 	*user_data = ctxt;
28862     } else {
28863        /*
28864         * for each callback unused by Schemas initialize it to the Split
28865 	* routine only if non NULL in the user block, this can speed up
28866 	* things at the SAX level.
28867 	*/
28868         if (old_sax->internalSubset != NULL)
28869             ret->schemas_sax.internalSubset = internalSubsetSplit;
28870         if (old_sax->isStandalone != NULL)
28871             ret->schemas_sax.isStandalone = isStandaloneSplit;
28872         if (old_sax->hasInternalSubset != NULL)
28873             ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
28874         if (old_sax->hasExternalSubset != NULL)
28875             ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
28876         if (old_sax->resolveEntity != NULL)
28877             ret->schemas_sax.resolveEntity = resolveEntitySplit;
28878         if (old_sax->getEntity != NULL)
28879             ret->schemas_sax.getEntity = getEntitySplit;
28880         if (old_sax->entityDecl != NULL)
28881             ret->schemas_sax.entityDecl = entityDeclSplit;
28882         if (old_sax->notationDecl != NULL)
28883             ret->schemas_sax.notationDecl = notationDeclSplit;
28884         if (old_sax->attributeDecl != NULL)
28885             ret->schemas_sax.attributeDecl = attributeDeclSplit;
28886         if (old_sax->elementDecl != NULL)
28887             ret->schemas_sax.elementDecl = elementDeclSplit;
28888         if (old_sax->unparsedEntityDecl != NULL)
28889             ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
28890         if (old_sax->setDocumentLocator != NULL)
28891             ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
28892         if (old_sax->startDocument != NULL)
28893             ret->schemas_sax.startDocument = startDocumentSplit;
28894         if (old_sax->endDocument != NULL)
28895             ret->schemas_sax.endDocument = endDocumentSplit;
28896         if (old_sax->processingInstruction != NULL)
28897             ret->schemas_sax.processingInstruction = processingInstructionSplit;
28898         if (old_sax->comment != NULL)
28899             ret->schemas_sax.comment = commentSplit;
28900         if (old_sax->warning != NULL)
28901             ret->schemas_sax.warning = warningSplit;
28902         if (old_sax->error != NULL)
28903             ret->schemas_sax.error = errorSplit;
28904         if (old_sax->fatalError != NULL)
28905             ret->schemas_sax.fatalError = fatalErrorSplit;
28906         if (old_sax->getParameterEntity != NULL)
28907             ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
28908         if (old_sax->externalSubset != NULL)
28909             ret->schemas_sax.externalSubset = externalSubsetSplit;
28910 
28911 	/*
28912 	 * the 6 schemas callback have to go to the splitter functions
28913 	 * Note that we use the same text-function for ignorableWhitespace
28914 	 * if possible, to prevent the parser from testing for ignorable
28915 	 * whitespace.
28916 	 */
28917         ret->schemas_sax.characters = charactersSplit;
28918 	if ((old_sax->ignorableWhitespace != NULL) &&
28919 	    (old_sax->ignorableWhitespace != old_sax->characters))
28920 	    ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
28921 	else
28922 	    ret->schemas_sax.ignorableWhitespace = charactersSplit;
28923         ret->schemas_sax.cdataBlock = cdataBlockSplit;
28924         ret->schemas_sax.reference = referenceSplit;
28925         ret->schemas_sax.startElementNs = startElementNsSplit;
28926         ret->schemas_sax.endElementNs = endElementNsSplit;
28927 
28928 	ret->user_data_ptr = user_data;
28929 	ret->user_data = *user_data;
28930 	*user_data = ret;
28931     }
28932 
28933     /*
28934      * plug the pointers back.
28935      */
28936     *sax = &(ret->schemas_sax);
28937     ctxt->sax = *sax;
28938     ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28939     xmlSchemaPreRun(ctxt);
28940     return(ret);
28941 }
28942 
28943 /**
28944  * xmlSchemaSAXUnplug:
28945  * @plug:  a data structure returned by xmlSchemaSAXPlug
28946  *
28947  * Unplug a SAX based validation layer in a SAX parsing event flow.
28948  * The original pointers used in the call are restored.
28949  *
28950  * Returns 0 in case of success and -1 in case of failure.
28951  */
28952 int
xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)28953 xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
28954 {
28955     xmlSAXHandlerPtr *sax;
28956     void **user_data;
28957 
28958     if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
28959         return(-1);
28960     plug->magic = 0;
28961 
28962     xmlSchemaPostRun(plug->ctxt);
28963     /* restore the data */
28964     sax = plug->user_sax_ptr;
28965     *sax = plug->user_sax;
28966     if (plug->user_sax != NULL) {
28967 	user_data = plug->user_data_ptr;
28968 	*user_data = plug->user_data;
28969     }
28970 
28971     /* free and return */
28972     xmlFree(plug);
28973     return(0);
28974 }
28975 
28976 /**
28977  * xmlSchemaValidateSetLocator:
28978  * @vctxt: a schema validation context
28979  * @f: the locator function pointer
28980  * @ctxt: the locator context
28981  *
28982  * Allows to set a locator function to the validation context,
28983  * which will be used to provide file and line information since
28984  * those are not provided as part of the SAX validation flow
28985  * Setting @f to NULL disable the locator.
28986  */
28987 
28988 void
xmlSchemaValidateSetLocator(xmlSchemaValidCtxtPtr vctxt,xmlSchemaValidityLocatorFunc f,void * ctxt)28989 xmlSchemaValidateSetLocator(xmlSchemaValidCtxtPtr vctxt,
28990                             xmlSchemaValidityLocatorFunc f,
28991 			    void *ctxt)
28992 {
28993     if (vctxt == NULL) return;
28994     vctxt->locFunc = f;
28995     vctxt->locCtxt = ctxt;
28996 }
28997 
28998 /**
28999  * xmlSchemaValidateStreamLocator:
29000  * @ctx: the xmlTextReaderPtr used
29001  * @file: returned file information
29002  * @line: returned line information
29003  *
29004  * Internal locator function for the readers
29005  *
29006  * Returns 0 in case the Schema validation could be (de)activated and
29007  *         -1 in case of error.
29008  */
29009 static int
xmlSchemaValidateStreamLocator(void * ctx,const char ** file,unsigned long * line)29010 xmlSchemaValidateStreamLocator(void *ctx, const char **file,
29011                                unsigned long *line) {
29012     xmlParserCtxtPtr ctxt;
29013 
29014     if ((ctx == NULL) || ((file == NULL) && (line == NULL)))
29015         return(-1);
29016 
29017     if (file != NULL)
29018         *file = NULL;
29019     if (line != NULL)
29020         *line = 0;
29021 
29022     ctxt = (xmlParserCtxtPtr) ctx;
29023     if (ctxt->input != NULL) {
29024        if (file != NULL)
29025            *file = ctxt->input->filename;
29026        if (line != NULL)
29027            *line = ctxt->input->line;
29028        return(0);
29029     }
29030     return(-1);
29031 }
29032 
29033 /**
29034  * xmlSchemaValidateStream:
29035  * @ctxt:  a schema validation context
29036  * @input:  the input to use for reading the data
29037  * @enc:  an optional encoding information
29038  * @sax:  a SAX handler for the resulting events
29039  * @user_data:  the context to provide to the SAX handler.
29040  *
29041  * Validate an input based on a flow of SAX event from the parser
29042  * and forward the events to the @sax handler with the provided @user_data
29043  * the user provided @sax handler must be a SAX2 one.
29044  *
29045  * Returns 0 if the document is schemas valid, a positive error code
29046  *     number otherwise and -1 in case of internal or API error.
29047  */
29048 int
xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,xmlParserInputBufferPtr input,xmlCharEncoding enc,xmlSAXHandlerPtr sax,void * user_data)29049 xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
29050                         xmlParserInputBufferPtr input, xmlCharEncoding enc,
29051                         xmlSAXHandlerPtr sax, void *user_data)
29052 {
29053     xmlSchemaSAXPlugPtr plug = NULL;
29054     xmlSAXHandlerPtr old_sax = NULL;
29055     xmlParserCtxtPtr pctxt = NULL;
29056     xmlParserInputPtr inputStream = NULL;
29057     int ret;
29058 
29059     if ((ctxt == NULL) || (input == NULL))
29060         return (-1);
29061 
29062     /*
29063      * prepare the parser
29064      */
29065     pctxt = xmlNewParserCtxt();
29066     if (pctxt == NULL)
29067         return (-1);
29068     old_sax = pctxt->sax;
29069     pctxt->sax = sax;
29070     pctxt->userData = user_data;
29071 #if 0
29072     if (options)
29073         xmlCtxtUseOptions(pctxt, options);
29074 #endif
29075     pctxt->linenumbers = 1;
29076     xmlSchemaValidateSetLocator(ctxt, xmlSchemaValidateStreamLocator, pctxt);
29077 
29078     inputStream = xmlNewIOInputStream(pctxt, input, enc);;
29079     if (inputStream == NULL) {
29080         ret = -1;
29081 	goto done;
29082     }
29083     inputPush(pctxt, inputStream);
29084     ctxt->parserCtxt = pctxt;
29085     ctxt->input = input;
29086 
29087     /*
29088      * Plug the validation and launch the parsing
29089      */
29090     plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
29091     if (plug == NULL) {
29092         ret = -1;
29093 	goto done;
29094     }
29095     ctxt->input = input;
29096     ctxt->enc = enc;
29097     ctxt->sax = pctxt->sax;
29098     ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
29099     ret = xmlSchemaVStart(ctxt);
29100 
29101     if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
29102 	ret = ctxt->parserCtxt->errNo;
29103 	if (ret == 0)
29104 	    ret = 1;
29105     }
29106 
29107 done:
29108     ctxt->parserCtxt = NULL;
29109     ctxt->sax = NULL;
29110     ctxt->input = NULL;
29111     if (plug != NULL) {
29112         xmlSchemaSAXUnplug(plug);
29113     }
29114     /* cleanup */
29115     if (pctxt != NULL) {
29116 	pctxt->sax = old_sax;
29117 	xmlFreeParserCtxt(pctxt);
29118     }
29119     return (ret);
29120 }
29121 
29122 /**
29123  * xmlSchemaValidateFile:
29124  * @ctxt: a schema validation context
29125  * @filename: the URI of the instance
29126  * @options: a future set of options, currently unused
29127  *
29128  * Do a schemas validation of the given resource, it will use the
29129  * SAX streamable validation internally.
29130  *
29131  * Returns 0 if the document is valid, a positive error code
29132  *     number otherwise and -1 in case of an internal or API error.
29133  */
29134 int
xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,const char * filename,int options ATTRIBUTE_UNUSED)29135 xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
29136                       const char * filename,
29137 		      int options ATTRIBUTE_UNUSED)
29138 {
29139     int ret;
29140     xmlParserInputBufferPtr input;
29141 
29142     if ((ctxt == NULL) || (filename == NULL))
29143         return (-1);
29144 
29145     input = xmlParserInputBufferCreateFilename(filename,
29146 	XML_CHAR_ENCODING_NONE);
29147     if (input == NULL)
29148 	return (-1);
29149     ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
29150 	NULL, NULL);
29151     return (ret);
29152 }
29153 
29154 /**
29155  * xmlSchemaValidCtxtGetParserCtxt:
29156  * @ctxt: a schema validation context
29157  *
29158  * allow access to the parser context of the schema validation context
29159  *
29160  * Returns the parser context of the schema validation context or NULL
29161  *         in case of error.
29162  */
29163 xmlParserCtxtPtr
xmlSchemaValidCtxtGetParserCtxt(xmlSchemaValidCtxtPtr ctxt)29164 xmlSchemaValidCtxtGetParserCtxt(xmlSchemaValidCtxtPtr ctxt)
29165 {
29166     if (ctxt == NULL)
29167         return(NULL);
29168     return (ctxt->parserCtxt);
29169 }
29170 
29171 #define bottom_xmlschemas
29172 #include "elfgcchack.h"
29173 #endif /* LIBXML_SCHEMAS_ENABLED */
29174