• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * schemas.c : implementation of the XML Schema handling and
3  *             schema validity checking
4  *
5  * See Copyright for the status of this software.
6  *
7  * Daniel Veillard <veillard@redhat.com>
8  */
9 
10 /*
11  * TODO:
12  *   - when types are redefined in includes, check that all
13  *     types in the redef list are equal
14  *     -> need a type equality operation.
15  *   - if we don't intend to use the schema for schemas, we
16  *     need to validate all schema attributes (ref, type, name)
17  *     against their types.
18  *   - Eliminate item creation for: ??
19  *
20  * URGENT TODO:
21  *   - For xsi-driven schema acquisition, augment the IDCs after every
22  *     acquisition episode (xmlSchemaAugmentIDC).
23  *
24  * NOTES:
25  *   - 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     if (item == NULL) {
1346         return (NULL);
1347     }
1348     switch (item->type) {
1349 	case XML_SCHEMA_TYPE_ELEMENT:
1350 	    return (((xmlSchemaElementPtr) item)->name);
1351 	case XML_SCHEMA_TYPE_ATTRIBUTE:
1352 	    return (((xmlSchemaAttributePtr) item)->name);
1353 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1354 	    return (((xmlSchemaAttributeGroupPtr) item)->name);
1355 	case XML_SCHEMA_TYPE_BASIC:
1356 	case XML_SCHEMA_TYPE_SIMPLE:
1357 	case XML_SCHEMA_TYPE_COMPLEX:
1358 	    return (((xmlSchemaTypePtr) item)->name);
1359 	case XML_SCHEMA_TYPE_GROUP:
1360 	    return (((xmlSchemaModelGroupDefPtr) item)->name);
1361 	case XML_SCHEMA_TYPE_IDC_KEY:
1362 	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1363 	case XML_SCHEMA_TYPE_IDC_KEYREF:
1364 	    return (((xmlSchemaIDCPtr) item)->name);
1365 	case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1366 	    if (WXS_ATTRUSE_DECL(item) != NULL) {
1367 		return(xmlSchemaGetComponentName(
1368 		    WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1369 	    } else
1370 		return(NULL);
1371 	case XML_SCHEMA_EXTRA_QNAMEREF:
1372 	    return (((xmlSchemaQNameRefPtr) item)->name);
1373 	case XML_SCHEMA_TYPE_NOTATION:
1374 	    return (((xmlSchemaNotationPtr) item)->name);
1375 	default:
1376 	    /*
1377 	    * Other components cannot have names.
1378 	    */
1379 	    break;
1380     }
1381     return (NULL);
1382 }
1383 
1384 #define xmlSchemaGetQNameRefName(r) (WXS_QNAME_CAST (r))->name
1385 #define xmlSchemaGetQNameRefTargetNs(r) (WXS_QNAME_CAST (r))->targetNamespace
1386 /*
1387 static const xmlChar *
1388 xmlSchemaGetQNameRefName(void *ref)
1389 {
1390     return(((xmlSchemaQNameRefPtr) ref)->name);
1391 }
1392 
1393 static const xmlChar *
1394 xmlSchemaGetQNameRefTargetNs(void *ref)
1395 {
1396     return(((xmlSchemaQNameRefPtr) ref)->targetNamespace);
1397 }
1398 */
1399 
1400 static const xmlChar *
xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)1401 xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
1402 {
1403     if (item == NULL) {
1404         return (NULL);
1405     }
1406     switch (item->type) {
1407 	case XML_SCHEMA_TYPE_ELEMENT:
1408 	    return (((xmlSchemaElementPtr) item)->targetNamespace);
1409 	case XML_SCHEMA_TYPE_ATTRIBUTE:
1410 	    return (((xmlSchemaAttributePtr) item)->targetNamespace);
1411 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1412 	    return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
1413 	case XML_SCHEMA_TYPE_BASIC:
1414 	    return (BAD_CAST "http://www.w3.org/2001/XMLSchema");
1415 	case XML_SCHEMA_TYPE_SIMPLE:
1416 	case XML_SCHEMA_TYPE_COMPLEX:
1417 	    return (((xmlSchemaTypePtr) item)->targetNamespace);
1418 	case XML_SCHEMA_TYPE_GROUP:
1419 	    return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1420 	case XML_SCHEMA_TYPE_IDC_KEY:
1421 	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1422 	case XML_SCHEMA_TYPE_IDC_KEYREF:
1423 	    return (((xmlSchemaIDCPtr) item)->targetNamespace);
1424 	case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1425 	    if (WXS_ATTRUSE_DECL(item) != NULL) {
1426 		return(xmlSchemaGetComponentTargetNs(
1427 		    WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1428 	    }
1429 	    /* TODO: Will returning NULL break something? */
1430 	    break;
1431 	case XML_SCHEMA_EXTRA_QNAMEREF:
1432 	    return (((xmlSchemaQNameRefPtr) item)->targetNamespace);
1433 	case XML_SCHEMA_TYPE_NOTATION:
1434 	    return (((xmlSchemaNotationPtr) item)->targetNamespace);
1435 	default:
1436 	    /*
1437 	    * Other components cannot have names.
1438 	    */
1439 	    break;
1440     }
1441     return (NULL);
1442 }
1443 
1444 static const xmlChar*
xmlSchemaGetComponentQName(xmlChar ** buf,void * item)1445 xmlSchemaGetComponentQName(xmlChar **buf,
1446 			   void *item)
1447 {
1448     return (xmlSchemaFormatQName(buf,
1449 	xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1450 	xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1451 }
1452 
1453 static const xmlChar*
xmlSchemaGetComponentDesignation(xmlChar ** buf,void * item)1454 xmlSchemaGetComponentDesignation(xmlChar **buf, void *item)
1455 {
1456     xmlChar *str = NULL;
1457 
1458     *buf = xmlStrcat(*buf, WXS_ITEM_TYPE_NAME(item));
1459     *buf = xmlStrcat(*buf, BAD_CAST " '");
1460     *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str,
1461 	(xmlSchemaBasicItemPtr) item));
1462     *buf = xmlStrcat(*buf, BAD_CAST "'");
1463     FREE_AND_NULL(str);
1464     return(*buf);
1465 }
1466 
1467 static const xmlChar*
xmlSchemaGetIDCDesignation(xmlChar ** buf,xmlSchemaIDCPtr idc)1468 xmlSchemaGetIDCDesignation(xmlChar **buf, xmlSchemaIDCPtr idc)
1469 {
1470     return(xmlSchemaGetComponentDesignation(buf, idc));
1471 }
1472 
1473 /**
1474  * xmlSchemaWildcardPCToString:
1475  * @pc: the type of processContents
1476  *
1477  * Returns a string representation of the type of
1478  * processContents.
1479  */
1480 static const xmlChar *
xmlSchemaWildcardPCToString(int pc)1481 xmlSchemaWildcardPCToString(int pc)
1482 {
1483     switch (pc) {
1484 	case XML_SCHEMAS_ANY_SKIP:
1485 	    return (BAD_CAST "skip");
1486 	case XML_SCHEMAS_ANY_LAX:
1487 	    return (BAD_CAST "lax");
1488 	case XML_SCHEMAS_ANY_STRICT:
1489 	    return (BAD_CAST "strict");
1490 	default:
1491 	    return (BAD_CAST "invalid process contents");
1492     }
1493 }
1494 
1495 /**
1496  * xmlSchemaGetCanonValueWhtspExt:
1497  * @val: the precomputed value
1498  * @retValue: the returned value
1499  * @ws: the whitespace type of the value
1500  * @for_hash: non-zero if this is supposed to generate a string for hashing
1501  *
1502  * Get a the canonical representation of the value.
1503  * The caller has to free the returned retValue.
1504  *
1505  * Returns 0 if the value could be built and -1 in case of
1506  *         API errors or if the value type is not supported yet.
1507  */
1508 static int
xmlSchemaGetCanonValueWhtspExt_1(xmlSchemaValPtr val,xmlSchemaWhitespaceValueType ws,xmlChar ** retValue,int for_hash)1509 xmlSchemaGetCanonValueWhtspExt_1(xmlSchemaValPtr val,
1510 			         xmlSchemaWhitespaceValueType ws,
1511 			         xmlChar **retValue,
1512 				 int for_hash)
1513 {
1514     int list;
1515     xmlSchemaValType valType;
1516     const xmlChar *value, *value2 = NULL;
1517 
1518 
1519     if ((retValue == NULL) || (val == NULL))
1520 	return (-1);
1521     list = xmlSchemaValueGetNext(val) ? 1 : 0;
1522     *retValue = NULL;
1523     do {
1524 	value = NULL;
1525 	valType = xmlSchemaGetValType(val);
1526 	switch (valType) {
1527 	    case XML_SCHEMAS_STRING:
1528 	    case XML_SCHEMAS_NORMSTRING:
1529 	    case XML_SCHEMAS_ANYSIMPLETYPE:
1530 		value = xmlSchemaValueGetAsString(val);
1531 		if (value != NULL) {
1532 		    if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1533 			value2 = xmlSchemaCollapseString(value);
1534 		    else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1535 			value2 = xmlSchemaWhiteSpaceReplace(value);
1536 		    if (value2 != NULL)
1537 			value = value2;
1538 		}
1539 		break;
1540 	    default:
1541 		if (xmlSchemaGetCanonValue(val, &value2) == -1) {
1542 		    if (value2 != NULL)
1543 			xmlFree((xmlChar *) value2);
1544 		    goto internal_error;
1545 		}
1546 		if (for_hash && valType == XML_SCHEMAS_DECIMAL) {
1547 		    /* We can mostly use the canonical value for hashing,
1548 		       except in the case of decimal.  There the canonical
1549 		       representation requires a trailing '.0' even for
1550 		       non-fractional numbers, but for the derived integer
1551 		       types it forbids any decimal point.  Nevertheless they
1552 		       compare equal if the value is equal.  We need to generate
1553 		       the same hash value for this to work, and it's easiest
1554 		       to just cut off the useless '.0' suffix for the
1555 		       decimal type.  */
1556 		    int len = xmlStrlen(value2);
1557 		    if (len > 2 && value2[len-1] == '0' && value2[len-2] == '.')
1558 		      ((xmlChar*)value2)[len-2] = 0;
1559 		}
1560 		value = value2;
1561 	}
1562 	if (*retValue == NULL)
1563 	    if (value == NULL) {
1564 		if (! list)
1565 		    *retValue = xmlStrdup(BAD_CAST "");
1566 	    } else
1567 		*retValue = xmlStrdup(value);
1568 	else if (value != NULL) {
1569 	    /* List. */
1570 	    *retValue = xmlStrcat((xmlChar *) *retValue, BAD_CAST " ");
1571 	    *retValue = xmlStrcat((xmlChar *) *retValue, value);
1572 	}
1573 	FREE_AND_NULL(value2)
1574 	val = xmlSchemaValueGetNext(val);
1575     } while (val != NULL);
1576 
1577     return (0);
1578 internal_error:
1579     if (*retValue != NULL)
1580 	xmlFree((xmlChar *) (*retValue));
1581     if (value2 != NULL)
1582 	xmlFree((xmlChar *) value2);
1583     return (-1);
1584 }
1585 
1586 static int
xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,xmlSchemaWhitespaceValueType ws,xmlChar ** retValue)1587 xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
1588 			       xmlSchemaWhitespaceValueType ws,
1589 			       xmlChar **retValue)
1590 {
1591     return xmlSchemaGetCanonValueWhtspExt_1(val, ws, retValue, 0);
1592 }
1593 
1594 static int
xmlSchemaGetCanonValueHash(xmlSchemaValPtr val,xmlChar ** retValue)1595 xmlSchemaGetCanonValueHash(xmlSchemaValPtr val,
1596 			   xmlChar **retValue)
1597 {
1598     return xmlSchemaGetCanonValueWhtspExt_1(val, XML_SCHEMA_WHITESPACE_COLLAPSE,
1599 					    retValue, 1);
1600 }
1601 
1602 /**
1603  * xmlSchemaFormatItemForReport:
1604  * @buf: the string buffer
1605  * @itemDes: the designation of the item
1606  * @itemName: the name of the item
1607  * @item: the item as an object
1608  * @itemNode: the node of the item
1609  * @local: the local name
1610  * @parsing: if the function is used during the parse
1611  *
1612  * Returns a representation of the given item used
1613  * for error reports.
1614  *
1615  * The following order is used to build the resulting
1616  * designation if the arguments are not NULL:
1617  * 1a. If itemDes not NULL -> itemDes
1618  * 1b. If (itemDes not NULL) and (itemName not NULL)
1619  *     -> itemDes + itemName
1620  * 2. If the preceding was NULL and (item not NULL) -> item
1621  * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
1622  *
1623  * If the itemNode is an attribute node, the name of the attribute
1624  * will be appended to the result.
1625  *
1626  * Returns the formatted string and sets @buf to the resulting value.
1627  */
1628 static xmlChar*
xmlSchemaFormatItemForReport(xmlChar ** buf,const xmlChar * itemDes,xmlSchemaBasicItemPtr item,xmlNodePtr itemNode)1629 xmlSchemaFormatItemForReport(xmlChar **buf,
1630 		     const xmlChar *itemDes,
1631 		     xmlSchemaBasicItemPtr item,
1632 		     xmlNodePtr itemNode)
1633 {
1634     xmlChar *str = NULL;
1635     int named = 1;
1636 
1637     if (*buf != NULL) {
1638 	xmlFree(*buf);
1639 	*buf = NULL;
1640     }
1641 
1642     if (itemDes != NULL) {
1643 	*buf = xmlStrdup(itemDes);
1644     } else if (item != NULL) {
1645 	switch (item->type) {
1646 	case XML_SCHEMA_TYPE_BASIC: {
1647 	    xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1648 
1649 	    if (WXS_IS_ATOMIC(type))
1650 		*buf = xmlStrdup(BAD_CAST "atomic type 'xs:");
1651 	    else if (WXS_IS_LIST(type))
1652 		*buf = xmlStrdup(BAD_CAST "list type 'xs:");
1653 	    else if (WXS_IS_UNION(type))
1654 		*buf = xmlStrdup(BAD_CAST "union type 'xs:");
1655 	    else
1656 		*buf = xmlStrdup(BAD_CAST "simple type 'xs:");
1657 	    *buf = xmlStrcat(*buf, type->name);
1658 	    *buf = xmlStrcat(*buf, BAD_CAST "'");
1659 	    }
1660 	    break;
1661 	case XML_SCHEMA_TYPE_SIMPLE: {
1662 	    xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1663 
1664 	    if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1665 		*buf = xmlStrdup(BAD_CAST"");
1666 	    } else {
1667 		*buf = xmlStrdup(BAD_CAST "local ");
1668 	    }
1669 	    if (WXS_IS_ATOMIC(type))
1670 		*buf = xmlStrcat(*buf, BAD_CAST "atomic type");
1671 	    else if (WXS_IS_LIST(type))
1672 		*buf = xmlStrcat(*buf, BAD_CAST "list type");
1673 	    else if (WXS_IS_UNION(type))
1674 		*buf = xmlStrcat(*buf, BAD_CAST "union type");
1675 	    else
1676 		*buf = xmlStrcat(*buf, BAD_CAST "simple type");
1677 	    if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1678 		*buf = xmlStrcat(*buf, BAD_CAST " '");
1679 		*buf = xmlStrcat(*buf, type->name);
1680 		*buf = xmlStrcat(*buf, BAD_CAST "'");
1681 	    }
1682 	    }
1683 	    break;
1684 	case XML_SCHEMA_TYPE_COMPLEX: {
1685 	    xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1686 
1687 	    if (type->flags & XML_SCHEMAS_TYPE_GLOBAL)
1688 		*buf = xmlStrdup(BAD_CAST "");
1689 	    else
1690 		*buf = xmlStrdup(BAD_CAST "local ");
1691 	    *buf = xmlStrcat(*buf, BAD_CAST "complex type");
1692 	    if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1693 		*buf = xmlStrcat(*buf, BAD_CAST " '");
1694 		*buf = xmlStrcat(*buf, type->name);
1695 		*buf = xmlStrcat(*buf, BAD_CAST "'");
1696 	    }
1697 	    }
1698 	    break;
1699 	case XML_SCHEMA_TYPE_ATTRIBUTE_USE: {
1700 		xmlSchemaAttributeUsePtr ause;
1701 
1702 		ause = WXS_ATTR_USE_CAST item;
1703 		*buf = xmlStrdup(BAD_CAST "attribute use ");
1704 		if (WXS_ATTRUSE_DECL(ause) != NULL) {
1705 		    *buf = xmlStrcat(*buf, BAD_CAST "'");
1706 		    *buf = xmlStrcat(*buf,
1707 			xmlSchemaGetComponentQName(&str, WXS_ATTRUSE_DECL(ause)));
1708 		    FREE_AND_NULL(str)
1709 			*buf = xmlStrcat(*buf, BAD_CAST "'");
1710 		} else {
1711 		    *buf = xmlStrcat(*buf, BAD_CAST "(unknown)");
1712 		}
1713 	    }
1714 	    break;
1715 	case XML_SCHEMA_TYPE_ATTRIBUTE: {
1716 		xmlSchemaAttributePtr attr;
1717 
1718 		attr = (xmlSchemaAttributePtr) item;
1719 		*buf = xmlStrdup(BAD_CAST "attribute decl.");
1720 		*buf = xmlStrcat(*buf, BAD_CAST " '");
1721 		*buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1722 		    attr->targetNamespace, attr->name));
1723 		FREE_AND_NULL(str)
1724 		    *buf = xmlStrcat(*buf, BAD_CAST "'");
1725 	    }
1726 	    break;
1727 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1728 	    xmlSchemaGetComponentDesignation(buf, item);
1729 	    break;
1730 	case XML_SCHEMA_TYPE_ELEMENT: {
1731 		xmlSchemaElementPtr elem;
1732 
1733 		elem = (xmlSchemaElementPtr) item;
1734 		*buf = xmlStrdup(BAD_CAST "element decl.");
1735 		*buf = xmlStrcat(*buf, BAD_CAST " '");
1736 		*buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1737 		    elem->targetNamespace, elem->name));
1738 		*buf = xmlStrcat(*buf, BAD_CAST "'");
1739 	    }
1740 	    break;
1741 	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1742 	case XML_SCHEMA_TYPE_IDC_KEY:
1743 	case XML_SCHEMA_TYPE_IDC_KEYREF:
1744 	    if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1745 		*buf = xmlStrdup(BAD_CAST "unique '");
1746 	    else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1747 		*buf = xmlStrdup(BAD_CAST "key '");
1748 	    else
1749 		*buf = xmlStrdup(BAD_CAST "keyRef '");
1750 	    *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1751 	    *buf = xmlStrcat(*buf, BAD_CAST "'");
1752 	    break;
1753 	case XML_SCHEMA_TYPE_ANY:
1754 	case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1755 	    *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1756 		    ((xmlSchemaWildcardPtr) item)->processContents));
1757 	    *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1758 	    break;
1759 	case XML_SCHEMA_FACET_MININCLUSIVE:
1760 	case XML_SCHEMA_FACET_MINEXCLUSIVE:
1761 	case XML_SCHEMA_FACET_MAXINCLUSIVE:
1762 	case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1763 	case XML_SCHEMA_FACET_TOTALDIGITS:
1764 	case XML_SCHEMA_FACET_FRACTIONDIGITS:
1765 	case XML_SCHEMA_FACET_PATTERN:
1766 	case XML_SCHEMA_FACET_ENUMERATION:
1767 	case XML_SCHEMA_FACET_WHITESPACE:
1768 	case XML_SCHEMA_FACET_LENGTH:
1769 	case XML_SCHEMA_FACET_MAXLENGTH:
1770 	case XML_SCHEMA_FACET_MINLENGTH:
1771 	    *buf = xmlStrdup(BAD_CAST "facet '");
1772 	    *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1773 	    *buf = xmlStrcat(*buf, BAD_CAST "'");
1774 	    break;
1775 	case XML_SCHEMA_TYPE_GROUP: {
1776 		*buf = xmlStrdup(BAD_CAST "model group def.");
1777 		*buf = xmlStrcat(*buf, BAD_CAST " '");
1778 		*buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1779 		*buf = xmlStrcat(*buf, BAD_CAST "'");
1780 		FREE_AND_NULL(str)
1781 	    }
1782 	    break;
1783 	case XML_SCHEMA_TYPE_SEQUENCE:
1784 	case XML_SCHEMA_TYPE_CHOICE:
1785 	case XML_SCHEMA_TYPE_ALL:
1786 	case XML_SCHEMA_TYPE_PARTICLE:
1787 	    *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1788 	    break;
1789 	case XML_SCHEMA_TYPE_NOTATION: {
1790 		*buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1791 		*buf = xmlStrcat(*buf, BAD_CAST " '");
1792 		*buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1793 		*buf = xmlStrcat(*buf, BAD_CAST "'");
1794 		FREE_AND_NULL(str);
1795 	    }
1796             /* Falls through. */
1797 	default:
1798 	    named = 0;
1799 	}
1800     } else
1801 	named = 0;
1802 
1803     if ((named == 0) && (itemNode != NULL)) {
1804 	xmlNodePtr elem;
1805 
1806 	if (itemNode->type == XML_ATTRIBUTE_NODE)
1807 	    elem = itemNode->parent;
1808 	else
1809 	    elem = itemNode;
1810 	*buf = xmlStrdup(BAD_CAST "Element '");
1811 	if (elem->ns != NULL) {
1812 	    *buf = xmlStrcat(*buf,
1813 		xmlSchemaFormatQName(&str, elem->ns->href, elem->name));
1814 	    FREE_AND_NULL(str)
1815 	} else
1816 	    *buf = xmlStrcat(*buf, elem->name);
1817 	*buf = xmlStrcat(*buf, BAD_CAST "'");
1818 
1819     }
1820     if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1821 	*buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1822 	if (itemNode->ns != NULL) {
1823 	    *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1824 		itemNode->ns->href, itemNode->name));
1825 	    FREE_AND_NULL(str)
1826 	} else
1827 	    *buf = xmlStrcat(*buf, itemNode->name);
1828 	*buf = xmlStrcat(*buf, BAD_CAST "'");
1829     }
1830     FREE_AND_NULL(str)
1831 
1832     return (xmlEscapeFormatString(buf));
1833 }
1834 
1835 /**
1836  * xmlSchemaFormatFacetEnumSet:
1837  * @buf: the string buffer
1838  * @type: the type holding the enumeration facets
1839  *
1840  * Builds a string consisting of all enumeration elements.
1841  *
1842  * Returns a string of all enumeration elements.
1843  */
1844 static const xmlChar *
xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,xmlChar ** buf,xmlSchemaTypePtr type)1845 xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,
1846 			    xmlChar **buf, xmlSchemaTypePtr type)
1847 {
1848     xmlSchemaFacetPtr facet;
1849     xmlSchemaWhitespaceValueType ws;
1850     xmlChar *value = NULL;
1851     int res, found = 0;
1852 
1853     if (*buf != NULL)
1854 	xmlFree(*buf);
1855     *buf = NULL;
1856 
1857     do {
1858 	/*
1859 	* Use the whitespace type of the base type.
1860 	*/
1861 	ws = xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
1862 	for (facet = type->facets; facet != NULL; facet = facet->next) {
1863 	    if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1864 		continue;
1865 	    found = 1;
1866 	    res = xmlSchemaGetCanonValueWhtspExt(facet->val,
1867 		ws, &value);
1868 	    if (res == -1) {
1869 		xmlSchemaInternalErr(actxt,
1870 		    "xmlSchemaFormatFacetEnumSet",
1871 		    "compute the canonical lexical representation");
1872 		if (*buf != NULL)
1873 		    xmlFree(*buf);
1874 		*buf = NULL;
1875 		return (NULL);
1876 	    }
1877 	    if (*buf == NULL)
1878 		*buf = xmlStrdup(BAD_CAST "'");
1879 	    else
1880 		*buf = xmlStrcat(*buf, BAD_CAST ", '");
1881 	    *buf = xmlStrcat(*buf, BAD_CAST value);
1882 	    *buf = xmlStrcat(*buf, BAD_CAST "'");
1883 	    if (value != NULL) {
1884 		xmlFree((xmlChar *)value);
1885 		value = NULL;
1886 	    }
1887 	}
1888 	/*
1889 	* The enumeration facet of a type restricts the enumeration
1890 	* facet of the ancestor type; i.e., such restricted enumerations
1891 	* do not belong to the set of the given type. Thus we break
1892 	* on the first found enumeration.
1893 	*/
1894 	if (found)
1895 	    break;
1896 	type = type->baseType;
1897     } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
1898 
1899     return ((const xmlChar *) *buf);
1900 }
1901 
1902 /************************************************************************
1903  *									*
1904  *			Error functions				        *
1905  *									*
1906  ************************************************************************/
1907 
1908 #if 0
1909 static void
1910 xmlSchemaErrMemory(const char *msg)
1911 {
1912     __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1913                      msg);
1914 }
1915 #endif
1916 
1917 static void
xmlSchemaPSimpleErr(const char * msg)1918 xmlSchemaPSimpleErr(const char *msg)
1919 {
1920     __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1921                      msg);
1922 }
1923 
1924 /**
1925  * xmlSchemaPErrMemory:
1926  * @node: a context node
1927  * @extra:  extra information
1928  *
1929  * Handle an out of memory condition
1930  */
1931 static void
xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,const char * extra,xmlNodePtr node)1932 xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
1933                     const char *extra, xmlNodePtr node)
1934 {
1935     if (ctxt != NULL)
1936         ctxt->nberrors++;
1937     __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
1938                      extra);
1939 }
1940 
1941 /**
1942  * xmlSchemaPErr:
1943  * @ctxt: the parsing context
1944  * @node: the context node
1945  * @error: the error code
1946  * @msg: the error message
1947  * @str1: extra data
1948  * @str2: extra data
1949  *
1950  * Handle a parser error
1951  */
1952 static void LIBXML_ATTR_FORMAT(4,0)
xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int error,const char * msg,const xmlChar * str1,const xmlChar * str2)1953 xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1954               const char *msg, const xmlChar * str1, const xmlChar * str2)
1955 {
1956     xmlGenericErrorFunc channel = NULL;
1957     xmlStructuredErrorFunc schannel = NULL;
1958     void *data = NULL;
1959 
1960     if (ctxt != NULL) {
1961         ctxt->nberrors++;
1962 	ctxt->err = error;
1963         channel = ctxt->error;
1964         data = ctxt->errCtxt;
1965 	schannel = ctxt->serror;
1966     }
1967     __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1968                     error, XML_ERR_ERROR, NULL, 0,
1969                     (const char *) str1, (const char *) str2, NULL, 0, 0,
1970                     msg, str1, str2);
1971 }
1972 
1973 /**
1974  * xmlSchemaPErr2:
1975  * @ctxt: the parsing context
1976  * @node: the context node
1977  * @node: the current child
1978  * @error: the error code
1979  * @msg: the error message
1980  * @str1: extra data
1981  * @str2: extra data
1982  *
1983  * Handle a parser error
1984  */
1985 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)1986 xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1987                xmlNodePtr child, int error,
1988                const char *msg, const xmlChar * str1, const xmlChar * str2)
1989 {
1990     if (child != NULL)
1991         xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
1992     else
1993         xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
1994 }
1995 
1996 
1997 /**
1998  * xmlSchemaPErrExt:
1999  * @ctxt: the parsing context
2000  * @node: the context node
2001  * @error: the error code
2002  * @strData1: extra data
2003  * @strData2: extra data
2004  * @strData3: extra data
2005  * @msg: the message
2006  * @str1:  extra parameter for the message display
2007  * @str2:  extra parameter for the message display
2008  * @str3:  extra parameter for the message display
2009  * @str4:  extra parameter for the message display
2010  * @str5:  extra parameter for the message display
2011  *
2012  * Handle a parser error
2013  */
2014 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)2015 xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
2016 		const xmlChar * strData1, const xmlChar * strData2,
2017 		const xmlChar * strData3, const char *msg, const xmlChar * str1,
2018 		const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
2019 		const xmlChar * str5)
2020 {
2021 
2022     xmlGenericErrorFunc channel = NULL;
2023     xmlStructuredErrorFunc schannel = NULL;
2024     void *data = NULL;
2025 
2026     if (ctxt != NULL) {
2027         ctxt->nberrors++;
2028 	ctxt->err = error;
2029         channel = ctxt->error;
2030         data = ctxt->errCtxt;
2031 	schannel = ctxt->serror;
2032     }
2033     __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
2034                     error, XML_ERR_ERROR, NULL, 0,
2035                     (const char *) strData1, (const char *) strData2,
2036 		    (const char *) strData3, 0, 0, msg, str1, str2,
2037 		    str3, str4, str5);
2038 }
2039 
2040 /************************************************************************
2041  *									*
2042  *			Allround error functions			*
2043  *									*
2044  ************************************************************************/
2045 
2046 /**
2047  * xmlSchemaVTypeErrMemory:
2048  * @node: a context node
2049  * @extra:  extra information
2050  *
2051  * Handle an out of memory condition
2052  */
2053 static void
xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,const char * extra,xmlNodePtr node)2054 xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
2055                     const char *extra, xmlNodePtr node)
2056 {
2057     if (ctxt != NULL) {
2058         ctxt->nberrors++;
2059         ctxt->err = XML_SCHEMAV_INTERNAL;
2060     }
2061     __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
2062                      extra);
2063 }
2064 
2065 static void LIBXML_ATTR_FORMAT(2,0)
xmlSchemaPSimpleInternalErr(xmlNodePtr node,const char * msg,const xmlChar * str)2066 xmlSchemaPSimpleInternalErr(xmlNodePtr node,
2067 			    const char *msg, const xmlChar *str)
2068 {
2069      __xmlSimpleError(XML_FROM_SCHEMASP, XML_SCHEMAP_INTERNAL, node,
2070 	 msg, (const char *) str);
2071 }
2072 
2073 #define WXS_ERROR_TYPE_ERROR 1
2074 #define WXS_ERROR_TYPE_WARNING 2
2075 /**
2076  * xmlSchemaErr4Line:
2077  * @ctxt: the validation context
2078  * @errorLevel: the error level
2079  * @error: the error code
2080  * @node: the context node
2081  * @line: the line number
2082  * @msg: the error message
2083  * @str1: extra data
2084  * @str2: extra data
2085  * @str3: extra data
2086  * @str4: extra data
2087  *
2088  * Handle a validation error
2089  */
2090 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)2091 xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt,
2092 		  xmlErrorLevel errorLevel,
2093 		  int error, xmlNodePtr node, int line, const char *msg,
2094 		  const xmlChar *str1, const xmlChar *str2,
2095 		  const xmlChar *str3, const xmlChar *str4)
2096 {
2097     xmlStructuredErrorFunc schannel = NULL;
2098     xmlGenericErrorFunc channel = NULL;
2099     void *data = NULL;
2100 
2101     if (ctxt != NULL) {
2102 	if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2103 	    xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
2104 	    const char *file = NULL;
2105 	    int col = 0;
2106 	    if (errorLevel != XML_ERR_WARNING) {
2107 		vctxt->nberrors++;
2108 		vctxt->err = error;
2109 		channel = vctxt->error;
2110 	    } else {
2111 		channel = vctxt->warning;
2112 	    }
2113 	    schannel = vctxt->serror;
2114 	    data = vctxt->errCtxt;
2115 
2116 	    /*
2117 	    * Error node. If we specify a line number, then
2118 	    * do not channel any node to the error function.
2119 	    */
2120 	    if (line == 0) {
2121 		if ((node == NULL) &&
2122 		    (vctxt->depth >= 0) &&
2123 		    (vctxt->inode != NULL)) {
2124 		    node = vctxt->inode->node;
2125 		}
2126 		/*
2127 		* Get filename and line if no node-tree.
2128 		*/
2129 		if ((node == NULL) &&
2130 		    (vctxt->parserCtxt != NULL) &&
2131 		    (vctxt->parserCtxt->input != NULL)) {
2132 		    file = vctxt->parserCtxt->input->filename;
2133 		    line = vctxt->parserCtxt->input->line;
2134 		    col = vctxt->parserCtxt->input->col;
2135 		}
2136 	    } else {
2137 		/*
2138 		* Override the given node's (if any) position
2139 		* and channel only the given line number.
2140 		*/
2141 		node = NULL;
2142 		/*
2143 		* Get filename.
2144 		*/
2145 		if (vctxt->doc != NULL)
2146 		    file = (const char *) vctxt->doc->URL;
2147 		else if ((vctxt->parserCtxt != NULL) &&
2148 		    (vctxt->parserCtxt->input != NULL))
2149 		    file = vctxt->parserCtxt->input->filename;
2150 	    }
2151 	    if (vctxt->locFunc != NULL) {
2152 	        if ((file == NULL) || (line == 0)) {
2153 		    unsigned long l;
2154 		    const char *f;
2155 		    vctxt->locFunc(vctxt->locCtxt, &f, &l);
2156 		    if (file == NULL)
2157 		        file = f;
2158 		    if (line == 0)
2159 		        line = (int) l;
2160 		}
2161 	    }
2162 	    if ((file == NULL) && (vctxt->filename != NULL))
2163 	        file = vctxt->filename;
2164 
2165 	    __xmlRaiseError(schannel, channel, data, ctxt,
2166 		node, XML_FROM_SCHEMASV,
2167 		error, errorLevel, file, line,
2168 		(const char *) str1, (const char *) str2,
2169 		(const char *) str3, 0, col, msg, str1, str2, str3, str4);
2170 
2171 	} else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
2172 	    xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
2173 	    if (errorLevel != XML_ERR_WARNING) {
2174 		pctxt->nberrors++;
2175 		pctxt->err = error;
2176 		channel = pctxt->error;
2177 	    } else {
2178 		channel = pctxt->warning;
2179 	    }
2180 	    schannel = pctxt->serror;
2181 	    data = pctxt->errCtxt;
2182 	    __xmlRaiseError(schannel, channel, data, ctxt,
2183 		node, XML_FROM_SCHEMASP, error,
2184 		errorLevel, NULL, 0,
2185 		(const char *) str1, (const char *) str2,
2186 		(const char *) str3, 0, 0, msg, str1, str2, str3, str4);
2187 	} else {
2188 	    TODO
2189 	}
2190     }
2191 }
2192 
2193 /**
2194  * xmlSchemaErr3:
2195  * @ctxt: the validation context
2196  * @node: the context node
2197  * @error: the error code
2198  * @msg: the error message
2199  * @str1: extra data
2200  * @str2: extra data
2201  * @str3: extra data
2202  *
2203  * Handle a validation error
2204  */
2205 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)2206 xmlSchemaErr3(xmlSchemaAbstractCtxtPtr actxt,
2207 	      int error, xmlNodePtr node, const char *msg,
2208 	      const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
2209 {
2210     xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2211 	msg, str1, str2, str3, NULL);
2212 }
2213 
2214 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)2215 xmlSchemaErr4(xmlSchemaAbstractCtxtPtr actxt,
2216 	      int error, xmlNodePtr node, const char *msg,
2217 	      const xmlChar *str1, const xmlChar *str2,
2218 	      const xmlChar *str3, const xmlChar *str4)
2219 {
2220     xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2221 	msg, str1, str2, str3, str4);
2222 }
2223 
2224 static void LIBXML_ATTR_FORMAT(4,0)
xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,int error,xmlNodePtr node,const char * msg,const xmlChar * str1,const xmlChar * str2)2225 xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
2226 	     int error, xmlNodePtr node, const char *msg,
2227 	     const xmlChar *str1, const xmlChar *str2)
2228 {
2229     xmlSchemaErr4(actxt, error, node, msg, str1, str2, NULL, NULL);
2230 }
2231 
2232 static xmlChar *
xmlSchemaFormatNodeForError(xmlChar ** msg,xmlSchemaAbstractCtxtPtr actxt,xmlNodePtr node)2233 xmlSchemaFormatNodeForError(xmlChar ** msg,
2234 			    xmlSchemaAbstractCtxtPtr actxt,
2235 			    xmlNodePtr node)
2236 {
2237     xmlChar *str = NULL;
2238 
2239     *msg = NULL;
2240     if ((node != NULL) &&
2241 	(node->type != XML_ELEMENT_NODE) &&
2242 	(node->type != XML_ATTRIBUTE_NODE))
2243     {
2244 	/*
2245 	* Don't try to format other nodes than element and
2246 	* attribute nodes.
2247 	* Play safe and return an empty string.
2248 	*/
2249 	*msg = xmlStrdup(BAD_CAST "");
2250 	return(*msg);
2251     }
2252     if (node != NULL) {
2253 	/*
2254 	* Work on tree nodes.
2255 	*/
2256 	if (node->type == XML_ATTRIBUTE_NODE) {
2257 	    xmlNodePtr elem = node->parent;
2258 
2259 	    *msg = xmlStrdup(BAD_CAST "Element '");
2260 	    if (elem->ns != NULL)
2261 		*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2262 		    elem->ns->href, elem->name));
2263 	    else
2264 		*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2265 		    NULL, elem->name));
2266 	    FREE_AND_NULL(str);
2267 	    *msg = xmlStrcat(*msg, BAD_CAST "', ");
2268 	    *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2269 	} else {
2270 	    *msg = xmlStrdup(BAD_CAST "Element '");
2271 	}
2272 	if (node->ns != NULL)
2273 	    *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2274 	    node->ns->href, node->name));
2275 	else
2276 	    *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2277 	    NULL, node->name));
2278 	FREE_AND_NULL(str);
2279 	*msg = xmlStrcat(*msg, BAD_CAST "': ");
2280     } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2281 	xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
2282 	/*
2283 	* Work on node infos.
2284 	*/
2285 	if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
2286 	    xmlSchemaNodeInfoPtr ielem =
2287 		vctxt->elemInfos[vctxt->depth];
2288 
2289 	    *msg = xmlStrdup(BAD_CAST "Element '");
2290 	    *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2291 		ielem->nsName, ielem->localName));
2292 	    FREE_AND_NULL(str);
2293 	    *msg = xmlStrcat(*msg, BAD_CAST "', ");
2294 	    *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2295 	} else {
2296 	    *msg = xmlStrdup(BAD_CAST "Element '");
2297 	}
2298 	*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2299 	    vctxt->inode->nsName, vctxt->inode->localName));
2300 	FREE_AND_NULL(str);
2301 	*msg = xmlStrcat(*msg, BAD_CAST "': ");
2302     } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
2303 	/*
2304 	* Hmm, no node while parsing?
2305 	* Return an empty string, in case NULL will break something.
2306 	*/
2307 	*msg = xmlStrdup(BAD_CAST "");
2308     } else {
2309 	TODO
2310 	return (NULL);
2311     }
2312 
2313     /*
2314      * xmlSchemaFormatItemForReport() also returns an escaped format
2315      * string, so do this before calling it below (in the future).
2316      */
2317     xmlEscapeFormatString(msg);
2318 
2319     /*
2320     * VAL TODO: The output of the given schema component is currently
2321     * disabled.
2322     */
2323 #if 0
2324     if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
2325 	*msg = xmlStrcat(*msg, BAD_CAST " [");
2326 	*msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
2327 	    NULL, type, NULL, 0));
2328 	FREE_AND_NULL(str)
2329 	*msg = xmlStrcat(*msg, BAD_CAST "]");
2330     }
2331 #endif
2332     return (*msg);
2333 }
2334 
2335 static void LIBXML_ATTR_FORMAT(3,0)
xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,const char * funcName,const char * message,const xmlChar * str1,const xmlChar * str2)2336 xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,
2337 		     const char *funcName,
2338 		     const char *message,
2339 		     const xmlChar *str1,
2340 		     const xmlChar *str2)
2341 {
2342     xmlChar *msg = NULL;
2343 
2344     if (actxt == NULL)
2345         return;
2346     msg = xmlStrdup(BAD_CAST "Internal error: %s, ");
2347     msg = xmlStrcat(msg, BAD_CAST message);
2348     msg = xmlStrcat(msg, BAD_CAST ".\n");
2349 
2350     if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
2351 	xmlSchemaErr3(actxt, XML_SCHEMAV_INTERNAL, NULL,
2352 	    (const char *) msg, (const xmlChar *) funcName, str1, str2);
2353     else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
2354 	xmlSchemaErr3(actxt, XML_SCHEMAP_INTERNAL, NULL,
2355 	    (const char *) msg, (const xmlChar *) funcName, str1, str2);
2356 
2357     FREE_AND_NULL(msg)
2358 }
2359 
2360 static void LIBXML_ATTR_FORMAT(3,0)
xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,const char * funcName,const char * message)2361 xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
2362 		     const char *funcName,
2363 		     const char *message)
2364 {
2365     xmlSchemaInternalErr2(actxt, funcName, message, NULL, NULL);
2366 }
2367 
2368 #if 0
2369 static void LIBXML_ATTR_FORMAT(3,0)
2370 xmlSchemaPInternalErr(xmlSchemaParserCtxtPtr pctxt,
2371 		     const char *funcName,
2372 		     const char *message,
2373 		     const xmlChar *str1,
2374 		     const xmlChar *str2)
2375 {
2376     xmlSchemaInternalErr2(ACTXT_CAST pctxt, funcName, message,
2377 	str1, str2);
2378 }
2379 #endif
2380 
2381 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)2382 xmlSchemaCustomErr4(xmlSchemaAbstractCtxtPtr actxt,
2383 		   xmlParserErrors error,
2384 		   xmlNodePtr node,
2385 		   xmlSchemaBasicItemPtr item,
2386 		   const char *message,
2387 		   const xmlChar *str1, const xmlChar *str2,
2388 		   const xmlChar *str3, const xmlChar *str4)
2389 {
2390     xmlChar *msg = NULL;
2391 
2392     if ((node == NULL) && (item != NULL) &&
2393 	(actxt->type == XML_SCHEMA_CTXT_PARSER)) {
2394 	node = WXS_ITEM_NODE(item);
2395 	xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2396 	msg = xmlStrcat(msg, BAD_CAST ": ");
2397     } else
2398 	xmlSchemaFormatNodeForError(&msg, actxt, node);
2399     msg = xmlStrcat(msg, (const xmlChar *) message);
2400     msg = xmlStrcat(msg, BAD_CAST ".\n");
2401     xmlSchemaErr4(actxt, error, node,
2402 	(const char *) msg, str1, str2, str3, str4);
2403     FREE_AND_NULL(msg)
2404 }
2405 
2406 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)2407 xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
2408 		   xmlParserErrors error,
2409 		   xmlNodePtr node,
2410 		   xmlSchemaBasicItemPtr item,
2411 		   const char *message,
2412 		   const xmlChar *str1,
2413 		   const xmlChar *str2)
2414 {
2415     xmlSchemaCustomErr4(actxt, error, node, item,
2416 	message, str1, str2, NULL, NULL);
2417 }
2418 
2419 
2420 
2421 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)2422 xmlSchemaCustomWarning(xmlSchemaAbstractCtxtPtr actxt,
2423 		   xmlParserErrors error,
2424 		   xmlNodePtr node,
2425 		   xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2426 		   const char *message,
2427 		   const xmlChar *str1,
2428 		   const xmlChar *str2,
2429 		   const xmlChar *str3)
2430 {
2431     xmlChar *msg = NULL;
2432 
2433     xmlSchemaFormatNodeForError(&msg, actxt, node);
2434     msg = xmlStrcat(msg, (const xmlChar *) message);
2435     msg = xmlStrcat(msg, BAD_CAST ".\n");
2436 
2437     /* URGENT TODO: Set the error code to something sane. */
2438     xmlSchemaErr4Line(actxt, XML_ERR_WARNING, error, node, 0,
2439 	(const char *) msg, str1, str2, str3, NULL);
2440 
2441     FREE_AND_NULL(msg)
2442 }
2443 
2444 
2445 
2446 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)2447 xmlSchemaKeyrefErr(xmlSchemaValidCtxtPtr vctxt,
2448 		   xmlParserErrors error,
2449 		   xmlSchemaPSVIIDCNodePtr idcNode,
2450 		   xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2451 		   const char *message,
2452 		   const xmlChar *str1,
2453 		   const xmlChar *str2)
2454 {
2455     xmlChar *msg = NULL, *qname = NULL;
2456 
2457     msg = xmlStrdup(BAD_CAST "Element '%s': ");
2458     msg = xmlStrcat(msg, (const xmlChar *) message);
2459     msg = xmlStrcat(msg, BAD_CAST ".\n");
2460     xmlSchemaErr4Line(ACTXT_CAST vctxt, XML_ERR_ERROR,
2461 	error, NULL, idcNode->nodeLine, (const char *) msg,
2462 	xmlSchemaFormatQName(&qname,
2463 	    vctxt->nodeQNames->items[idcNode->nodeQNameID +1],
2464 	    vctxt->nodeQNames->items[idcNode->nodeQNameID]),
2465 	str1, str2, NULL);
2466     FREE_AND_NULL(qname);
2467     FREE_AND_NULL(msg);
2468 }
2469 
2470 static int
xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,xmlNodePtr node)2471 xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
2472 			   xmlNodePtr node)
2473 {
2474     if (node != NULL)
2475 	return (node->type);
2476     if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
2477 	(((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
2478 	return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
2479     return (-1);
2480 }
2481 
2482 static int
xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)2483 xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
2484 {
2485     switch (item->type) {
2486 	case XML_SCHEMA_TYPE_COMPLEX:
2487 	case XML_SCHEMA_TYPE_SIMPLE:
2488 	    if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2489 		return(1);
2490 	    break;
2491 	case XML_SCHEMA_TYPE_GROUP:
2492 	    return (1);
2493 	case XML_SCHEMA_TYPE_ELEMENT:
2494 	    if ( ((xmlSchemaElementPtr) item)->flags &
2495 		XML_SCHEMAS_ELEM_GLOBAL)
2496 		return(1);
2497 	    break;
2498 	case XML_SCHEMA_TYPE_ATTRIBUTE:
2499 	    if ( ((xmlSchemaAttributePtr) item)->flags &
2500 		XML_SCHEMAS_ATTR_GLOBAL)
2501 		return(1);
2502 	    break;
2503 	/* Note that attribute groups are always global. */
2504 	default:
2505 	    return(1);
2506     }
2507     return (0);
2508 }
2509 
2510 static void
xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,xmlParserErrors error,xmlNodePtr node,const xmlChar * value,xmlSchemaTypePtr type,int displayValue)2511 xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2512 		       xmlParserErrors error,
2513 		       xmlNodePtr node,
2514 		       const xmlChar *value,
2515 		       xmlSchemaTypePtr type,
2516 		       int displayValue)
2517 {
2518     xmlChar *msg = NULL;
2519 
2520     xmlSchemaFormatNodeForError(&msg, actxt, node);
2521 
2522     if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2523 	    XML_ATTRIBUTE_NODE))
2524 	msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2525     else
2526 	msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
2527 	    "value of ");
2528 
2529     if (! xmlSchemaIsGlobalItem(type))
2530 	msg = xmlStrcat(msg, BAD_CAST "the local ");
2531     else
2532 	msg = xmlStrcat(msg, BAD_CAST "the ");
2533 
2534     if (WXS_IS_ATOMIC(type))
2535 	msg = xmlStrcat(msg, BAD_CAST "atomic type");
2536     else if (WXS_IS_LIST(type))
2537 	msg = xmlStrcat(msg, BAD_CAST "list type");
2538     else if (WXS_IS_UNION(type))
2539 	msg = xmlStrcat(msg, BAD_CAST "union type");
2540 
2541     if (xmlSchemaIsGlobalItem(type)) {
2542 	xmlChar *str = NULL;
2543 	msg = xmlStrcat(msg, BAD_CAST " '");
2544 	if (type->builtInType != 0) {
2545 	    msg = xmlStrcat(msg, BAD_CAST "xs:");
2546 	    str = xmlStrdup(type->name);
2547 	} else {
2548 	    const xmlChar *qName = xmlSchemaFormatQName(&str, type->targetNamespace, type->name);
2549 	    if (!str)
2550 		str = xmlStrdup(qName);
2551 	}
2552 	msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
2553 	msg = xmlStrcat(msg, BAD_CAST "'");
2554 	FREE_AND_NULL(str);
2555     }
2556     msg = xmlStrcat(msg, BAD_CAST ".\n");
2557     if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2558 	    XML_ATTRIBUTE_NODE))
2559 	xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2560     else
2561 	xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2562     FREE_AND_NULL(msg)
2563 }
2564 
2565 static const xmlChar *
xmlSchemaFormatErrorNodeQName(xmlChar ** str,xmlSchemaNodeInfoPtr ni,xmlNodePtr node)2566 xmlSchemaFormatErrorNodeQName(xmlChar ** str,
2567 			      xmlSchemaNodeInfoPtr ni,
2568 			      xmlNodePtr node)
2569 {
2570     if (node != NULL) {
2571 	if (node->ns != NULL)
2572 	    return (xmlSchemaFormatQName(str, node->ns->href, node->name));
2573 	else
2574 	    return (xmlSchemaFormatQName(str, NULL, node->name));
2575     } else if (ni != NULL)
2576 	return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
2577     return (NULL);
2578 }
2579 
2580 static void
xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,xmlParserErrors error,xmlSchemaAttrInfoPtr ni,xmlNodePtr node)2581 xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
2582 			xmlParserErrors error,
2583 			xmlSchemaAttrInfoPtr ni,
2584 			xmlNodePtr node)
2585 {
2586     xmlChar *msg = NULL, *str = NULL;
2587 
2588     xmlSchemaFormatNodeForError(&msg, actxt, node);
2589     msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
2590     xmlSchemaErr(actxt, error, node, (const char *) msg,
2591 	xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
2592 	NULL);
2593     FREE_AND_NULL(str)
2594     FREE_AND_NULL(msg)
2595 }
2596 
2597 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)2598 xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2599 		        xmlParserErrors error,
2600 		        xmlNodePtr node,
2601 			xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2602 			const char *message,
2603 			int nbval,
2604 			int nbneg,
2605 			xmlChar **values)
2606 {
2607     xmlChar *str = NULL, *msg = NULL;
2608     xmlChar *localName, *nsName;
2609     const xmlChar *cur, *end;
2610     int i;
2611 
2612     xmlSchemaFormatNodeForError(&msg, actxt, node);
2613     msg = xmlStrcat(msg, (const xmlChar *) message);
2614     msg = xmlStrcat(msg, BAD_CAST ".");
2615     /*
2616     * Note that is does not make sense to report that we have a
2617     * wildcard here, since the wildcard might be unfolded into
2618     * multiple transitions.
2619     */
2620     if (nbval + nbneg > 0) {
2621 	if (nbval + nbneg > 1) {
2622 	    str = xmlStrdup(BAD_CAST " Expected is one of ( ");
2623 	} else
2624 	    str = xmlStrdup(BAD_CAST " Expected is ( ");
2625 	nsName = NULL;
2626 
2627 	for (i = 0; i < nbval + nbneg; i++) {
2628 	    cur = values[i];
2629 	    if (cur == NULL)
2630 	        continue;
2631 	    if ((cur[0] == 'n') && (cur[1] == 'o') && (cur[2] == 't') &&
2632 	        (cur[3] == ' ')) {
2633 		cur += 4;
2634 		str = xmlStrcat(str, BAD_CAST "##other");
2635 	    }
2636 	    /*
2637 	    * Get the local name.
2638 	    */
2639 	    localName = NULL;
2640 
2641 	    end = cur;
2642 	    if (*end == '*') {
2643 		localName = xmlStrdup(BAD_CAST "*");
2644 		end++;
2645 	    } else {
2646 		while ((*end != 0) && (*end != '|'))
2647 		    end++;
2648 		localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
2649 	    }
2650 	    if (*end != 0) {
2651 		end++;
2652 		/*
2653 		* Skip "*|*" if they come with negated expressions, since
2654 		* they represent the same negated wildcard.
2655 		*/
2656 		if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
2657 		    /*
2658 		    * Get the namespace name.
2659 		    */
2660 		    cur = end;
2661 		    if (*end == '*') {
2662 			nsName = xmlStrdup(BAD_CAST "{*}");
2663 		    } else {
2664 			while (*end != 0)
2665 			    end++;
2666 
2667 			if (i >= nbval)
2668 			    nsName = xmlStrdup(BAD_CAST "{##other:");
2669 			else
2670 			    nsName = xmlStrdup(BAD_CAST "{");
2671 
2672 			nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
2673 			nsName = xmlStrcat(nsName, BAD_CAST "}");
2674 		    }
2675 		    str = xmlStrcat(str, BAD_CAST nsName);
2676 		    FREE_AND_NULL(nsName)
2677 		} else {
2678 		    FREE_AND_NULL(localName);
2679 		    continue;
2680 		}
2681 	    }
2682 	    str = xmlStrcat(str, BAD_CAST localName);
2683 	    FREE_AND_NULL(localName);
2684 
2685 	    if (i < nbval + nbneg -1)
2686 		str = xmlStrcat(str, BAD_CAST ", ");
2687 	}
2688 	str = xmlStrcat(str, BAD_CAST " ).\n");
2689 	msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
2690 	FREE_AND_NULL(str)
2691     } else
2692       msg = xmlStrcat(msg, BAD_CAST "\n");
2693     xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2694     xmlFree(msg);
2695 }
2696 
2697 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)2698 xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
2699 		  xmlParserErrors error,
2700 		  xmlNodePtr node,
2701 		  const xmlChar *value,
2702 		  unsigned long length,
2703 		  xmlSchemaTypePtr type,
2704 		  xmlSchemaFacetPtr facet,
2705 		  const char *message,
2706 		  const xmlChar *str1,
2707 		  const xmlChar *str2)
2708 {
2709     xmlChar *str = NULL, *msg = NULL;
2710     xmlSchemaTypeType facetType;
2711     int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
2712 
2713     xmlSchemaFormatNodeForError(&msg, actxt, node);
2714     if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
2715 	facetType = XML_SCHEMA_FACET_ENUMERATION;
2716 	/*
2717 	* If enumerations are validated, one must not expect the
2718 	* facet to be given.
2719 	*/
2720     } else
2721 	facetType = facet->type;
2722     msg = xmlStrcat(msg, BAD_CAST "[");
2723     msg = xmlStrcat(msg, BAD_CAST "facet '");
2724     msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
2725     msg = xmlStrcat(msg, BAD_CAST "'] ");
2726     if (message == NULL) {
2727 	/*
2728 	* Use a default message.
2729 	*/
2730 	if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
2731 	    (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
2732 	    (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
2733 
2734 	    char len[25], actLen[25];
2735 
2736 	    /* FIXME, TODO: What is the max expected string length of the
2737 	    * this value?
2738 	    */
2739 	    if (nodeType == XML_ATTRIBUTE_NODE)
2740 		msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
2741 	    else
2742 		msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
2743 
2744 	    snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
2745 	    snprintf(actLen, 24, "%lu", length);
2746 
2747 	    if (facetType == XML_SCHEMA_FACET_LENGTH)
2748 		msg = xmlStrcat(msg,
2749 		BAD_CAST "this differs from the allowed length of '%s'.\n");
2750 	    else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
2751 		msg = xmlStrcat(msg,
2752 		BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2753 	    else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
2754 		msg = xmlStrcat(msg,
2755 		BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
2756 
2757 	    if (nodeType == XML_ATTRIBUTE_NODE)
2758 		xmlSchemaErr3(actxt, error, node, (const char *) msg,
2759 		    value, (const xmlChar *) actLen, (const xmlChar *) len);
2760 	    else
2761 		xmlSchemaErr(actxt, error, node, (const char *) msg,
2762 		    (const xmlChar *) actLen, (const xmlChar *) len);
2763 
2764 	} else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2765 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2766 		"of the set {%s}.\n");
2767 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2768 		xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2769 	} else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2770 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2771 		"by the pattern '%s'.\n");
2772 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2773 		facet->value);
2774 	} else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2775 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2776 		"minimum value allowed ('%s').\n");
2777 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2778 		facet->value);
2779 	} else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2780 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2781 		"maximum value allowed ('%s').\n");
2782 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2783 		facet->value);
2784 	} else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
2785 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be greater than "
2786 		"'%s'.\n");
2787 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2788 		facet->value);
2789 	} else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
2790 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
2791 		"'%s'.\n");
2792 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2793 		facet->value);
2794 	} else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2795 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2796 		"digits than are allowed ('%s').\n");
2797 	    xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2798 		facet->value);
2799 	} else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2800 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2801 		"digits than are allowed ('%s').\n");
2802 	    xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2803 		facet->value);
2804 	} else if (nodeType == XML_ATTRIBUTE_NODE) {
2805 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
2806 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2807 	} else {
2808 	    msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2809 	    xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2810 	}
2811     } else {
2812 	msg = xmlStrcat(msg, (const xmlChar *) message);
2813 	msg = xmlStrcat(msg, BAD_CAST ".\n");
2814 	xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
2815     }
2816     FREE_AND_NULL(str)
2817     xmlFree(msg);
2818 }
2819 
2820 #define VERROR(err, type, msg) \
2821     xmlSchemaCustomErr(ACTXT_CAST vctxt, err, NULL, type, msg, NULL, NULL);
2822 
2823 #define VERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST vctxt, func, msg);
2824 
2825 #define PERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST pctxt, func, msg);
2826 #define PERROR_INT2(func, msg) xmlSchemaInternalErr(ACTXT_CAST ctxt, func, msg);
2827 
2828 #define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2829 
2830 
2831 /**
2832  * xmlSchemaPMissingAttrErr:
2833  * @ctxt: the schema validation context
2834  * @ownerItem: the owner as a schema object
2835  * @ownerElem: the owner as an element node
2836  * @node: the parent element node of the missing attribute node
2837  * @type: the corresponding type of the attribute node
2838  *
2839  * Reports an illegal attribute.
2840  */
2841 static void
xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr ownerItem,xmlNodePtr ownerElem,const char * name,const char * message)2842 xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
2843 			 xmlParserErrors error,
2844 			 xmlSchemaBasicItemPtr ownerItem,
2845 			 xmlNodePtr ownerElem,
2846 			 const char *name,
2847 			 const char *message)
2848 {
2849     xmlChar *des = NULL;
2850 
2851     xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2852 
2853     if (message != NULL)
2854 	xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
2855     else
2856 	xmlSchemaPErr(ctxt, ownerElem, error,
2857 	    "%s: The attribute '%s' is required but missing.\n",
2858 	    BAD_CAST des, BAD_CAST name);
2859     FREE_AND_NULL(des);
2860 }
2861 
2862 
2863 /**
2864  * xmlSchemaPResCompAttrErr:
2865  * @ctxt: the schema validation context
2866  * @error: the error code
2867  * @ownerItem: the owner as a schema object
2868  * @ownerElem: the owner as an element node
2869  * @name: the name of the attribute holding the QName
2870  * @refName: the referenced local name
2871  * @refURI: the referenced namespace URI
2872  * @message: optional message
2873  *
2874  * Used to report QName attribute values that failed to resolve
2875  * to schema components.
2876  */
2877 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)2878 xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
2879 			 xmlParserErrors error,
2880 			 xmlSchemaBasicItemPtr ownerItem,
2881 			 xmlNodePtr ownerElem,
2882 			 const char *name,
2883 			 const xmlChar *refName,
2884 			 const xmlChar *refURI,
2885 			 xmlSchemaTypeType refType,
2886 			 const char *refTypeStr)
2887 {
2888     xmlChar *des = NULL, *strA = NULL;
2889 
2890     xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2891     if (refTypeStr == NULL)
2892 	refTypeStr = (const char *) xmlSchemaItemTypeToStr(refType);
2893     xmlSchemaPErrExt(ctxt, ownerElem, error,
2894 	    NULL, NULL, NULL,
2895 	    "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2896 	    "%s.\n", BAD_CAST des, BAD_CAST name,
2897 	    xmlSchemaFormatQName(&strA, refURI, refName),
2898 	    BAD_CAST refTypeStr, NULL);
2899     FREE_AND_NULL(des)
2900     FREE_AND_NULL(strA)
2901 }
2902 
2903 /**
2904  * xmlSchemaPCustomAttrErr:
2905  * @ctxt: the schema parser context
2906  * @error: the error code
2907  * @ownerDes: the designation of the owner
2908  * @ownerItem: the owner as a schema object
2909  * @attr: the illegal attribute node
2910  *
2911  * Reports an illegal attribute during the parse.
2912  */
2913 static void
xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlChar ** ownerDes,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,const char * msg)2914 xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
2915 			xmlParserErrors error,
2916 			xmlChar **ownerDes,
2917 			xmlSchemaBasicItemPtr ownerItem,
2918 			xmlAttrPtr attr,
2919 			const char *msg)
2920 {
2921     xmlChar *des = NULL;
2922 
2923     if (ownerDes == NULL)
2924 	xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
2925     else if (*ownerDes == NULL) {
2926 	xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
2927 	des = *ownerDes;
2928     } else
2929 	des = *ownerDes;
2930     if (attr == NULL) {
2931 	xmlSchemaPErrExt(ctxt, NULL, error, NULL, NULL, NULL,
2932 	    "%s, attribute '%s': %s.\n",
2933 	    BAD_CAST des, (const xmlChar *) "Unknown",
2934 	    (const xmlChar *) msg, NULL, NULL);
2935     } else {
2936 	xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
2937 	    "%s, attribute '%s': %s.\n",
2938 	    BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2939     }
2940     if (ownerDes == NULL)
2941 	FREE_AND_NULL(des);
2942 }
2943 
2944 /**
2945  * xmlSchemaPIllegalAttrErr:
2946  * @ctxt: the schema parser context
2947  * @error: the error code
2948  * @ownerItem: the attribute's owner item
2949  * @attr: the illegal attribute node
2950  *
2951  * Reports an illegal attribute during the parse.
2952  */
2953 static void
xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr ownerComp ATTRIBUTE_UNUSED,xmlAttrPtr attr)2954 xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
2955 			 xmlParserErrors error,
2956 			 xmlSchemaBasicItemPtr ownerComp ATTRIBUTE_UNUSED,
2957 			 xmlAttrPtr attr)
2958 {
2959     xmlChar *strA = NULL, *strB = NULL;
2960 
2961     xmlSchemaFormatNodeForError(&strA, ACTXT_CAST ctxt, attr->parent);
2962     xmlSchemaErr4(ACTXT_CAST ctxt, error, (xmlNodePtr) attr,
2963 	"%sThe attribute '%s' is not allowed.\n", BAD_CAST strA,
2964 	xmlSchemaFormatQNameNs(&strB, attr->ns, attr->name),
2965 	NULL, NULL);
2966     FREE_AND_NULL(strA);
2967     FREE_AND_NULL(strB);
2968 }
2969 
2970 /**
2971  * xmlSchemaPCustomErr:
2972  * @ctxt: the schema parser context
2973  * @error: the error code
2974  * @itemDes: the designation of the schema item
2975  * @item: the schema item
2976  * @itemElem: the node of the schema item
2977  * @message: the error message
2978  * @str1: an optional param for the error message
2979  * @str2: an optional param for the error message
2980  * @str3: an optional param for the error message
2981  *
2982  * Reports an error during parsing.
2983  */
2984 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)2985 xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
2986 		    xmlParserErrors error,
2987 		    xmlSchemaBasicItemPtr item,
2988 		    xmlNodePtr itemElem,
2989 		    const char *message,
2990 		    const xmlChar *str1,
2991 		    const xmlChar *str2,
2992 		    const xmlChar *str3)
2993 {
2994     xmlChar *des = NULL, *msg = NULL;
2995 
2996     xmlSchemaFormatItemForReport(&des, NULL, item, itemElem);
2997     msg = xmlStrdup(BAD_CAST "%s: ");
2998     msg = xmlStrcat(msg, (const xmlChar *) message);
2999     msg = xmlStrcat(msg, BAD_CAST ".\n");
3000     if ((itemElem == NULL) && (item != NULL))
3001 	itemElem = WXS_ITEM_NODE(item);
3002     xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
3003 	(const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
3004     FREE_AND_NULL(des);
3005     FREE_AND_NULL(msg);
3006 }
3007 
3008 /**
3009  * xmlSchemaPCustomErr:
3010  * @ctxt: the schema parser context
3011  * @error: the error code
3012  * @itemDes: the designation of the schema item
3013  * @item: the schema item
3014  * @itemElem: the node of the schema item
3015  * @message: the error message
3016  * @str1: the optional param for the error message
3017  *
3018  * Reports an error during parsing.
3019  */
3020 static void LIBXML_ATTR_FORMAT(5,0)
xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr item,xmlNodePtr itemElem,const char * message,const xmlChar * str1)3021 xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
3022 		    xmlParserErrors error,
3023 		    xmlSchemaBasicItemPtr item,
3024 		    xmlNodePtr itemElem,
3025 		    const char *message,
3026 		    const xmlChar *str1)
3027 {
3028     xmlSchemaPCustomErrExt(ctxt, error, item, itemElem, message,
3029 	str1, NULL, NULL);
3030 }
3031 
3032 /**
3033  * xmlSchemaPAttrUseErr:
3034  * @ctxt: the schema parser context
3035  * @error: the error code
3036  * @itemDes: the designation of the schema type
3037  * @item: the schema type
3038  * @itemElem: the node of the schema type
3039  * @attr: the invalid schema attribute
3040  * @message: the error message
3041  * @str1: the optional param for the error message
3042  *
3043  * Reports an attribute use error during parsing.
3044  */
3045 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)3046 xmlSchemaPAttrUseErr4(xmlSchemaParserCtxtPtr ctxt,
3047 		    xmlParserErrors error,
3048 		    xmlNodePtr node,
3049 		    xmlSchemaBasicItemPtr ownerItem,
3050 		    const xmlSchemaAttributeUsePtr attruse,
3051 		    const char *message,
3052 		    const xmlChar *str1, const xmlChar *str2,
3053 		    const xmlChar *str3,const xmlChar *str4)
3054 {
3055     xmlChar *str = NULL, *msg = NULL;
3056 
3057     xmlSchemaFormatItemForReport(&msg, NULL, ownerItem, NULL);
3058     msg = xmlStrcat(msg, BAD_CAST ", ");
3059     msg = xmlStrcat(msg,
3060 	BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
3061 	WXS_BASIC_CAST attruse, NULL));
3062     FREE_AND_NULL(str);
3063     msg = xmlStrcat(msg, BAD_CAST ": ");
3064     msg = xmlStrcat(msg, (const xmlChar *) message);
3065     msg = xmlStrcat(msg, BAD_CAST ".\n");
3066     xmlSchemaErr4(ACTXT_CAST ctxt, error, node,
3067 	(const char *) msg, str1, str2, str3, str4);
3068     xmlFree(msg);
3069 }
3070 
3071 /**
3072  * xmlSchemaPIllegalFacetAtomicErr:
3073  * @ctxt: the schema parser context
3074  * @error: the error code
3075  * @type: the schema type
3076  * @baseType: the base type of type
3077  * @facet: the illegal facet
3078  *
3079  * Reports an illegal facet for atomic simple types.
3080  */
3081 static void
xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaTypePtr type,xmlSchemaTypePtr baseType,xmlSchemaFacetPtr facet)3082 xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
3083 			  xmlParserErrors error,
3084 			  xmlSchemaTypePtr type,
3085 			  xmlSchemaTypePtr baseType,
3086 			  xmlSchemaFacetPtr facet)
3087 {
3088     xmlChar *des = NULL, *strT = NULL;
3089 
3090     xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type, type->node);
3091     xmlSchemaPErrExt(ctxt, type->node, error, NULL, NULL, NULL,
3092 	"%s: The facet '%s' is not allowed on types derived from the "
3093 	"type %s.\n",
3094 	BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
3095 	xmlSchemaFormatItemForReport(&strT, NULL, WXS_BASIC_CAST baseType, NULL),
3096 	NULL, NULL);
3097     FREE_AND_NULL(des);
3098     FREE_AND_NULL(strT);
3099 }
3100 
3101 /**
3102  * xmlSchemaPIllegalFacetListUnionErr:
3103  * @ctxt: the schema parser context
3104  * @error: the error code
3105  * @itemDes: the designation of the schema item involved
3106  * @item: the schema item involved
3107  * @facet: the illegal facet
3108  *
3109  * Reports an illegal facet for <list> and <union>.
3110  */
3111 static void
xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaTypePtr type,xmlSchemaFacetPtr facet)3112 xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
3113 			  xmlParserErrors error,
3114 			  xmlSchemaTypePtr type,
3115 			  xmlSchemaFacetPtr facet)
3116 {
3117     xmlChar *des = NULL;
3118 
3119     xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type,
3120 	type->node);
3121     xmlSchemaPErr(ctxt, type->node, error,
3122 	"%s: The facet '%s' is not allowed.\n",
3123 	BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
3124     FREE_AND_NULL(des);
3125 }
3126 
3127 /**
3128  * xmlSchemaPMutualExclAttrErr:
3129  * @ctxt: the schema validation context
3130  * @error: the error code
3131  * @elemDes: the designation of the parent element node
3132  * @attr: the bad attribute node
3133  * @type: the corresponding type of the attribute node
3134  *
3135  * Reports an illegal attribute.
3136  */
3137 static void
xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,const char * name1,const char * name2)3138 xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
3139 			 xmlParserErrors error,
3140 			 xmlSchemaBasicItemPtr ownerItem,
3141 			 xmlAttrPtr attr,
3142 			 const char *name1,
3143 			 const char *name2)
3144 {
3145     xmlChar *des = NULL;
3146 
3147     xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST ownerItem, attr->parent);
3148     xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
3149 	"%s: The attributes '%s' and '%s' are mutually exclusive.\n",
3150 	BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
3151     FREE_AND_NULL(des);
3152 }
3153 
3154 /**
3155  * xmlSchemaPSimpleTypeErr:
3156  * @ctxt:  the schema validation context
3157  * @error: the error code
3158  * @type: the type specifier
3159  * @ownerItem: the schema object if existent
3160  * @node: the validated node
3161  * @value: the validated value
3162  *
3163  * Reports a simple type validation error.
3164  * TODO: Should this report the value of an element as well?
3165  */
3166 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)3167 xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
3168 			xmlParserErrors error,
3169 			xmlSchemaBasicItemPtr ownerItem ATTRIBUTE_UNUSED,
3170 			xmlNodePtr node,
3171 			xmlSchemaTypePtr type,
3172 			const char *expected,
3173 			const xmlChar *value,
3174 			const char *message,
3175 			const xmlChar *str1,
3176 			const xmlChar *str2)
3177 {
3178     xmlChar *msg = NULL;
3179 
3180     xmlSchemaFormatNodeForError(&msg, ACTXT_CAST ctxt, node);
3181     if (message == NULL) {
3182 	/*
3183 	* Use default messages.
3184 	*/
3185 	if (type != NULL) {
3186 	    if (node->type == XML_ATTRIBUTE_NODE)
3187 		msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
3188 	    else
3189 		msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
3190 		"valid value of ");
3191 	    if (! xmlSchemaIsGlobalItem(type))
3192 		msg = xmlStrcat(msg, BAD_CAST "the local ");
3193 	    else
3194 		msg = xmlStrcat(msg, BAD_CAST "the ");
3195 
3196 	    if (WXS_IS_ATOMIC(type))
3197 		msg = xmlStrcat(msg, BAD_CAST "atomic type");
3198 	    else if (WXS_IS_LIST(type))
3199 		msg = xmlStrcat(msg, BAD_CAST "list type");
3200 	    else if (WXS_IS_UNION(type))
3201 		msg = xmlStrcat(msg, BAD_CAST "union type");
3202 
3203 	    if (xmlSchemaIsGlobalItem(type)) {
3204 		xmlChar *str = NULL;
3205 		msg = xmlStrcat(msg, BAD_CAST " '");
3206 		if (type->builtInType != 0) {
3207 		    msg = xmlStrcat(msg, BAD_CAST "xs:");
3208 		    str = xmlStrdup(type->name);
3209 		} else {
3210 		    const xmlChar *qName = xmlSchemaFormatQName(&str, type->targetNamespace, type->name);
3211 		    if (!str)
3212 			str = xmlStrdup(qName);
3213 		}
3214 		msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
3215 		msg = xmlStrcat(msg, BAD_CAST "'.");
3216 		FREE_AND_NULL(str);
3217 	    }
3218 	} else {
3219 	    if (node->type == XML_ATTRIBUTE_NODE)
3220 		msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
3221 	    else
3222 		msg = xmlStrcat(msg, BAD_CAST "The character content is not "
3223 		"valid.");
3224 	}
3225 	if (expected) {
3226 	    xmlChar *expectedEscaped = xmlCharStrdup(expected);
3227 	    msg = xmlStrcat(msg, BAD_CAST " Expected is '");
3228 	    msg = xmlStrcat(msg, xmlEscapeFormatString(&expectedEscaped));
3229 	    FREE_AND_NULL(expectedEscaped);
3230 	    msg = xmlStrcat(msg, BAD_CAST "'.\n");
3231 	} else
3232 	    msg = xmlStrcat(msg, BAD_CAST "\n");
3233 	if (node->type == XML_ATTRIBUTE_NODE)
3234 	    xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
3235 	else
3236 	    xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
3237     } else {
3238 	msg = xmlStrcat(msg, BAD_CAST message);
3239 	msg = xmlStrcat(msg, BAD_CAST ".\n");
3240 	xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
3241 	     (const char*) msg, str1, str2, NULL, NULL, NULL);
3242     }
3243     /* Cleanup. */
3244     FREE_AND_NULL(msg)
3245 }
3246 
3247 /**
3248  * xmlSchemaPContentErr:
3249  * @ctxt: the schema parser context
3250  * @error: the error code
3251  * @ownerItem: the owner item of the holder of the content
3252  * @ownerElem: the node of the holder of the content
3253  * @child: the invalid child node
3254  * @message: the optional error message
3255  * @content: the optional string describing the correct content
3256  *
3257  * Reports an error concerning the content of a schema element.
3258  */
3259 static void
xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr ownerItem,xmlNodePtr ownerElem,xmlNodePtr child,const char * message,const char * content)3260 xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
3261 		     xmlParserErrors error,
3262 		     xmlSchemaBasicItemPtr ownerItem,
3263 		     xmlNodePtr ownerElem,
3264 		     xmlNodePtr child,
3265 		     const char *message,
3266 		     const char *content)
3267 {
3268     xmlChar *des = NULL;
3269 
3270     xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
3271     if (message != NULL)
3272 	xmlSchemaPErr2(ctxt, ownerElem, child, error,
3273 	    "%s: %s.\n",
3274 	    BAD_CAST des, BAD_CAST message);
3275     else {
3276 	if (content != NULL) {
3277 	    xmlSchemaPErr2(ctxt, ownerElem, child, error,
3278 		"%s: The content is not valid. Expected is %s.\n",
3279 		BAD_CAST des, BAD_CAST content);
3280 	} else {
3281 	    xmlSchemaPErr2(ctxt, ownerElem, child, error,
3282 		"%s: The content is not valid.\n",
3283 		BAD_CAST des, NULL);
3284 	}
3285     }
3286     FREE_AND_NULL(des)
3287 }
3288 
3289 /************************************************************************
3290  *									*
3291  *			Streamable error functions                      *
3292  *									*
3293  ************************************************************************/
3294 
3295 
3296 
3297 
3298 /************************************************************************
3299  *									*
3300  *			Validation helper functions			*
3301  *									*
3302  ************************************************************************/
3303 
3304 
3305 /************************************************************************
3306  *									*
3307  *			Allocation functions				*
3308  *									*
3309  ************************************************************************/
3310 
3311 /**
3312  * xmlSchemaNewSchemaForParserCtxt:
3313  * @ctxt:  a schema validation context
3314  *
3315  * Allocate a new Schema structure.
3316  *
3317  * Returns the newly allocated structure or NULL in case or error
3318  */
3319 static xmlSchemaPtr
xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)3320 xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
3321 {
3322     xmlSchemaPtr ret;
3323 
3324     ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
3325     if (ret == NULL) {
3326         xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
3327         return (NULL);
3328     }
3329     memset(ret, 0, sizeof(xmlSchema));
3330     ret->dict = ctxt->dict;
3331     xmlDictReference(ret->dict);
3332 
3333     return (ret);
3334 }
3335 
3336 /**
3337  * xmlSchemaNewFacet:
3338  *
3339  * Allocate a new Facet structure.
3340  *
3341  * Returns the newly allocated structure or NULL in case or error
3342  */
3343 xmlSchemaFacetPtr
xmlSchemaNewFacet(void)3344 xmlSchemaNewFacet(void)
3345 {
3346     xmlSchemaFacetPtr ret;
3347 
3348     ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
3349     if (ret == NULL) {
3350         return (NULL);
3351     }
3352     memset(ret, 0, sizeof(xmlSchemaFacet));
3353 
3354     return (ret);
3355 }
3356 
3357 /**
3358  * xmlSchemaNewAnnot:
3359  * @ctxt:  a schema validation context
3360  * @node:  a node
3361  *
3362  * Allocate a new annotation structure.
3363  *
3364  * Returns the newly allocated structure or NULL in case or error
3365  */
3366 static xmlSchemaAnnotPtr
xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node)3367 xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3368 {
3369     xmlSchemaAnnotPtr ret;
3370 
3371     ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
3372     if (ret == NULL) {
3373         xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
3374         return (NULL);
3375     }
3376     memset(ret, 0, sizeof(xmlSchemaAnnot));
3377     ret->content = node;
3378     return (ret);
3379 }
3380 
3381 static xmlSchemaItemListPtr
xmlSchemaItemListCreate(void)3382 xmlSchemaItemListCreate(void)
3383 {
3384     xmlSchemaItemListPtr ret;
3385 
3386     ret = xmlMalloc(sizeof(xmlSchemaItemList));
3387     if (ret == NULL) {
3388 	xmlSchemaPErrMemory(NULL,
3389 	    "allocating an item list structure", NULL);
3390 	return (NULL);
3391     }
3392     memset(ret, 0, sizeof(xmlSchemaItemList));
3393     return (ret);
3394 }
3395 
3396 static void
xmlSchemaItemListClear(xmlSchemaItemListPtr list)3397 xmlSchemaItemListClear(xmlSchemaItemListPtr list)
3398 {
3399     if (list->items != NULL) {
3400 	xmlFree(list->items);
3401 	list->items = NULL;
3402     }
3403     list->nbItems = 0;
3404     list->sizeItems = 0;
3405 }
3406 
3407 static int
xmlSchemaItemListAdd(xmlSchemaItemListPtr list,void * item)3408 xmlSchemaItemListAdd(xmlSchemaItemListPtr list, void *item)
3409 {
3410     if (list->items == NULL) {
3411 	list->items = (void **) xmlMalloc(
3412 	    20 * sizeof(void *));
3413 	if (list->items == NULL) {
3414 	    xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3415 	    return(-1);
3416 	}
3417 	list->sizeItems = 20;
3418     } else if (list->sizeItems <= list->nbItems) {
3419 	list->sizeItems *= 2;
3420 	list->items = (void **) xmlRealloc(list->items,
3421 	    list->sizeItems * sizeof(void *));
3422 	if (list->items == NULL) {
3423 	    xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3424 	    list->sizeItems = 0;
3425 	    return(-1);
3426 	}
3427     }
3428     list->items[list->nbItems++] = item;
3429     return(0);
3430 }
3431 
3432 static int
xmlSchemaItemListAddSize(xmlSchemaItemListPtr list,int initialSize,void * item)3433 xmlSchemaItemListAddSize(xmlSchemaItemListPtr list,
3434 			 int initialSize,
3435 			 void *item)
3436 {
3437     if (list->items == NULL) {
3438 	if (initialSize <= 0)
3439 	    initialSize = 1;
3440 	list->items = (void **) xmlMalloc(
3441 	    initialSize * sizeof(void *));
3442 	if (list->items == NULL) {
3443 	    xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3444 	    return(-1);
3445 	}
3446 	list->sizeItems = initialSize;
3447     } else if (list->sizeItems <= list->nbItems) {
3448 	list->sizeItems *= 2;
3449 	list->items = (void **) xmlRealloc(list->items,
3450 	    list->sizeItems * sizeof(void *));
3451 	if (list->items == NULL) {
3452 	    xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3453 	    list->sizeItems = 0;
3454 	    return(-1);
3455 	}
3456     }
3457     list->items[list->nbItems++] = item;
3458     return(0);
3459 }
3460 
3461 static int
xmlSchemaItemListInsert(xmlSchemaItemListPtr list,void * item,int idx)3462 xmlSchemaItemListInsert(xmlSchemaItemListPtr list, void *item, int idx)
3463 {
3464     if (list->items == NULL) {
3465 	list->items = (void **) xmlMalloc(
3466 	    20 * sizeof(void *));
3467 	if (list->items == NULL) {
3468 	    xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3469 	    return(-1);
3470 	}
3471 	list->sizeItems = 20;
3472     } else if (list->sizeItems <= list->nbItems) {
3473 	list->sizeItems *= 2;
3474 	list->items = (void **) xmlRealloc(list->items,
3475 	    list->sizeItems * sizeof(void *));
3476 	if (list->items == NULL) {
3477 	    xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3478 	    list->sizeItems = 0;
3479 	    return(-1);
3480 	}
3481     }
3482     /*
3483     * Just append if the index is greater/equal than the item count.
3484     */
3485     if (idx >= list->nbItems) {
3486 	list->items[list->nbItems++] = item;
3487     } else {
3488 	int i;
3489 	for (i = list->nbItems; i > idx; i--)
3490 	    list->items[i] = list->items[i-1];
3491 	list->items[idx] = item;
3492 	list->nbItems++;
3493     }
3494     return(0);
3495 }
3496 
3497 #if 0 /* enable if ever needed */
3498 static int
3499 xmlSchemaItemListInsertSize(xmlSchemaItemListPtr list,
3500 			    int initialSize,
3501 			    void *item,
3502 			    int idx)
3503 {
3504     if (list->items == NULL) {
3505 	if (initialSize <= 0)
3506 	    initialSize = 1;
3507 	list->items = (void **) xmlMalloc(
3508 	    initialSize * sizeof(void *));
3509 	if (list->items == NULL) {
3510 	    xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3511 	    return(-1);
3512 	}
3513 	list->sizeItems = initialSize;
3514     } else if (list->sizeItems <= list->nbItems) {
3515 	list->sizeItems *= 2;
3516 	list->items = (void **) xmlRealloc(list->items,
3517 	    list->sizeItems * sizeof(void *));
3518 	if (list->items == NULL) {
3519 	    xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3520 	    list->sizeItems = 0;
3521 	    return(-1);
3522 	}
3523     }
3524     /*
3525     * Just append if the index is greater/equal than the item count.
3526     */
3527     if (idx >= list->nbItems) {
3528 	list->items[list->nbItems++] = item;
3529     } else {
3530 	int i;
3531 	for (i = list->nbItems; i > idx; i--)
3532 	    list->items[i] = list->items[i-1];
3533 	list->items[idx] = item;
3534 	list->nbItems++;
3535     }
3536     return(0);
3537 }
3538 #endif
3539 
3540 static int
xmlSchemaItemListRemove(xmlSchemaItemListPtr list,int idx)3541 xmlSchemaItemListRemove(xmlSchemaItemListPtr list, int idx)
3542 {
3543     int i;
3544     if ((list->items == NULL) || (idx >= list->nbItems)) {
3545 	xmlSchemaPSimpleErr("Internal error: xmlSchemaItemListRemove, "
3546 	    "index error.\n");
3547 	return(-1);
3548     }
3549 
3550     if (list->nbItems == 1) {
3551 	/* TODO: Really free the list? */
3552 	xmlFree(list->items);
3553 	list->items = NULL;
3554 	list->nbItems = 0;
3555 	list->sizeItems = 0;
3556     } else if (list->nbItems -1 == idx) {
3557 	list->nbItems--;
3558     } else {
3559 	for (i = idx; i < list->nbItems -1; i++)
3560 	    list->items[i] = list->items[i+1];
3561 	list->nbItems--;
3562     }
3563     return(0);
3564 }
3565 
3566 /**
3567  * xmlSchemaItemListFree:
3568  * @annot:  a schema type structure
3569  *
3570  * Deallocate a annotation structure
3571  */
3572 static void
xmlSchemaItemListFree(xmlSchemaItemListPtr list)3573 xmlSchemaItemListFree(xmlSchemaItemListPtr list)
3574 {
3575     if (list == NULL)
3576 	return;
3577     if (list->items != NULL)
3578 	xmlFree(list->items);
3579     xmlFree(list);
3580 }
3581 
3582 static void
xmlSchemaBucketFree(xmlSchemaBucketPtr bucket)3583 xmlSchemaBucketFree(xmlSchemaBucketPtr bucket)
3584 {
3585     if (bucket == NULL)
3586 	return;
3587     if (bucket->globals != NULL) {
3588 	xmlSchemaComponentListFree(bucket->globals);
3589 	xmlSchemaItemListFree(bucket->globals);
3590     }
3591     if (bucket->locals != NULL) {
3592 	xmlSchemaComponentListFree(bucket->locals);
3593 	xmlSchemaItemListFree(bucket->locals);
3594     }
3595     if (bucket->relations != NULL) {
3596 	xmlSchemaSchemaRelationPtr prev, cur = bucket->relations;
3597 	do {
3598 	    prev = cur;
3599 	    cur = cur->next;
3600 	    xmlFree(prev);
3601 	} while (cur != NULL);
3602     }
3603     if ((! bucket->preserveDoc) && (bucket->doc != NULL)) {
3604 	xmlFreeDoc(bucket->doc);
3605     }
3606     if (bucket->type == XML_SCHEMA_SCHEMA_IMPORT) {
3607 	if (WXS_IMPBUCKET(bucket)->schema != NULL)
3608 	    xmlSchemaFree(WXS_IMPBUCKET(bucket)->schema);
3609     }
3610     xmlFree(bucket);
3611 }
3612 
3613 static void
xmlSchemaBucketFreeEntry(void * bucket,const xmlChar * name ATTRIBUTE_UNUSED)3614 xmlSchemaBucketFreeEntry(void *bucket, const xmlChar *name ATTRIBUTE_UNUSED)
3615 {
3616     xmlSchemaBucketFree((xmlSchemaBucketPtr) bucket);
3617 }
3618 
3619 static xmlSchemaBucketPtr
xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,int type,const xmlChar * targetNamespace)3620 xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,
3621 			 int type, const xmlChar *targetNamespace)
3622 {
3623     xmlSchemaBucketPtr ret;
3624     int size;
3625     xmlSchemaPtr mainSchema;
3626 
3627     if (WXS_CONSTRUCTOR(pctxt)->mainSchema == NULL) {
3628 	PERROR_INT("xmlSchemaBucketCreate",
3629 	    "no main schema on constructor");
3630 	return(NULL);
3631     }
3632     mainSchema = WXS_CONSTRUCTOR(pctxt)->mainSchema;
3633     /* Create the schema bucket. */
3634     if (WXS_IS_BUCKET_INCREDEF(type))
3635 	size = sizeof(xmlSchemaInclude);
3636     else
3637 	size = sizeof(xmlSchemaImport);
3638     ret = (xmlSchemaBucketPtr) xmlMalloc(size);
3639     if (ret == NULL) {
3640 	xmlSchemaPErrMemory(NULL, "allocating schema bucket", NULL);
3641 	return(NULL);
3642     }
3643     memset(ret, 0, size);
3644     ret->targetNamespace = targetNamespace;
3645     ret->type = type;
3646     ret->globals = xmlSchemaItemListCreate();
3647     if (ret->globals == NULL) {
3648 	xmlFree(ret);
3649 	return(NULL);
3650     }
3651     ret->locals = xmlSchemaItemListCreate();
3652     if (ret->locals == NULL) {
3653 	xmlFree(ret);
3654 	return(NULL);
3655     }
3656     /*
3657     * The following will assure that only the first bucket is marked as
3658     * XML_SCHEMA_SCHEMA_MAIN and it points to the *main* schema.
3659     * For each following import buckets an xmlSchema will be created.
3660     * An xmlSchema will be created for every distinct targetNamespace.
3661     * We assign the targetNamespace to the schemata here.
3662     */
3663     if (! WXS_HAS_BUCKETS(pctxt)) {
3664 	if (WXS_IS_BUCKET_INCREDEF(type)) {
3665 	    PERROR_INT("xmlSchemaBucketCreate",
3666 		"first bucket but it's an include or redefine");
3667 	    xmlSchemaBucketFree(ret);
3668 	    return(NULL);
3669 	}
3670 	/* Force the type to be XML_SCHEMA_SCHEMA_MAIN. */
3671 	ret->type = XML_SCHEMA_SCHEMA_MAIN;
3672 	/* Point to the *main* schema. */
3673 	WXS_CONSTRUCTOR(pctxt)->mainBucket = ret;
3674 	WXS_IMPBUCKET(ret)->schema = mainSchema;
3675 	/*
3676 	* Ensure that the main schema gets a targetNamespace.
3677 	*/
3678 	mainSchema->targetNamespace = targetNamespace;
3679     } else {
3680 	if (type == XML_SCHEMA_SCHEMA_MAIN) {
3681 	    PERROR_INT("xmlSchemaBucketCreate",
3682 		"main bucket but it's not the first one");
3683 	    xmlSchemaBucketFree(ret);
3684 	    return(NULL);
3685 	} else if (type == XML_SCHEMA_SCHEMA_IMPORT) {
3686 	    /*
3687 	    * Create a schema for imports and assign the
3688 	    * targetNamespace.
3689 	    */
3690 	    WXS_IMPBUCKET(ret)->schema = xmlSchemaNewSchema(pctxt);
3691 	    if (WXS_IMPBUCKET(ret)->schema == NULL) {
3692 		xmlSchemaBucketFree(ret);
3693 		return(NULL);
3694 	    }
3695 	    WXS_IMPBUCKET(ret)->schema->targetNamespace = targetNamespace;
3696 	}
3697     }
3698     if (WXS_IS_BUCKET_IMPMAIN(type)) {
3699 	int res;
3700 	/*
3701 	* Imports go into the "schemasImports" slot of the main *schema*.
3702 	* Note that we create an import entry for the main schema as well; i.e.,
3703 	* even if there's only one schema, we'll get an import.
3704 	*/
3705 	if (mainSchema->schemasImports == NULL) {
3706 	    mainSchema->schemasImports = xmlHashCreateDict(5,
3707 		WXS_CONSTRUCTOR(pctxt)->dict);
3708 	    if (mainSchema->schemasImports == NULL) {
3709 		xmlSchemaBucketFree(ret);
3710 		return(NULL);
3711 	    }
3712 	}
3713 	if (targetNamespace == NULL)
3714 	    res = xmlHashAddEntry(mainSchema->schemasImports,
3715 		XML_SCHEMAS_NO_NAMESPACE, ret);
3716 	else
3717 	    res = xmlHashAddEntry(mainSchema->schemasImports,
3718 		targetNamespace, ret);
3719 	if (res != 0) {
3720 	    PERROR_INT("xmlSchemaBucketCreate",
3721 		"failed to add the schema bucket to the hash");
3722 	    xmlSchemaBucketFree(ret);
3723 	    return(NULL);
3724 	}
3725     } else {
3726 	/* Set the @ownerImport of an include bucket. */
3727 	if (WXS_IS_BUCKET_IMPMAIN(WXS_CONSTRUCTOR(pctxt)->bucket->type))
3728 	    WXS_INCBUCKET(ret)->ownerImport =
3729 		WXS_IMPBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket);
3730 	else
3731 	    WXS_INCBUCKET(ret)->ownerImport =
3732 		WXS_INCBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket)->ownerImport;
3733 
3734 	/* Includes got into the "includes" slot of the *main* schema. */
3735 	if (mainSchema->includes == NULL) {
3736 	    mainSchema->includes = xmlSchemaItemListCreate();
3737 	    if (mainSchema->includes == NULL) {
3738 		xmlSchemaBucketFree(ret);
3739 		return(NULL);
3740 	    }
3741 	}
3742 	xmlSchemaItemListAdd(mainSchema->includes, ret);
3743     }
3744     /*
3745     * Add to list of all buckets; this is used for lookup
3746     * during schema construction time only.
3747     */
3748     if (xmlSchemaItemListAdd(WXS_CONSTRUCTOR(pctxt)->buckets, ret) == -1)
3749 	return(NULL);
3750     return(ret);
3751 }
3752 
3753 static int
xmlSchemaAddItemSize(xmlSchemaItemListPtr * list,int initialSize,void * item)3754 xmlSchemaAddItemSize(xmlSchemaItemListPtr *list, int initialSize, void *item)
3755 {
3756     if (*list == NULL) {
3757 	*list = xmlSchemaItemListCreate();
3758 	if (*list == NULL)
3759 	    return(-1);
3760     }
3761     xmlSchemaItemListAddSize(*list, initialSize, item);
3762     return(0);
3763 }
3764 
3765 /**
3766  * xmlSchemaFreeAnnot:
3767  * @annot:  a schema type structure
3768  *
3769  * Deallocate a annotation structure
3770  */
3771 static void
xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)3772 xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
3773 {
3774     if (annot == NULL)
3775         return;
3776     if (annot->next == NULL) {
3777 	xmlFree(annot);
3778     } else {
3779 	xmlSchemaAnnotPtr prev;
3780 
3781 	do {
3782 	    prev = annot;
3783 	    annot = annot->next;
3784 	    xmlFree(prev);
3785 	} while (annot != NULL);
3786     }
3787 }
3788 
3789 /**
3790  * xmlSchemaFreeNotation:
3791  * @schema:  a schema notation structure
3792  *
3793  * Deallocate a Schema Notation structure.
3794  */
3795 static void
xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)3796 xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
3797 {
3798     if (nota == NULL)
3799         return;
3800     xmlFree(nota);
3801 }
3802 
3803 /**
3804  * xmlSchemaFreeAttribute:
3805  * @attr:  an attribute declaration
3806  *
3807  * Deallocates an attribute declaration structure.
3808  */
3809 static void
xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)3810 xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
3811 {
3812     if (attr == NULL)
3813         return;
3814     if (attr->annot != NULL)
3815 	xmlSchemaFreeAnnot(attr->annot);
3816     if (attr->defVal != NULL)
3817 	xmlSchemaFreeValue(attr->defVal);
3818     xmlFree(attr);
3819 }
3820 
3821 /**
3822  * xmlSchemaFreeAttributeUse:
3823  * @use:  an attribute use
3824  *
3825  * Deallocates an attribute use structure.
3826  */
3827 static void
xmlSchemaFreeAttributeUse(xmlSchemaAttributeUsePtr use)3828 xmlSchemaFreeAttributeUse(xmlSchemaAttributeUsePtr use)
3829 {
3830     if (use == NULL)
3831         return;
3832     if (use->annot != NULL)
3833 	xmlSchemaFreeAnnot(use->annot);
3834     if (use->defVal != NULL)
3835 	xmlSchemaFreeValue(use->defVal);
3836     xmlFree(use);
3837 }
3838 
3839 /**
3840  * xmlSchemaFreeAttributeUseProhib:
3841  * @prohib:  an attribute use prohibition
3842  *
3843  * Deallocates an attribute use structure.
3844  */
3845 static void
xmlSchemaFreeAttributeUseProhib(xmlSchemaAttributeUseProhibPtr prohib)3846 xmlSchemaFreeAttributeUseProhib(xmlSchemaAttributeUseProhibPtr prohib)
3847 {
3848     if (prohib == NULL)
3849         return;
3850     xmlFree(prohib);
3851 }
3852 
3853 /**
3854  * xmlSchemaFreeWildcardNsSet:
3855  * set:  a schema wildcard namespace
3856  *
3857  * Deallocates a list of wildcard constraint structures.
3858  */
3859 static void
xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)3860 xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
3861 {
3862     xmlSchemaWildcardNsPtr next;
3863 
3864     while (set != NULL) {
3865 	next = set->next;
3866 	xmlFree(set);
3867 	set = next;
3868     }
3869 }
3870 
3871 /**
3872  * xmlSchemaFreeWildcard:
3873  * @wildcard:  a wildcard structure
3874  *
3875  * Deallocates a wildcard structure.
3876  */
3877 void
xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)3878 xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
3879 {
3880     if (wildcard == NULL)
3881         return;
3882     if (wildcard->annot != NULL)
3883         xmlSchemaFreeAnnot(wildcard->annot);
3884     if (wildcard->nsSet != NULL)
3885 	xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
3886     if (wildcard->negNsSet != NULL)
3887 	xmlFree(wildcard->negNsSet);
3888     xmlFree(wildcard);
3889 }
3890 
3891 /**
3892  * xmlSchemaFreeAttributeGroup:
3893  * @schema:  a schema attribute group structure
3894  *
3895  * Deallocate a Schema Attribute Group structure.
3896  */
3897 static void
xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attrGr)3898 xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attrGr)
3899 {
3900     if (attrGr == NULL)
3901         return;
3902     if (attrGr->annot != NULL)
3903         xmlSchemaFreeAnnot(attrGr->annot);
3904     if (attrGr->attrUses != NULL)
3905 	xmlSchemaItemListFree(WXS_LIST_CAST attrGr->attrUses);
3906     xmlFree(attrGr);
3907 }
3908 
3909 /**
3910  * xmlSchemaFreeQNameRef:
3911  * @item: a QName reference structure
3912  *
3913  * Deallocatea a QName reference structure.
3914  */
3915 static void
xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)3916 xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3917 {
3918     xmlFree(item);
3919 }
3920 
3921 /**
3922  * xmlSchemaFreeTypeLinkList:
3923  * @alink: a type link
3924  *
3925  * Deallocate a list of types.
3926  */
3927 static void
xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)3928 xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3929 {
3930     xmlSchemaTypeLinkPtr next;
3931 
3932     while (link != NULL) {
3933 	next = link->next;
3934 	xmlFree(link);
3935 	link = next;
3936     }
3937 }
3938 
3939 static void
xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)3940 xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3941 {
3942     xmlSchemaIDCStateObjPtr next;
3943     while (sto != NULL) {
3944 	next = sto->next;
3945 	if (sto->history != NULL)
3946 	    xmlFree(sto->history);
3947 	if (sto->xpathCtxt != NULL)
3948 	    xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3949 	xmlFree(sto);
3950 	sto = next;
3951     }
3952 }
3953 
3954 /**
3955  * xmlSchemaFreeIDC:
3956  * @idc: a identity-constraint definition
3957  *
3958  * Deallocates an identity-constraint definition.
3959  */
3960 static void
xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)3961 xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3962 {
3963     xmlSchemaIDCSelectPtr cur, prev;
3964 
3965     if (idcDef == NULL)
3966 	return;
3967     if (idcDef->annot != NULL)
3968         xmlSchemaFreeAnnot(idcDef->annot);
3969     /* Selector */
3970     if (idcDef->selector != NULL) {
3971 	if (idcDef->selector->xpathComp != NULL)
3972 	    xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3973 	xmlFree(idcDef->selector);
3974     }
3975     /* Fields */
3976     if (idcDef->fields != NULL) {
3977 	cur = idcDef->fields;
3978 	do {
3979 	    prev = cur;
3980 	    cur = cur->next;
3981 	    if (prev->xpathComp != NULL)
3982 		xmlFreePattern((xmlPatternPtr) prev->xpathComp);
3983 	    xmlFree(prev);
3984 	} while (cur != NULL);
3985     }
3986     xmlFree(idcDef);
3987 }
3988 
3989 /**
3990  * xmlSchemaFreeElement:
3991  * @schema:  a schema element structure
3992  *
3993  * Deallocate a Schema Element structure.
3994  */
3995 static void
xmlSchemaFreeElement(xmlSchemaElementPtr elem)3996 xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3997 {
3998     if (elem == NULL)
3999         return;
4000     if (elem->annot != NULL)
4001         xmlSchemaFreeAnnot(elem->annot);
4002     if (elem->contModel != NULL)
4003         xmlRegFreeRegexp(elem->contModel);
4004     if (elem->defVal != NULL)
4005 	xmlSchemaFreeValue(elem->defVal);
4006     xmlFree(elem);
4007 }
4008 
4009 /**
4010  * xmlSchemaFreeFacet:
4011  * @facet:  a schema facet structure
4012  *
4013  * Deallocate a Schema Facet structure.
4014  */
4015 void
xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)4016 xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
4017 {
4018     if (facet == NULL)
4019         return;
4020     if (facet->val != NULL)
4021         xmlSchemaFreeValue(facet->val);
4022     if (facet->regexp != NULL)
4023         xmlRegFreeRegexp(facet->regexp);
4024     if (facet->annot != NULL)
4025         xmlSchemaFreeAnnot(facet->annot);
4026     xmlFree(facet);
4027 }
4028 
4029 /**
4030  * xmlSchemaFreeType:
4031  * @type:  a schema type structure
4032  *
4033  * Deallocate a Schema Type structure.
4034  */
4035 void
xmlSchemaFreeType(xmlSchemaTypePtr type)4036 xmlSchemaFreeType(xmlSchemaTypePtr type)
4037 {
4038     if (type == NULL)
4039         return;
4040     if (type->annot != NULL)
4041         xmlSchemaFreeAnnot(type->annot);
4042     if (type->facets != NULL) {
4043         xmlSchemaFacetPtr facet, next;
4044 
4045         facet = type->facets;
4046         while (facet != NULL) {
4047             next = facet->next;
4048             xmlSchemaFreeFacet(facet);
4049             facet = next;
4050         }
4051     }
4052     if (type->attrUses != NULL)
4053 	xmlSchemaItemListFree((xmlSchemaItemListPtr) type->attrUses);
4054     if (type->memberTypes != NULL)
4055 	xmlSchemaFreeTypeLinkList(type->memberTypes);
4056     if (type->facetSet != NULL) {
4057 	xmlSchemaFacetLinkPtr next, link;
4058 
4059 	link = type->facetSet;
4060 	do {
4061 	    next = link->next;
4062 	    xmlFree(link);
4063 	    link = next;
4064 	} while (link != NULL);
4065     }
4066     if (type->contModel != NULL)
4067         xmlRegFreeRegexp(type->contModel);
4068     xmlFree(type);
4069 }
4070 
4071 /**
4072  * xmlSchemaFreeModelGroupDef:
4073  * @item:  a schema model group definition
4074  *
4075  * Deallocates a schema model group definition.
4076  */
4077 static void
xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)4078 xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
4079 {
4080     if (item->annot != NULL)
4081 	xmlSchemaFreeAnnot(item->annot);
4082     xmlFree(item);
4083 }
4084 
4085 /**
4086  * xmlSchemaFreeModelGroup:
4087  * @item:  a schema model group
4088  *
4089  * Deallocates a schema model group structure.
4090  */
4091 static void
xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)4092 xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
4093 {
4094     if (item->annot != NULL)
4095 	xmlSchemaFreeAnnot(item->annot);
4096     xmlFree(item);
4097 }
4098 
4099 static void
xmlSchemaComponentListFree(xmlSchemaItemListPtr list)4100 xmlSchemaComponentListFree(xmlSchemaItemListPtr list)
4101 {
4102     if ((list == NULL) || (list->nbItems == 0))
4103 	return;
4104     {
4105 	xmlSchemaTreeItemPtr item;
4106 	xmlSchemaTreeItemPtr *items = (xmlSchemaTreeItemPtr *) list->items;
4107 	int i;
4108 
4109 	for (i = 0; i < list->nbItems; i++) {
4110 	    item = items[i];
4111 	    if (item == NULL)
4112 		continue;
4113 	    switch (item->type) {
4114 		case XML_SCHEMA_TYPE_SIMPLE:
4115 		case XML_SCHEMA_TYPE_COMPLEX:
4116 		    xmlSchemaFreeType((xmlSchemaTypePtr) item);
4117 		    break;
4118 		case XML_SCHEMA_TYPE_ATTRIBUTE:
4119 		    xmlSchemaFreeAttribute((xmlSchemaAttributePtr) item);
4120 		    break;
4121 		case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
4122 		    xmlSchemaFreeAttributeUse((xmlSchemaAttributeUsePtr) item);
4123 		    break;
4124 		case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
4125 		    xmlSchemaFreeAttributeUseProhib(
4126 			(xmlSchemaAttributeUseProhibPtr) item);
4127 		    break;
4128 		case XML_SCHEMA_TYPE_ELEMENT:
4129 		    xmlSchemaFreeElement((xmlSchemaElementPtr) item);
4130 		    break;
4131 		case XML_SCHEMA_TYPE_PARTICLE:
4132 		    if (item->annot != NULL)
4133 			xmlSchemaFreeAnnot(item->annot);
4134 		    xmlFree(item);
4135 		    break;
4136 		case XML_SCHEMA_TYPE_SEQUENCE:
4137 		case XML_SCHEMA_TYPE_CHOICE:
4138 		case XML_SCHEMA_TYPE_ALL:
4139 		    xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
4140 		    break;
4141 		case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
4142 		    xmlSchemaFreeAttributeGroup(
4143 			(xmlSchemaAttributeGroupPtr) item);
4144 		    break;
4145 		case XML_SCHEMA_TYPE_GROUP:
4146 		    xmlSchemaFreeModelGroupDef(
4147 			(xmlSchemaModelGroupDefPtr) item);
4148 		    break;
4149 		case XML_SCHEMA_TYPE_ANY:
4150 		case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
4151 		    xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
4152 		    break;
4153 		case XML_SCHEMA_TYPE_IDC_KEY:
4154 		case XML_SCHEMA_TYPE_IDC_UNIQUE:
4155 		case XML_SCHEMA_TYPE_IDC_KEYREF:
4156 		    xmlSchemaFreeIDC((xmlSchemaIDCPtr) item);
4157 		    break;
4158 		case XML_SCHEMA_TYPE_NOTATION:
4159 		    xmlSchemaFreeNotation((xmlSchemaNotationPtr) item);
4160 		    break;
4161 		case XML_SCHEMA_EXTRA_QNAMEREF:
4162 		    xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
4163 		    break;
4164 		default: {
4165 		    /* TODO: This should never be hit. */
4166 		    xmlSchemaPSimpleInternalErr(NULL,
4167 			"Internal error: xmlSchemaComponentListFree, "
4168 			"unexpected component type '%s'\n",
4169 			(const xmlChar *) WXS_ITEM_TYPE_NAME(item));
4170 			 }
4171 		    break;
4172 	    }
4173 	}
4174 	list->nbItems = 0;
4175     }
4176 }
4177 
4178 /**
4179  * xmlSchemaFree:
4180  * @schema:  a schema structure
4181  *
4182  * Deallocate a Schema structure.
4183  */
4184 void
xmlSchemaFree(xmlSchemaPtr schema)4185 xmlSchemaFree(xmlSchemaPtr schema)
4186 {
4187     if (schema == NULL)
4188         return;
4189     /* @volatiles is not used anymore :-/ */
4190     if (schema->volatiles != NULL)
4191 	TODO
4192     /*
4193     * Note that those slots are not responsible for freeing
4194     * schema components anymore; this will now be done by
4195     * the schema buckets.
4196     */
4197     if (schema->notaDecl != NULL)
4198         xmlHashFree(schema->notaDecl, NULL);
4199     if (schema->attrDecl != NULL)
4200         xmlHashFree(schema->attrDecl, NULL);
4201     if (schema->attrgrpDecl != NULL)
4202         xmlHashFree(schema->attrgrpDecl, NULL);
4203     if (schema->elemDecl != NULL)
4204         xmlHashFree(schema->elemDecl, NULL);
4205     if (schema->typeDecl != NULL)
4206         xmlHashFree(schema->typeDecl, NULL);
4207     if (schema->groupDecl != NULL)
4208         xmlHashFree(schema->groupDecl, NULL);
4209     if (schema->idcDef != NULL)
4210         xmlHashFree(schema->idcDef, NULL);
4211 
4212     if (schema->schemasImports != NULL)
4213 	xmlHashFree(schema->schemasImports, xmlSchemaBucketFreeEntry);
4214     if (schema->includes != NULL) {
4215 	xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->includes;
4216 	int i;
4217 	for (i = 0; i < list->nbItems; i++) {
4218 	    xmlSchemaBucketFree((xmlSchemaBucketPtr) list->items[i]);
4219 	}
4220 	xmlSchemaItemListFree(list);
4221     }
4222     if (schema->annot != NULL)
4223         xmlSchemaFreeAnnot(schema->annot);
4224     /* Never free the doc here, since this will be done by the buckets. */
4225 
4226     xmlDictFree(schema->dict);
4227     xmlFree(schema);
4228 }
4229 
4230 /************************************************************************
4231  *									*
4232  *			Debug functions					*
4233  *									*
4234  ************************************************************************/
4235 
4236 #ifdef LIBXML_OUTPUT_ENABLED
4237 
4238 static void
4239 xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output); /* forward */
4240 
4241 /**
4242  * xmlSchemaElementDump:
4243  * @elem:  an element
4244  * @output:  the file output
4245  *
4246  * Dump the element
4247  */
4248 static void
xmlSchemaElementDump(void * payload,void * data,const xmlChar * name ATTRIBUTE_UNUSED,const xmlChar * namespace ATTRIBUTE_UNUSED,const xmlChar * context ATTRIBUTE_UNUSED)4249 xmlSchemaElementDump(void *payload, void *data,
4250                      const xmlChar * name ATTRIBUTE_UNUSED,
4251 		     const xmlChar * namespace ATTRIBUTE_UNUSED,
4252                      const xmlChar * context ATTRIBUTE_UNUSED)
4253 {
4254     xmlSchemaElementPtr elem = (xmlSchemaElementPtr) payload;
4255     FILE *output = (FILE *) data;
4256     if (elem == NULL)
4257         return;
4258 
4259 
4260     fprintf(output, "Element");
4261     if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
4262 	fprintf(output, " (global)");
4263     fprintf(output, ": '%s' ", elem->name);
4264     if (namespace != NULL)
4265 	fprintf(output, "ns '%s'", namespace);
4266     fprintf(output, "\n");
4267 #if 0
4268     if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
4269 	fprintf(output, "  min %d ", elem->minOccurs);
4270         if (elem->maxOccurs >= UNBOUNDED)
4271             fprintf(output, "max: unbounded\n");
4272         else if (elem->maxOccurs != 1)
4273             fprintf(output, "max: %d\n", elem->maxOccurs);
4274         else
4275             fprintf(output, "\n");
4276     }
4277 #endif
4278     /*
4279     * Misc other properties.
4280     */
4281     if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
4282 	(elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
4283 	(elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
4284 	(elem->flags & XML_SCHEMAS_ELEM_DEFAULT)) {
4285 	fprintf(output, "  props: ");
4286 	if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
4287 	    fprintf(output, "[fixed] ");
4288 	if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
4289 	    fprintf(output, "[default] ");
4290 	if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
4291 	    fprintf(output, "[abstract] ");
4292 	if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
4293 	    fprintf(output, "[nillable] ");
4294 	fprintf(output, "\n");
4295     }
4296     /*
4297     * Default/fixed value.
4298     */
4299     if (elem->value != NULL)
4300 	fprintf(output, "  value: '%s'\n", elem->value);
4301     /*
4302     * Type.
4303     */
4304     if (elem->namedType != NULL) {
4305 	fprintf(output, "  type: '%s' ", elem->namedType);
4306 	if (elem->namedTypeNs != NULL)
4307 	    fprintf(output, "ns '%s'\n", elem->namedTypeNs);
4308 	else
4309 	    fprintf(output, "\n");
4310     } else if (elem->subtypes != NULL) {
4311 	/*
4312 	* Dump local types.
4313 	*/
4314 	xmlSchemaTypeDump(elem->subtypes, output);
4315     }
4316     /*
4317     * Substitution group.
4318     */
4319     if (elem->substGroup != NULL) {
4320 	fprintf(output, "  substitutionGroup: '%s' ", elem->substGroup);
4321 	if (elem->substGroupNs != NULL)
4322 	    fprintf(output, "ns '%s'\n", elem->substGroupNs);
4323 	else
4324 	    fprintf(output, "\n");
4325     }
4326 }
4327 
4328 /**
4329  * xmlSchemaAnnotDump:
4330  * @output:  the file output
4331  * @annot:  a annotation
4332  *
4333  * Dump the annotation
4334  */
4335 static void
xmlSchemaAnnotDump(FILE * output,xmlSchemaAnnotPtr annot)4336 xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
4337 {
4338     xmlChar *content;
4339 
4340     if (annot == NULL)
4341         return;
4342 
4343     content = xmlNodeGetContent(annot->content);
4344     if (content != NULL) {
4345         fprintf(output, "  Annot: %s\n", content);
4346         xmlFree(content);
4347     } else
4348         fprintf(output, "  Annot: empty\n");
4349 }
4350 
4351 /**
4352  * xmlSchemaContentModelDump:
4353  * @particle: the schema particle
4354  * @output: the file output
4355  * @depth: the depth used for indentation
4356  *
4357  * Dump a SchemaType structure
4358  */
4359 static void
xmlSchemaContentModelDump(xmlSchemaParticlePtr particle,FILE * output,int depth)4360 xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
4361 {
4362     xmlChar *str = NULL;
4363     xmlSchemaTreeItemPtr term;
4364     char shift[100];
4365     int i;
4366 
4367     if (particle == NULL)
4368 	return;
4369     for (i = 0;((i < depth) && (i < 25));i++)
4370         shift[2 * i] = shift[2 * i + 1] = ' ';
4371     shift[2 * i] = shift[2 * i + 1] = 0;
4372     fprintf(output, "%s", shift);
4373     if (particle->children == NULL) {
4374 	fprintf(output, "MISSING particle term\n");
4375 	return;
4376     }
4377     term = particle->children;
4378     if (term == NULL) {
4379 	fprintf(output, "(NULL)");
4380     } else {
4381 	switch (term->type) {
4382 	    case XML_SCHEMA_TYPE_ELEMENT:
4383 		fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
4384 		    ((xmlSchemaElementPtr)term)->targetNamespace,
4385 		    ((xmlSchemaElementPtr)term)->name));
4386 		FREE_AND_NULL(str);
4387 		break;
4388 	    case XML_SCHEMA_TYPE_SEQUENCE:
4389 		fprintf(output, "SEQUENCE");
4390 		break;
4391 	    case XML_SCHEMA_TYPE_CHOICE:
4392 		fprintf(output, "CHOICE");
4393 		break;
4394 	    case XML_SCHEMA_TYPE_ALL:
4395 		fprintf(output, "ALL");
4396 		break;
4397 	    case XML_SCHEMA_TYPE_ANY:
4398 		fprintf(output, "ANY");
4399 		break;
4400 	    default:
4401 		fprintf(output, "UNKNOWN\n");
4402 		return;
4403 	}
4404     }
4405     if (particle->minOccurs != 1)
4406 	fprintf(output, " min: %d", particle->minOccurs);
4407     if (particle->maxOccurs >= UNBOUNDED)
4408 	fprintf(output, " max: unbounded");
4409     else if (particle->maxOccurs != 1)
4410 	fprintf(output, " max: %d", particle->maxOccurs);
4411     fprintf(output, "\n");
4412     if (term &&
4413 	((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
4414 	 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
4415 	 (term->type == XML_SCHEMA_TYPE_ALL)) &&
4416 	 (term->children != NULL)) {
4417 	xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
4418 	    output, depth +1);
4419     }
4420     if (particle->next != NULL)
4421 	xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
4422 		output, depth);
4423 }
4424 
4425 /**
4426  * xmlSchemaAttrUsesDump:
4427  * @uses:  attribute uses list
4428  * @output:  the file output
4429  *
4430  * Dumps a list of attribute use components.
4431  */
4432 static void
xmlSchemaAttrUsesDump(xmlSchemaItemListPtr uses,FILE * output)4433 xmlSchemaAttrUsesDump(xmlSchemaItemListPtr uses, FILE * output)
4434 {
4435     xmlSchemaAttributeUsePtr use;
4436     xmlSchemaAttributeUseProhibPtr prohib;
4437     xmlSchemaQNameRefPtr ref;
4438     const xmlChar *name, *tns;
4439     xmlChar *str = NULL;
4440     int i;
4441 
4442     if ((uses == NULL) || (uses->nbItems == 0))
4443         return;
4444 
4445     fprintf(output, "  attributes:\n");
4446     for (i = 0; i < uses->nbItems; i++) {
4447 	use = uses->items[i];
4448 	if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
4449 	    fprintf(output, "  [prohibition] ");
4450 	    prohib = (xmlSchemaAttributeUseProhibPtr) use;
4451 	    name = prohib->name;
4452 	    tns = prohib->targetNamespace;
4453 	} else if (use->type == XML_SCHEMA_EXTRA_QNAMEREF) {
4454 	    fprintf(output, "  [reference] ");
4455 	    ref = (xmlSchemaQNameRefPtr) use;
4456 	    name = ref->name;
4457 	    tns = ref->targetNamespace;
4458 	} else {
4459 	    fprintf(output, "  [use] ");
4460 	    name = WXS_ATTRUSE_DECL_NAME(use);
4461 	    tns = WXS_ATTRUSE_DECL_TNS(use);
4462 	}
4463 	fprintf(output, "'%s'\n",
4464 	    (const char *) xmlSchemaFormatQName(&str, tns, name));
4465 	FREE_AND_NULL(str);
4466     }
4467 }
4468 
4469 /**
4470  * xmlSchemaTypeDump:
4471  * @output:  the file output
4472  * @type:  a type structure
4473  *
4474  * Dump a SchemaType structure
4475  */
4476 static void
xmlSchemaTypeDump(xmlSchemaTypePtr type,FILE * output)4477 xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
4478 {
4479     if (type == NULL) {
4480         fprintf(output, "Type: NULL\n");
4481         return;
4482     }
4483     fprintf(output, "Type: ");
4484     if (type->name != NULL)
4485         fprintf(output, "'%s' ", type->name);
4486     else
4487         fprintf(output, "(no name) ");
4488     if (type->targetNamespace != NULL)
4489 	fprintf(output, "ns '%s' ", type->targetNamespace);
4490     switch (type->type) {
4491         case XML_SCHEMA_TYPE_BASIC:
4492             fprintf(output, "[basic] ");
4493             break;
4494         case XML_SCHEMA_TYPE_SIMPLE:
4495             fprintf(output, "[simple] ");
4496             break;
4497         case XML_SCHEMA_TYPE_COMPLEX:
4498             fprintf(output, "[complex] ");
4499             break;
4500         case XML_SCHEMA_TYPE_SEQUENCE:
4501             fprintf(output, "[sequence] ");
4502             break;
4503         case XML_SCHEMA_TYPE_CHOICE:
4504             fprintf(output, "[choice] ");
4505             break;
4506         case XML_SCHEMA_TYPE_ALL:
4507             fprintf(output, "[all] ");
4508             break;
4509         case XML_SCHEMA_TYPE_UR:
4510             fprintf(output, "[ur] ");
4511             break;
4512         case XML_SCHEMA_TYPE_RESTRICTION:
4513             fprintf(output, "[restriction] ");
4514             break;
4515         case XML_SCHEMA_TYPE_EXTENSION:
4516             fprintf(output, "[extension] ");
4517             break;
4518         default:
4519             fprintf(output, "[unknown type %d] ", type->type);
4520             break;
4521     }
4522     fprintf(output, "content: ");
4523     switch (type->contentType) {
4524         case XML_SCHEMA_CONTENT_UNKNOWN:
4525             fprintf(output, "[unknown] ");
4526             break;
4527         case XML_SCHEMA_CONTENT_EMPTY:
4528             fprintf(output, "[empty] ");
4529             break;
4530         case XML_SCHEMA_CONTENT_ELEMENTS:
4531             fprintf(output, "[element] ");
4532             break;
4533         case XML_SCHEMA_CONTENT_MIXED:
4534             fprintf(output, "[mixed] ");
4535             break;
4536         case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
4537 	/* not used. */
4538             break;
4539         case XML_SCHEMA_CONTENT_BASIC:
4540             fprintf(output, "[basic] ");
4541             break;
4542         case XML_SCHEMA_CONTENT_SIMPLE:
4543             fprintf(output, "[simple] ");
4544             break;
4545         case XML_SCHEMA_CONTENT_ANY:
4546             fprintf(output, "[any] ");
4547             break;
4548     }
4549     fprintf(output, "\n");
4550     if (type->base != NULL) {
4551         fprintf(output, "  base type: '%s'", type->base);
4552 	if (type->baseNs != NULL)
4553 	    fprintf(output, " ns '%s'\n", type->baseNs);
4554 	else
4555 	    fprintf(output, "\n");
4556     }
4557     if (type->attrUses != NULL)
4558 	xmlSchemaAttrUsesDump(type->attrUses, output);
4559     if (type->annot != NULL)
4560         xmlSchemaAnnotDump(output, type->annot);
4561 #ifdef DUMP_CONTENT_MODEL
4562     if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
4563 	(type->subtypes != NULL)) {
4564 	xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
4565 	    output, 1);
4566     }
4567 #endif
4568 }
4569 
4570 static void
xmlSchemaTypeDumpEntry(void * type,void * output,const xmlChar * name ATTRIBUTE_UNUSED)4571 xmlSchemaTypeDumpEntry(void *type, void *output,
4572                        const xmlChar *name ATTRIBUTE_UNUSED)
4573 {
4574     xmlSchemaTypeDump((xmlSchemaTypePtr) type, (FILE *) output);
4575 }
4576 
4577 /**
4578  * xmlSchemaDump:
4579  * @output:  the file output
4580  * @schema:  a schema structure
4581  *
4582  * Dump a Schema structure.
4583  */
4584 void
xmlSchemaDump(FILE * output,xmlSchemaPtr schema)4585 xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
4586 {
4587     if (output == NULL)
4588         return;
4589     if (schema == NULL) {
4590         fprintf(output, "Schemas: NULL\n");
4591         return;
4592     }
4593     fprintf(output, "Schemas: ");
4594     if (schema->name != NULL)
4595         fprintf(output, "%s, ", schema->name);
4596     else
4597         fprintf(output, "no name, ");
4598     if (schema->targetNamespace != NULL)
4599         fprintf(output, "%s", (const char *) schema->targetNamespace);
4600     else
4601         fprintf(output, "no target namespace");
4602     fprintf(output, "\n");
4603     if (schema->annot != NULL)
4604         xmlSchemaAnnotDump(output, schema->annot);
4605     xmlHashScan(schema->typeDecl, xmlSchemaTypeDumpEntry, output);
4606     xmlHashScanFull(schema->elemDecl, xmlSchemaElementDump, output);
4607 }
4608 
4609 #ifdef DEBUG_IDC_NODE_TABLE
4610 /**
4611  * xmlSchemaDebugDumpIDCTable:
4612  * @vctxt: the WXS validation context
4613  *
4614  * Displays the current IDC table for debug purposes.
4615  */
4616 static void
xmlSchemaDebugDumpIDCTable(FILE * output,const xmlChar * namespaceName,const xmlChar * localName,xmlSchemaPSVIIDCBindingPtr bind)4617 xmlSchemaDebugDumpIDCTable(FILE * output,
4618 			   const xmlChar *namespaceName,
4619 			   const xmlChar *localName,
4620 			   xmlSchemaPSVIIDCBindingPtr bind)
4621 {
4622     xmlChar *str = NULL;
4623     const xmlChar *value;
4624     xmlSchemaPSVIIDCNodePtr tab;
4625     xmlSchemaPSVIIDCKeyPtr key;
4626     int i, j, res;
4627 
4628     fprintf(output, "IDC: TABLES on '%s'\n",
4629 	xmlSchemaFormatQName(&str, namespaceName, localName));
4630     FREE_AND_NULL(str)
4631 
4632     if (bind == NULL)
4633 	return;
4634     do {
4635 	fprintf(output, "IDC:   BINDING '%s' (%d)\n",
4636 	    xmlSchemaGetComponentQName(&str,
4637 		bind->definition), bind->nbNodes);
4638 	FREE_AND_NULL(str)
4639 	for (i = 0; i < bind->nbNodes; i++) {
4640 	    tab = bind->nodeTable[i];
4641 	    fprintf(output, "         ( ");
4642 	    for (j = 0; j < bind->definition->nbFields; j++) {
4643 		key = tab->keys[j];
4644 		if ((key != NULL) && (key->val != NULL)) {
4645 		    res = xmlSchemaGetCanonValue(key->val, &value);
4646 		    if (res >= 0)
4647 			fprintf(output, "'%s' ", value);
4648 		    else
4649 			fprintf(output, "CANON-VALUE-FAILED ");
4650 		    if (res == 0)
4651 			FREE_AND_NULL(value)
4652 		} else if (key != NULL)
4653 		    fprintf(output, "(no val), ");
4654 		else
4655 		    fprintf(output, "(key missing), ");
4656 	    }
4657 	    fprintf(output, ")\n");
4658 	}
4659 	if (bind->dupls && bind->dupls->nbItems) {
4660 	    fprintf(output, "IDC:     dupls (%d):\n", bind->dupls->nbItems);
4661 	    for (i = 0; i < bind->dupls->nbItems; i++) {
4662 		tab = bind->dupls->items[i];
4663 		fprintf(output, "         ( ");
4664 		for (j = 0; j < bind->definition->nbFields; j++) {
4665 		    key = tab->keys[j];
4666 		    if ((key != NULL) && (key->val != NULL)) {
4667 			res = xmlSchemaGetCanonValue(key->val, &value);
4668 			if (res >= 0)
4669 			    fprintf(output, "'%s' ", value);
4670 			else
4671 			    fprintf(output, "CANON-VALUE-FAILED ");
4672 			if (res == 0)
4673 			    FREE_AND_NULL(value)
4674 		    } else if (key != NULL)
4675 		    fprintf(output, "(no val), ");
4676 			else
4677 			    fprintf(output, "(key missing), ");
4678 		}
4679 		fprintf(output, ")\n");
4680 	    }
4681 	}
4682 	bind = bind->next;
4683     } while (bind != NULL);
4684 }
4685 #endif /* DEBUG_IDC */
4686 #endif /* LIBXML_OUTPUT_ENABLED */
4687 
4688 /************************************************************************
4689  *									*
4690  *			Utilities					*
4691  *									*
4692  ************************************************************************/
4693 
4694 /**
4695  * xmlSchemaGetPropNode:
4696  * @node: the element node
4697  * @name: the name of the attribute
4698  *
4699  * Seeks an attribute with a name of @name in
4700  * no namespace.
4701  *
4702  * Returns the attribute or NULL if not present.
4703  */
4704 static xmlAttrPtr
xmlSchemaGetPropNode(xmlNodePtr node,const char * name)4705 xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
4706 {
4707     xmlAttrPtr prop;
4708 
4709     if ((node == NULL) || (name == NULL))
4710 	return(NULL);
4711     prop = node->properties;
4712     while (prop != NULL) {
4713         if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
4714 	    return(prop);
4715 	prop = prop->next;
4716     }
4717     return (NULL);
4718 }
4719 
4720 /**
4721  * xmlSchemaGetPropNodeNs:
4722  * @node: the element node
4723  * @uri: the uri
4724  * @name: the name of the attribute
4725  *
4726  * Seeks an attribute with a local name of @name and
4727  * a namespace URI of @uri.
4728  *
4729  * Returns the attribute or NULL if not present.
4730  */
4731 static xmlAttrPtr
xmlSchemaGetPropNodeNs(xmlNodePtr node,const char * uri,const char * name)4732 xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
4733 {
4734     xmlAttrPtr prop;
4735 
4736     if ((node == NULL) || (name == NULL))
4737 	return(NULL);
4738     prop = node->properties;
4739     while (prop != NULL) {
4740 	if ((prop->ns != NULL) &&
4741 	    xmlStrEqual(prop->name, BAD_CAST name) &&
4742 	    xmlStrEqual(prop->ns->href, BAD_CAST uri))
4743 	    return(prop);
4744 	prop = prop->next;
4745     }
4746     return (NULL);
4747 }
4748 
4749 static const xmlChar *
xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node)4750 xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
4751 {
4752     xmlChar *val;
4753     const xmlChar *ret;
4754 
4755     val = xmlNodeGetContent(node);
4756     if (val == NULL)
4757 	val = xmlStrdup((xmlChar *)"");
4758     ret = xmlDictLookup(ctxt->dict, val, -1);
4759     xmlFree(val);
4760     return(ret);
4761 }
4762 
4763 static const xmlChar *
xmlSchemaGetNodeContentNoDict(xmlNodePtr node)4764 xmlSchemaGetNodeContentNoDict(xmlNodePtr node)
4765 {
4766     return((const xmlChar*) xmlNodeGetContent(node));
4767 }
4768 
4769 /**
4770  * xmlSchemaGetProp:
4771  * @ctxt: the parser context
4772  * @node: the node
4773  * @name: the property name
4774  *
4775  * Read a attribute value and internalize the string
4776  *
4777  * Returns the string or NULL if not present.
4778  */
4779 static const xmlChar *
xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,const char * name)4780 xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4781                  const char *name)
4782 {
4783     xmlChar *val;
4784     const xmlChar *ret;
4785 
4786     val = xmlGetNoNsProp(node, BAD_CAST name);
4787     if (val == NULL)
4788         return(NULL);
4789     ret = xmlDictLookup(ctxt->dict, val, -1);
4790     xmlFree(val);
4791     return(ret);
4792 }
4793 
4794 /************************************************************************
4795  *									*
4796  *			Parsing functions				*
4797  *									*
4798  ************************************************************************/
4799 
4800 #define WXS_FIND_GLOBAL_ITEM(slot)			\
4801     if (xmlStrEqual(nsName, schema->targetNamespace)) { \
4802 	ret = xmlHashLookup(schema->slot, name); \
4803 	if (ret != NULL) goto exit; \
4804     } \
4805     if (xmlHashSize(schema->schemasImports) > 1) { \
4806 	xmlSchemaImportPtr import; \
4807 	if (nsName == NULL) \
4808 	    import = xmlHashLookup(schema->schemasImports, \
4809 		XML_SCHEMAS_NO_NAMESPACE); \
4810 	else \
4811 	    import = xmlHashLookup(schema->schemasImports, nsName); \
4812 	if (import == NULL) \
4813 	    goto exit; \
4814 	ret = xmlHashLookup(import->schema->slot, name); \
4815     }
4816 
4817 /**
4818  * xmlSchemaGetElem:
4819  * @schema:  the schema context
4820  * @name:  the element name
4821  * @ns:  the element namespace
4822  *
4823  * Lookup a global element declaration in the schema.
4824  *
4825  * Returns the element declaration or NULL if not found.
4826  */
4827 static xmlSchemaElementPtr
xmlSchemaGetElem(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4828 xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
4829                  const xmlChar * nsName)
4830 {
4831     xmlSchemaElementPtr ret = NULL;
4832 
4833     if ((name == NULL) || (schema == NULL))
4834         return(NULL);
4835     if (schema != NULL) {
4836 	WXS_FIND_GLOBAL_ITEM(elemDecl)
4837     }
4838 exit:
4839 #ifdef DEBUG
4840     if (ret == NULL) {
4841         if (nsName == NULL)
4842             fprintf(stderr, "Unable to lookup element decl. %s", name);
4843         else
4844             fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
4845                     nsName);
4846     }
4847 #endif
4848     return (ret);
4849 }
4850 
4851 /**
4852  * xmlSchemaGetType:
4853  * @schema:  the main schema
4854  * @name:  the type's name
4855  * nsName:  the type's namespace
4856  *
4857  * Lookup a type in the schemas or the predefined types
4858  *
4859  * Returns the group definition or NULL if not found.
4860  */
4861 static xmlSchemaTypePtr
xmlSchemaGetType(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4862 xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
4863                  const xmlChar * nsName)
4864 {
4865     xmlSchemaTypePtr ret = NULL;
4866 
4867     if (name == NULL)
4868         return (NULL);
4869     /* First try the built-in types. */
4870     if ((nsName != NULL) && xmlStrEqual(nsName, xmlSchemaNs)) {
4871 	ret = xmlSchemaGetPredefinedType(name, nsName);
4872 	if (ret != NULL)
4873 	    goto exit;
4874 	/*
4875 	* Note that we try the parsed schemas as well here
4876 	* since one might have parsed the S4S, which contain more
4877 	* than the built-in types.
4878 	* TODO: Can we optimize this?
4879 	*/
4880     }
4881     if (schema != NULL) {
4882 	WXS_FIND_GLOBAL_ITEM(typeDecl)
4883     }
4884 exit:
4885 
4886 #ifdef DEBUG
4887     if (ret == NULL) {
4888         if (nsName == NULL)
4889             fprintf(stderr, "Unable to lookup type %s", name);
4890         else
4891             fprintf(stderr, "Unable to lookup type %s:%s", name,
4892                     nsName);
4893     }
4894 #endif
4895     return (ret);
4896 }
4897 
4898 /**
4899  * xmlSchemaGetAttributeDecl:
4900  * @schema:  the context of the schema
4901  * @name:  the name of the attribute
4902  * @ns:  the target namespace of the attribute
4903  *
4904  * Lookup a an attribute in the schema or imported schemas
4905  *
4906  * Returns the attribute declaration or NULL if not found.
4907  */
4908 static xmlSchemaAttributePtr
xmlSchemaGetAttributeDecl(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4909 xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
4910                  const xmlChar * nsName)
4911 {
4912     xmlSchemaAttributePtr ret = NULL;
4913 
4914     if ((name == NULL) || (schema == NULL))
4915         return (NULL);
4916     if (schema != NULL) {
4917 	WXS_FIND_GLOBAL_ITEM(attrDecl)
4918     }
4919 exit:
4920 #ifdef DEBUG
4921     if (ret == NULL) {
4922         if (nsName == NULL)
4923             fprintf(stderr, "Unable to lookup attribute %s", name);
4924         else
4925             fprintf(stderr, "Unable to lookup attribute %s:%s", name,
4926                     nsName);
4927     }
4928 #endif
4929     return (ret);
4930 }
4931 
4932 /**
4933  * xmlSchemaGetAttributeGroup:
4934  * @schema:  the context of the schema
4935  * @name:  the name of the attribute group
4936  * @ns:  the target namespace of the attribute group
4937  *
4938  * Lookup a an attribute group in the schema or imported schemas
4939  *
4940  * Returns the attribute group definition or NULL if not found.
4941  */
4942 static xmlSchemaAttributeGroupPtr
xmlSchemaGetAttributeGroup(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4943 xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
4944                  const xmlChar * nsName)
4945 {
4946     xmlSchemaAttributeGroupPtr ret = NULL;
4947 
4948     if ((name == NULL) || (schema == NULL))
4949         return (NULL);
4950     if (schema != NULL) {
4951 	WXS_FIND_GLOBAL_ITEM(attrgrpDecl)
4952     }
4953 exit:
4954     /* TODO:
4955     if ((ret != NULL) && (ret->redef != NULL)) {
4956 	* Return the last redefinition. *
4957 	ret = ret->redef;
4958     }
4959     */
4960 #ifdef DEBUG
4961     if (ret == NULL) {
4962         if (nsName == NULL)
4963             fprintf(stderr, "Unable to lookup attribute group %s", name);
4964         else
4965             fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
4966                     nsName);
4967     }
4968 #endif
4969     return (ret);
4970 }
4971 
4972 /**
4973  * xmlSchemaGetGroup:
4974  * @schema:  the context of the schema
4975  * @name:  the name of the group
4976  * @ns:  the target namespace of the group
4977  *
4978  * Lookup a group in the schema or imported schemas
4979  *
4980  * Returns the group definition or NULL if not found.
4981  */
4982 static xmlSchemaModelGroupDefPtr
xmlSchemaGetGroup(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4983 xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
4984                  const xmlChar * nsName)
4985 {
4986     xmlSchemaModelGroupDefPtr ret = NULL;
4987 
4988     if ((name == NULL) || (schema == NULL))
4989         return (NULL);
4990     if (schema != NULL) {
4991 	WXS_FIND_GLOBAL_ITEM(groupDecl)
4992     }
4993 exit:
4994 
4995 #ifdef DEBUG
4996     if (ret == NULL) {
4997         if (nsName == NULL)
4998             fprintf(stderr, "Unable to lookup group %s", name);
4999         else
5000             fprintf(stderr, "Unable to lookup group %s:%s", name,
5001                     nsName);
5002     }
5003 #endif
5004     return (ret);
5005 }
5006 
5007 static xmlSchemaNotationPtr
xmlSchemaGetNotation(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)5008 xmlSchemaGetNotation(xmlSchemaPtr schema,
5009 		     const xmlChar *name,
5010 		     const xmlChar *nsName)
5011 {
5012     xmlSchemaNotationPtr ret = NULL;
5013 
5014     if ((name == NULL) || (schema == NULL))
5015         return (NULL);
5016     if (schema != NULL) {
5017 	WXS_FIND_GLOBAL_ITEM(notaDecl)
5018     }
5019 exit:
5020     return (ret);
5021 }
5022 
5023 static xmlSchemaIDCPtr
xmlSchemaGetIDC(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)5024 xmlSchemaGetIDC(xmlSchemaPtr schema,
5025 		const xmlChar *name,
5026 		const xmlChar *nsName)
5027 {
5028     xmlSchemaIDCPtr ret = NULL;
5029 
5030     if ((name == NULL) || (schema == NULL))
5031         return (NULL);
5032     if (schema != NULL) {
5033 	WXS_FIND_GLOBAL_ITEM(idcDef)
5034     }
5035 exit:
5036     return (ret);
5037 }
5038 
5039 /**
5040  * xmlSchemaGetNamedComponent:
5041  * @schema:  the schema
5042  * @name:  the name of the group
5043  * @ns:  the target namespace of the group
5044  *
5045  * Lookup a group in the schema or imported schemas
5046  *
5047  * Returns the group definition or NULL if not found.
5048  */
5049 static xmlSchemaBasicItemPtr
xmlSchemaGetNamedComponent(xmlSchemaPtr schema,xmlSchemaTypeType itemType,const xmlChar * name,const xmlChar * targetNs)5050 xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
5051 			   xmlSchemaTypeType itemType,
5052 			   const xmlChar *name,
5053 			   const xmlChar *targetNs)
5054 {
5055     switch (itemType) {
5056 	case XML_SCHEMA_TYPE_GROUP:
5057 	    return ((xmlSchemaBasicItemPtr) xmlSchemaGetGroup(schema,
5058 		name, targetNs));
5059 	case XML_SCHEMA_TYPE_ELEMENT:
5060 	    return ((xmlSchemaBasicItemPtr) xmlSchemaGetElem(schema,
5061 		name, targetNs));
5062 	default:
5063 	    TODO
5064 	    return (NULL);
5065     }
5066 }
5067 
5068 /************************************************************************
5069  *									*
5070  *			Parsing functions				*
5071  *									*
5072  ************************************************************************/
5073 
5074 #define IS_BLANK_NODE(n)						\
5075     (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
5076 
5077 /**
5078  * xmlSchemaIsBlank:
5079  * @str:  a string
5080  * @len: the length of the string or -1
5081  *
5082  * Check if a string is ignorable
5083  *
5084  * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
5085  */
5086 static int
xmlSchemaIsBlank(xmlChar * str,int len)5087 xmlSchemaIsBlank(xmlChar * str, int len)
5088 {
5089     if (str == NULL)
5090         return (1);
5091     if (len < 0) {
5092 	while (*str != 0) {
5093 	    if (!(IS_BLANK_CH(*str)))
5094 		return (0);
5095 	    str++;
5096 	}
5097     } else while ((*str != 0) && (len != 0)) {
5098 	if (!(IS_BLANK_CH(*str)))
5099 	    return (0);
5100 	str++;
5101 	len--;
5102     }
5103 
5104     return (1);
5105 }
5106 
5107 #define WXS_COMP_NAME(c, t) ((t) (c))->name
5108 #define WXS_COMP_TNS(c, t) ((t) (c))->targetNamespace
5109 /*
5110 * xmlSchemaFindRedefCompInGraph:
5111 * ATTENTION TODO: This uses pointer comp. for strings.
5112 */
5113 static xmlSchemaBasicItemPtr
xmlSchemaFindRedefCompInGraph(xmlSchemaBucketPtr bucket,xmlSchemaTypeType type,const xmlChar * name,const xmlChar * nsName)5114 xmlSchemaFindRedefCompInGraph(xmlSchemaBucketPtr bucket,
5115 			      xmlSchemaTypeType type,
5116 			      const xmlChar *name,
5117 			      const xmlChar *nsName)
5118 {
5119     xmlSchemaBasicItemPtr ret;
5120     int i;
5121 
5122     if ((bucket == NULL) || (name == NULL))
5123 	return(NULL);
5124     if ((bucket->globals == NULL) ||
5125 	(bucket->globals->nbItems == 0))
5126 	goto subschemas;
5127     /*
5128     * Search in global components.
5129     */
5130     for (i = 0; i < bucket->globals->nbItems; i++) {
5131 	ret = bucket->globals->items[i];
5132 	if (ret->type == type) {
5133 	    switch (type) {
5134 		case XML_SCHEMA_TYPE_COMPLEX:
5135 		case XML_SCHEMA_TYPE_SIMPLE:
5136 		    if ((WXS_COMP_NAME(ret, xmlSchemaTypePtr) == name) &&
5137 			(WXS_COMP_TNS(ret, xmlSchemaTypePtr) ==
5138 			nsName))
5139 		    {
5140 			return(ret);
5141 		    }
5142 		    break;
5143 		case XML_SCHEMA_TYPE_GROUP:
5144 		    if ((WXS_COMP_NAME(ret,
5145 			    xmlSchemaModelGroupDefPtr) == name) &&
5146 			(WXS_COMP_TNS(ret,
5147 			    xmlSchemaModelGroupDefPtr) == nsName))
5148 		    {
5149 			return(ret);
5150 		    }
5151 		    break;
5152 		case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
5153 		    if ((WXS_COMP_NAME(ret,
5154 			    xmlSchemaAttributeGroupPtr) == name) &&
5155 			(WXS_COMP_TNS(ret,
5156 			    xmlSchemaAttributeGroupPtr) == nsName))
5157 		    {
5158 			return(ret);
5159 		    }
5160 		    break;
5161 		default:
5162 		    /* Should not be hit. */
5163 		    return(NULL);
5164 	    }
5165 	}
5166     }
5167 subschemas:
5168     /*
5169     * Process imported/included schemas.
5170     */
5171     if (bucket->relations != NULL) {
5172 	xmlSchemaSchemaRelationPtr rel = bucket->relations;
5173 
5174 	/*
5175 	* TODO: Marking the bucket will not avoid multiple searches
5176 	* in the same schema, but avoids at least circularity.
5177 	*/
5178 	bucket->flags |= XML_SCHEMA_BUCKET_MARKED;
5179 	do {
5180 	    if ((rel->bucket != NULL) &&
5181 		((rel->bucket->flags & XML_SCHEMA_BUCKET_MARKED) == 0)) {
5182 		ret = xmlSchemaFindRedefCompInGraph(rel->bucket,
5183 		    type, name, nsName);
5184 		if (ret != NULL)
5185 		    return(ret);
5186 	    }
5187 	    rel = rel->next;
5188 	} while (rel != NULL);
5189 	 bucket->flags ^= XML_SCHEMA_BUCKET_MARKED;
5190     }
5191     return(NULL);
5192 }
5193 
5194 /**
5195  * xmlSchemaAddNotation:
5196  * @ctxt:  a schema parser context
5197  * @schema:  the schema being built
5198  * @name:  the item name
5199  *
5200  * Add an XML schema annotation declaration
5201  * *WARNING* this interface is highly subject to change
5202  *
5203  * Returns the new structure or NULL in case of error
5204  */
5205 static xmlSchemaNotationPtr
xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node ATTRIBUTE_UNUSED)5206 xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5207                      const xmlChar *name, const xmlChar *nsName,
5208 		     xmlNodePtr node ATTRIBUTE_UNUSED)
5209 {
5210     xmlSchemaNotationPtr ret = NULL;
5211 
5212     if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5213         return (NULL);
5214 
5215     ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
5216     if (ret == NULL) {
5217         xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
5218         return (NULL);
5219     }
5220     memset(ret, 0, sizeof(xmlSchemaNotation));
5221     ret->type = XML_SCHEMA_TYPE_NOTATION;
5222     ret->name = name;
5223     ret->targetNamespace = nsName;
5224     /* TODO: do we need the node to be set?
5225     * ret->node = node;*/
5226     WXS_ADD_GLOBAL(ctxt, ret);
5227     return (ret);
5228 }
5229 
5230 /**
5231  * xmlSchemaAddAttribute:
5232  * @ctxt:  a schema parser context
5233  * @schema:  the schema being built
5234  * @name:  the item name
5235  * @namespace:  the namespace
5236  *
5237  * Add an XML schema Attribute declaration
5238  * *WARNING* this interface is highly subject to change
5239  *
5240  * Returns the new structure or NULL in case of error
5241  */
5242 static xmlSchemaAttributePtr
xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node,int topLevel)5243 xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5244                       const xmlChar * name, const xmlChar * nsName,
5245 		      xmlNodePtr node, int topLevel)
5246 {
5247     xmlSchemaAttributePtr ret = NULL;
5248 
5249     if ((ctxt == NULL) || (schema == NULL))
5250         return (NULL);
5251 
5252     ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
5253     if (ret == NULL) {
5254         xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
5255         return (NULL);
5256     }
5257     memset(ret, 0, sizeof(xmlSchemaAttribute));
5258     ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
5259     ret->node = node;
5260     ret->name = name;
5261     ret->targetNamespace = nsName;
5262 
5263     if (topLevel)
5264 	WXS_ADD_GLOBAL(ctxt, ret);
5265     else
5266 	WXS_ADD_LOCAL(ctxt, ret);
5267     WXS_ADD_PENDING(ctxt, ret);
5268     return (ret);
5269 }
5270 
5271 /**
5272  * xmlSchemaAddAttributeUse:
5273  * @ctxt:  a schema parser context
5274  * @schema:  the schema being built
5275  * @name:  the item name
5276  * @namespace:  the namespace
5277  *
5278  * Add an XML schema Attribute declaration
5279  * *WARNING* this interface is highly subject to change
5280  *
5281  * Returns the new structure or NULL in case of error
5282  */
5283 static xmlSchemaAttributeUsePtr
xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt,xmlNodePtr node)5284 xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt,
5285 			 xmlNodePtr node)
5286 {
5287     xmlSchemaAttributeUsePtr ret = NULL;
5288 
5289     if (pctxt == NULL)
5290         return (NULL);
5291 
5292     ret = (xmlSchemaAttributeUsePtr) xmlMalloc(sizeof(xmlSchemaAttributeUse));
5293     if (ret == NULL) {
5294         xmlSchemaPErrMemory(pctxt, "allocating attribute", NULL);
5295         return (NULL);
5296     }
5297     memset(ret, 0, sizeof(xmlSchemaAttributeUse));
5298     ret->type = XML_SCHEMA_TYPE_ATTRIBUTE_USE;
5299     ret->node = node;
5300 
5301     WXS_ADD_LOCAL(pctxt, ret);
5302     return (ret);
5303 }
5304 
5305 /*
5306 * xmlSchemaAddRedef:
5307 *
5308 * Adds a redefinition information. This is used at a later stage to:
5309 * resolve references to the redefined components and to check constraints.
5310 */
5311 static xmlSchemaRedefPtr
xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBucketPtr targetBucket,void * item,const xmlChar * refName,const xmlChar * refTargetNs)5312 xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt,
5313 		  xmlSchemaBucketPtr targetBucket,
5314 		  void *item,
5315 		  const xmlChar *refName,
5316 		  const xmlChar *refTargetNs)
5317 {
5318     xmlSchemaRedefPtr ret;
5319 
5320     ret = (xmlSchemaRedefPtr)
5321 	xmlMalloc(sizeof(xmlSchemaRedef));
5322     if (ret == NULL) {
5323 	xmlSchemaPErrMemory(pctxt,
5324 	    "allocating redefinition info", NULL);
5325 	return (NULL);
5326     }
5327     memset(ret, 0, sizeof(xmlSchemaRedef));
5328     ret->item = item;
5329     ret->targetBucket = targetBucket;
5330     ret->refName = refName;
5331     ret->refTargetNs = refTargetNs;
5332     if (WXS_CONSTRUCTOR(pctxt)->redefs == NULL)
5333 	WXS_CONSTRUCTOR(pctxt)->redefs = ret;
5334     else
5335 	WXS_CONSTRUCTOR(pctxt)->lastRedef->next = ret;
5336     WXS_CONSTRUCTOR(pctxt)->lastRedef = ret;
5337 
5338     return (ret);
5339 }
5340 
5341 /**
5342  * xmlSchemaAddAttributeGroupDefinition:
5343  * @ctxt:  a schema parser context
5344  * @schema:  the schema being built
5345  * @name:  the item name
5346  * @nsName:  the target namespace
5347  * @node: the corresponding node
5348  *
5349  * Add an XML schema Attribute Group definition.
5350  *
5351  * Returns the new structure or NULL in case of error
5352  */
5353 static xmlSchemaAttributeGroupPtr
xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema ATTRIBUTE_UNUSED,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node)5354 xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
5355                            xmlSchemaPtr schema ATTRIBUTE_UNUSED,
5356 			   const xmlChar *name,
5357 			   const xmlChar *nsName,
5358 			   xmlNodePtr node)
5359 {
5360     xmlSchemaAttributeGroupPtr ret = NULL;
5361 
5362     if ((pctxt == NULL) || (name == NULL))
5363         return (NULL);
5364 
5365     ret = (xmlSchemaAttributeGroupPtr)
5366         xmlMalloc(sizeof(xmlSchemaAttributeGroup));
5367     if (ret == NULL) {
5368 	xmlSchemaPErrMemory(pctxt, "allocating attribute group", NULL);
5369 	return (NULL);
5370     }
5371     memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
5372     ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5373     ret->name = name;
5374     ret->targetNamespace = nsName;
5375     ret->node = node;
5376 
5377     /* TODO: Remove the flag. */
5378     ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5379     if (pctxt->isRedefine) {
5380 	pctxt->redef = xmlSchemaAddRedef(pctxt, pctxt->redefined,
5381 	    ret, name, nsName);
5382 	if (pctxt->redef == NULL) {
5383 	    xmlFree(ret);
5384 	    return(NULL);
5385 	}
5386 	pctxt->redefCounter = 0;
5387     }
5388     WXS_ADD_GLOBAL(pctxt, ret);
5389     WXS_ADD_PENDING(pctxt, ret);
5390     return (ret);
5391 }
5392 
5393 /**
5394  * xmlSchemaAddElement:
5395  * @ctxt:  a schema parser context
5396  * @schema:  the schema being built
5397  * @name:  the type name
5398  * @namespace:  the type namespace
5399  *
5400  * Add an XML schema Element declaration
5401  * *WARNING* this interface is highly subject to change
5402  *
5403  * Returns the new structure or NULL in case of error
5404  */
5405 static xmlSchemaElementPtr
xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node,int topLevel)5406 xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt,
5407                     const xmlChar * name, const xmlChar * nsName,
5408 		    xmlNodePtr node, int topLevel)
5409 {
5410     xmlSchemaElementPtr ret = NULL;
5411 
5412     if ((ctxt == NULL) || (name == NULL))
5413         return (NULL);
5414 
5415     ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
5416     if (ret == NULL) {
5417         xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
5418         return (NULL);
5419     }
5420     memset(ret, 0, sizeof(xmlSchemaElement));
5421     ret->type = XML_SCHEMA_TYPE_ELEMENT;
5422     ret->name = name;
5423     ret->targetNamespace = nsName;
5424     ret->node = node;
5425 
5426     if (topLevel)
5427 	WXS_ADD_GLOBAL(ctxt, ret);
5428     else
5429 	WXS_ADD_LOCAL(ctxt, ret);
5430     WXS_ADD_PENDING(ctxt, ret);
5431     return (ret);
5432 }
5433 
5434 /**
5435  * xmlSchemaAddType:
5436  * @ctxt:  a schema parser context
5437  * @schema:  the schema being built
5438  * @name:  the item name
5439  * @namespace:  the namespace
5440  *
5441  * Add an XML schema item
5442  * *WARNING* this interface is highly subject to change
5443  *
5444  * Returns the new structure or NULL in case of error
5445  */
5446 static xmlSchemaTypePtr
xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaTypeType type,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node,int topLevel)5447 xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5448 		 xmlSchemaTypeType type,
5449                  const xmlChar * name, const xmlChar * nsName,
5450 		 xmlNodePtr node, int topLevel)
5451 {
5452     xmlSchemaTypePtr ret = NULL;
5453 
5454     if ((ctxt == NULL) || (schema == NULL))
5455         return (NULL);
5456 
5457     ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
5458     if (ret == NULL) {
5459         xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
5460         return (NULL);
5461     }
5462     memset(ret, 0, sizeof(xmlSchemaType));
5463     ret->type = type;
5464     ret->name = name;
5465     ret->targetNamespace = nsName;
5466     ret->node = node;
5467     if (topLevel) {
5468 	if (ctxt->isRedefine) {
5469 	    ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5470 		ret, name, nsName);
5471 	    if (ctxt->redef == NULL) {
5472 		xmlFree(ret);
5473 		return(NULL);
5474 	    }
5475 	    ctxt->redefCounter = 0;
5476 	}
5477 	WXS_ADD_GLOBAL(ctxt, ret);
5478     } else
5479 	WXS_ADD_LOCAL(ctxt, ret);
5480     WXS_ADD_PENDING(ctxt, ret);
5481     return (ret);
5482 }
5483 
5484 static xmlSchemaQNameRefPtr
xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypeType refType,const xmlChar * refName,const xmlChar * refNs)5485 xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt,
5486 		     xmlSchemaTypeType refType,
5487 		     const xmlChar *refName,
5488 		     const xmlChar *refNs)
5489 {
5490     xmlSchemaQNameRefPtr ret;
5491 
5492     ret = (xmlSchemaQNameRefPtr)
5493 	xmlMalloc(sizeof(xmlSchemaQNameRef));
5494     if (ret == NULL) {
5495 	xmlSchemaPErrMemory(pctxt,
5496 	    "allocating QName reference item", NULL);
5497 	return (NULL);
5498     }
5499     ret->node = NULL;
5500     ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
5501     ret->name = refName;
5502     ret->targetNamespace = refNs;
5503     ret->item = NULL;
5504     ret->itemType = refType;
5505     /*
5506     * Store the reference item in the schema.
5507     */
5508     WXS_ADD_LOCAL(pctxt, ret);
5509     return (ret);
5510 }
5511 
5512 static xmlSchemaAttributeUseProhibPtr
xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt)5513 xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt)
5514 {
5515     xmlSchemaAttributeUseProhibPtr ret;
5516 
5517     ret = (xmlSchemaAttributeUseProhibPtr)
5518 	xmlMalloc(sizeof(xmlSchemaAttributeUseProhib));
5519     if (ret == NULL) {
5520 	xmlSchemaPErrMemory(pctxt,
5521 	    "allocating attribute use prohibition", NULL);
5522 	return (NULL);
5523     }
5524     memset(ret, 0, sizeof(xmlSchemaAttributeUseProhib));
5525     ret->type = XML_SCHEMA_EXTRA_ATTR_USE_PROHIB;
5526     WXS_ADD_LOCAL(pctxt, ret);
5527     return (ret);
5528 }
5529 
5530 
5531 /**
5532  * xmlSchemaAddModelGroup:
5533  * @ctxt:  a schema parser context
5534  * @schema:  the schema being built
5535  * @type: the "compositor" type of the model group
5536  * @node: the node in the schema doc
5537  *
5538  * Adds a schema model group
5539  * *WARNING* this interface is highly subject to change
5540  *
5541  * Returns the new structure or NULL in case of error
5542  */
5543 static xmlSchemaModelGroupPtr
xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaTypeType type,xmlNodePtr node)5544 xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt,
5545 		       xmlSchemaPtr schema,
5546 		       xmlSchemaTypeType type,
5547 		       xmlNodePtr node)
5548 {
5549     xmlSchemaModelGroupPtr ret = NULL;
5550 
5551     if ((ctxt == NULL) || (schema == NULL))
5552         return (NULL);
5553 
5554     ret = (xmlSchemaModelGroupPtr)
5555 	xmlMalloc(sizeof(xmlSchemaModelGroup));
5556     if (ret == NULL) {
5557 	xmlSchemaPErrMemory(ctxt, "allocating model group component",
5558 	    NULL);
5559 	return (NULL);
5560     }
5561     memset(ret, 0, sizeof(xmlSchemaModelGroup));
5562     ret->type = type;
5563     ret->node = node;
5564     WXS_ADD_LOCAL(ctxt, ret);
5565     if ((type == XML_SCHEMA_TYPE_SEQUENCE) ||
5566 	(type == XML_SCHEMA_TYPE_CHOICE))
5567 	WXS_ADD_PENDING(ctxt, ret);
5568     return (ret);
5569 }
5570 
5571 
5572 /**
5573  * xmlSchemaAddParticle:
5574  * @ctxt:  a schema parser context
5575  * @schema:  the schema being built
5576  * @node: the corresponding node in the schema doc
5577  * @min: the minOccurs
5578  * @max: the maxOccurs
5579  *
5580  * Adds an XML schema particle component.
5581  * *WARNING* this interface is highly subject to change
5582  *
5583  * Returns the new structure or NULL in case of error
5584  */
5585 static xmlSchemaParticlePtr
xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int min,int max)5586 xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt,
5587 		     xmlNodePtr node, int min, int max)
5588 {
5589     xmlSchemaParticlePtr ret = NULL;
5590     if (ctxt == NULL)
5591         return (NULL);
5592 
5593 #ifdef DEBUG
5594     fprintf(stderr, "Adding particle component\n");
5595 #endif
5596     ret = (xmlSchemaParticlePtr)
5597 	xmlMalloc(sizeof(xmlSchemaParticle));
5598     if (ret == NULL) {
5599 	xmlSchemaPErrMemory(ctxt, "allocating particle component",
5600 	    NULL);
5601 	return (NULL);
5602     }
5603     ret->type = XML_SCHEMA_TYPE_PARTICLE;
5604     ret->annot = NULL;
5605     ret->node = node;
5606     ret->minOccurs = min;
5607     ret->maxOccurs = max;
5608     ret->next = NULL;
5609     ret->children = NULL;
5610 
5611     WXS_ADD_LOCAL(ctxt, ret);
5612     /*
5613     * Note that addition to pending components will be done locally
5614     * to the specific parsing function, since the most particles
5615     * need not to be fixed up (i.e. the reference to be resolved).
5616     * REMOVED: WXS_ADD_PENDING(ctxt, ret);
5617     */
5618     return (ret);
5619 }
5620 
5621 /**
5622  * xmlSchemaAddModelGroupDefinition:
5623  * @ctxt:  a schema validation context
5624  * @schema:  the schema being built
5625  * @name:  the group name
5626  *
5627  * Add an XML schema Group definition
5628  *
5629  * Returns the new structure or NULL in case of error
5630  */
5631 static xmlSchemaModelGroupDefPtr
xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node)5632 xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
5633 				 xmlSchemaPtr schema,
5634 				 const xmlChar *name,
5635 				 const xmlChar *nsName,
5636 				 xmlNodePtr node)
5637 {
5638     xmlSchemaModelGroupDefPtr ret = NULL;
5639 
5640     if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5641         return (NULL);
5642 
5643     ret = (xmlSchemaModelGroupDefPtr)
5644 	xmlMalloc(sizeof(xmlSchemaModelGroupDef));
5645     if (ret == NULL) {
5646         xmlSchemaPErrMemory(ctxt, "adding group", NULL);
5647         return (NULL);
5648     }
5649     memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
5650     ret->name = name;
5651     ret->type = XML_SCHEMA_TYPE_GROUP;
5652     ret->node = node;
5653     ret->targetNamespace = nsName;
5654 
5655     if (ctxt->isRedefine) {
5656 	ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5657 	    ret, name, nsName);
5658 	if (ctxt->redef == NULL) {
5659 	    xmlFree(ret);
5660 	    return(NULL);
5661 	}
5662 	ctxt->redefCounter = 0;
5663     }
5664     WXS_ADD_GLOBAL(ctxt, ret);
5665     WXS_ADD_PENDING(ctxt, ret);
5666     return (ret);
5667 }
5668 
5669 /**
5670  * xmlSchemaNewWildcardNs:
5671  * @ctxt:  a schema validation context
5672  *
5673  * Creates a new wildcard namespace constraint.
5674  *
5675  * Returns the new structure or NULL in case of error
5676  */
5677 static xmlSchemaWildcardNsPtr
xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)5678 xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
5679 {
5680     xmlSchemaWildcardNsPtr ret;
5681 
5682     ret = (xmlSchemaWildcardNsPtr)
5683 	xmlMalloc(sizeof(xmlSchemaWildcardNs));
5684     if (ret == NULL) {
5685 	xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
5686 	return (NULL);
5687     }
5688     ret->value = NULL;
5689     ret->next = NULL;
5690     return (ret);
5691 }
5692 
5693 static xmlSchemaIDCPtr
xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName,int category,xmlNodePtr node)5694 xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5695                   const xmlChar *name, const xmlChar *nsName,
5696 		  int category, xmlNodePtr node)
5697 {
5698     xmlSchemaIDCPtr ret = NULL;
5699 
5700     if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5701         return (NULL);
5702 
5703     ret = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
5704     if (ret == NULL) {
5705         xmlSchemaPErrMemory(ctxt,
5706 	    "allocating an identity-constraint definition", NULL);
5707         return (NULL);
5708     }
5709     memset(ret, 0, sizeof(xmlSchemaIDC));
5710     /* The target namespace of the parent element declaration. */
5711     ret->targetNamespace = nsName;
5712     ret->name = name;
5713     ret->type = category;
5714     ret->node = node;
5715 
5716     WXS_ADD_GLOBAL(ctxt, ret);
5717     /*
5718     * Only keyrefs need to be fixup up.
5719     */
5720     if (category == XML_SCHEMA_TYPE_IDC_KEYREF)
5721 	WXS_ADD_PENDING(ctxt, ret);
5722     return (ret);
5723 }
5724 
5725 /**
5726  * xmlSchemaAddWildcard:
5727  * @ctxt:  a schema validation context
5728  * @schema: a schema
5729  *
5730  * Adds a wildcard.
5731  * It corresponds to a xsd:anyAttribute and xsd:any.
5732  *
5733  * Returns the new structure or NULL in case of error
5734  */
5735 static xmlSchemaWildcardPtr
xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaTypeType type,xmlNodePtr node)5736 xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5737 		     xmlSchemaTypeType type, xmlNodePtr node)
5738 {
5739     xmlSchemaWildcardPtr ret = NULL;
5740 
5741     if ((ctxt == NULL) || (schema == NULL))
5742         return (NULL);
5743 
5744     ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
5745     if (ret == NULL) {
5746         xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
5747         return (NULL);
5748     }
5749     memset(ret, 0, sizeof(xmlSchemaWildcard));
5750     ret->type = type;
5751     ret->node = node;
5752     WXS_ADD_LOCAL(ctxt, ret);
5753     return (ret);
5754 }
5755 
5756 static void
xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group)5757 xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group)
5758 {
5759     if (group == NULL)
5760 	return;
5761     if (group->members != NULL)
5762 	xmlSchemaItemListFree(group->members);
5763     xmlFree(group);
5764 }
5765 
5766 static void
xmlSchemaSubstGroupFreeEntry(void * group,const xmlChar * name ATTRIBUTE_UNUSED)5767 xmlSchemaSubstGroupFreeEntry(void *group, const xmlChar *name ATTRIBUTE_UNUSED)
5768 {
5769     xmlSchemaSubstGroupFree((xmlSchemaSubstGroupPtr) group);
5770 }
5771 
5772 static xmlSchemaSubstGroupPtr
xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt,xmlSchemaElementPtr head)5773 xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt,
5774 		       xmlSchemaElementPtr head)
5775 {
5776     xmlSchemaSubstGroupPtr ret;
5777 
5778     /* Init subst group hash. */
5779     if (WXS_SUBST_GROUPS(pctxt) == NULL) {
5780 	WXS_SUBST_GROUPS(pctxt) = xmlHashCreateDict(10, pctxt->dict);
5781 	if (WXS_SUBST_GROUPS(pctxt) == NULL)
5782 	    return(NULL);
5783     }
5784     /* Create a new substitution group. */
5785     ret = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
5786     if (ret == NULL) {
5787 	xmlSchemaPErrMemory(NULL,
5788 	    "allocating a substitution group container", NULL);
5789 	return(NULL);
5790     }
5791     memset(ret, 0, sizeof(xmlSchemaSubstGroup));
5792     ret->head = head;
5793     /* Create list of members. */
5794     ret->members = xmlSchemaItemListCreate();
5795     if (ret->members == NULL) {
5796 	xmlSchemaSubstGroupFree(ret);
5797 	return(NULL);
5798     }
5799     /* Add subst group to hash. */
5800     if (xmlHashAddEntry2(WXS_SUBST_GROUPS(pctxt),
5801 	head->name, head->targetNamespace, ret) != 0) {
5802 	PERROR_INT("xmlSchemaSubstGroupAdd",
5803 	    "failed to add a new substitution container");
5804 	xmlSchemaSubstGroupFree(ret);
5805 	return(NULL);
5806     }
5807     return(ret);
5808 }
5809 
5810 static xmlSchemaSubstGroupPtr
xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt,xmlSchemaElementPtr head)5811 xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt,
5812 		       xmlSchemaElementPtr head)
5813 {
5814     if (WXS_SUBST_GROUPS(pctxt) == NULL)
5815 	return(NULL);
5816     return(xmlHashLookup2(WXS_SUBST_GROUPS(pctxt),
5817 	head->name, head->targetNamespace));
5818 
5819 }
5820 
5821 /**
5822  * xmlSchemaAddElementSubstitutionMember:
5823  * @pctxt:  a schema parser context
5824  * @head:  the head of the substitution group
5825  * @member: the new member of the substitution group
5826  *
5827  * Allocate a new annotation structure.
5828  *
5829  * Returns the newly allocated structure or NULL in case or error
5830  */
5831 static int
xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,xmlSchemaElementPtr head,xmlSchemaElementPtr member)5832 xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
5833 				      xmlSchemaElementPtr head,
5834 				      xmlSchemaElementPtr member)
5835 {
5836     xmlSchemaSubstGroupPtr substGroup = NULL;
5837 
5838     if ((pctxt == NULL) || (head == NULL) || (member == NULL))
5839 	return (-1);
5840 
5841     substGroup = xmlSchemaSubstGroupGet(pctxt, head);
5842     if (substGroup == NULL)
5843 	substGroup = xmlSchemaSubstGroupAdd(pctxt, head);
5844     if (substGroup == NULL)
5845 	return(-1);
5846     if (xmlSchemaItemListAdd(substGroup->members, member) == -1)
5847 	return(-1);
5848     return(0);
5849 }
5850 
5851 /************************************************************************
5852  *									*
5853  *		Utilities for parsing					*
5854  *									*
5855  ************************************************************************/
5856 
5857 /**
5858  * xmlSchemaPValAttrNodeQNameValue:
5859  * @ctxt:  a schema parser context
5860  * @schema: the schema context
5861  * @ownerItem: the parent as a schema object
5862  * @value:  the QName value
5863  * @uri:  the resulting namespace URI if found
5864  * @local: the resulting local part if found, the attribute value otherwise
5865  *
5866  * Extracts the local name and the URI of a QName value and validates it.
5867  * This one is intended to be used on attribute values that
5868  * should resolve to schema components.
5869  *
5870  * Returns 0, in case the QName is valid, a positive error code
5871  * if not valid and -1 if an internal error occurs.
5872  */
5873 static int
xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,const xmlChar * value,const xmlChar ** uri,const xmlChar ** local)5874 xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
5875 				       xmlSchemaPtr schema,
5876 				       xmlSchemaBasicItemPtr ownerItem,
5877 				       xmlAttrPtr attr,
5878 				       const xmlChar *value,
5879 				       const xmlChar **uri,
5880 				       const xmlChar **local)
5881 {
5882     const xmlChar *pref;
5883     xmlNsPtr ns;
5884     int len, ret;
5885 
5886     *uri = NULL;
5887     *local = NULL;
5888     ret = xmlValidateQName(value, 1);
5889     if (ret > 0) {
5890 	xmlSchemaPSimpleTypeErr(ctxt,
5891 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5892 	    ownerItem, (xmlNodePtr) attr,
5893 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
5894 	    NULL, value, NULL, NULL, NULL);
5895 	*local = value;
5896 	return (ctxt->err);
5897     } else if (ret < 0)
5898 	return (-1);
5899 
5900     if (!strchr((char *) value, ':')) {
5901 	ns = xmlSearchNs(attr->doc, attr->parent, NULL);
5902 	if (ns && ns->href && ns->href[0])
5903 	    *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5904 	else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
5905 	    /* TODO: move XML_SCHEMAS_INCLUDING_CONVERT_NS to the
5906 	    * parser context. */
5907 	    /*
5908 	    * This one takes care of included schemas with no
5909 	    * target namespace.
5910 	    */
5911 	    *uri = ctxt->targetNamespace;
5912 	}
5913 	*local = xmlDictLookup(ctxt->dict, value, -1);
5914 	return (0);
5915     }
5916     /*
5917     * At this point xmlSplitQName3 has to return a local name.
5918     */
5919     *local = xmlSplitQName3(value, &len);
5920     *local = xmlDictLookup(ctxt->dict, *local, -1);
5921     pref = xmlDictLookup(ctxt->dict, value, len);
5922     ns = xmlSearchNs(attr->doc, attr->parent, pref);
5923     if (ns == NULL) {
5924 	xmlSchemaPSimpleTypeErr(ctxt,
5925 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5926 	    ownerItem, (xmlNodePtr) attr,
5927 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
5928 	    "The value '%s' of simple type 'xs:QName' has no "
5929 	    "corresponding namespace declaration in scope", value, NULL);
5930 	return (ctxt->err);
5931     } else {
5932         *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5933     }
5934     return (0);
5935 }
5936 
5937 /**
5938  * xmlSchemaPValAttrNodeQName:
5939  * @ctxt:  a schema parser context
5940  * @schema: the schema context
5941  * @ownerItem: the owner as a schema object
5942  * @attr:  the attribute node
5943  * @uri:  the resulting namespace URI if found
5944  * @local: the resulting local part if found, the attribute value otherwise
5945  *
5946  * Extracts and validates the QName of an attribute value.
5947  * This one is intended to be used on attribute values that
5948  * should resolve to schema components.
5949  *
5950  * Returns 0, in case the QName is valid, a positive error code
5951  * if not valid and -1 if an internal error occurs.
5952  */
5953 static int
xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,const xmlChar ** uri,const xmlChar ** local)5954 xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
5955 				       xmlSchemaPtr schema,
5956 				       xmlSchemaBasicItemPtr ownerItem,
5957 				       xmlAttrPtr attr,
5958 				       const xmlChar **uri,
5959 				       const xmlChar **local)
5960 {
5961     const xmlChar *value;
5962 
5963     value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5964     return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
5965 	ownerItem, attr, value, uri, local));
5966 }
5967 
5968 /**
5969  * xmlSchemaPValAttrQName:
5970  * @ctxt:  a schema parser context
5971  * @schema: the schema context
5972  * @ownerItem: the owner as a schema object
5973  * @ownerElem:  the parent node of the attribute
5974  * @name:  the name of the attribute
5975  * @uri:  the resulting namespace URI if found
5976  * @local: the resulting local part if found, the attribute value otherwise
5977  *
5978  * Extracts and validates the QName of an attribute value.
5979  *
5980  * Returns 0, in case the QName is valid, a positive error code
5981  * if not valid and -1 if an internal error occurs.
5982  */
5983 static int
xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaBasicItemPtr ownerItem,xmlNodePtr ownerElem,const char * name,const xmlChar ** uri,const xmlChar ** local)5984 xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5985 				   xmlSchemaPtr schema,
5986 				   xmlSchemaBasicItemPtr ownerItem,
5987 				   xmlNodePtr ownerElem,
5988 				   const char *name,
5989 				   const xmlChar **uri,
5990 				   const xmlChar **local)
5991 {
5992     xmlAttrPtr attr;
5993 
5994     attr = xmlSchemaGetPropNode(ownerElem, name);
5995     if (attr == NULL) {
5996 	*local = NULL;
5997 	*uri = NULL;
5998 	return (0);
5999     }
6000     return (xmlSchemaPValAttrNodeQName(ctxt, schema,
6001 	ownerItem, attr, uri, local));
6002 }
6003 
6004 /**
6005  * xmlSchemaPValAttrID:
6006  * @ctxt:  a schema parser context
6007  *
6008  * Extracts and validates the ID of an attribute value.
6009  *
6010  * Returns 0, in case the ID is valid, a positive error code
6011  * if not valid and -1 if an internal error occurs.
6012  */
6013 static int
xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt,xmlAttrPtr attr)6014 xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr)
6015 {
6016     int ret;
6017     const xmlChar *value;
6018 
6019     if (attr == NULL)
6020 	return(0);
6021     value = xmlSchemaGetNodeContentNoDict((xmlNodePtr) attr);
6022     ret = xmlValidateNCName(value, 1);
6023     if (ret == 0) {
6024 	/*
6025 	* NOTE: the IDness might have already be declared in the DTD
6026 	*/
6027 	if (attr->atype != XML_ATTRIBUTE_ID) {
6028 	    xmlIDPtr res;
6029 	    xmlChar *strip;
6030 
6031 	    /*
6032 	    * TODO: Use xmlSchemaStrip here; it's not exported at this
6033 	    * moment.
6034 	    */
6035 	    strip = xmlSchemaCollapseString(value);
6036 	    if (strip != NULL) {
6037 		xmlFree((xmlChar *) value);
6038 		value = strip;
6039 	    }
6040 	    res = xmlAddID(NULL, attr->doc, value, attr);
6041 	    if (res == NULL) {
6042 		ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
6043 		xmlSchemaPSimpleTypeErr(ctxt,
6044 		    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6045 		    NULL, (xmlNodePtr) attr,
6046 		    xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
6047 		    NULL, NULL, "Duplicate value '%s' of simple "
6048 		    "type 'xs:ID'", value, NULL);
6049 	    } else
6050 		attr->atype = XML_ATTRIBUTE_ID;
6051 	}
6052     } else if (ret > 0) {
6053 	ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
6054 	xmlSchemaPSimpleTypeErr(ctxt,
6055 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6056 	    NULL, (xmlNodePtr) attr,
6057 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
6058 	    NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
6059 	    "not a valid 'xs:NCName'",
6060 	    value, NULL);
6061     }
6062     if (value != NULL)
6063 	xmlFree((xmlChar *)value);
6064 
6065     return (ret);
6066 }
6067 
6068 static int
xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr ownerElem,const xmlChar * name)6069 xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
6070 		    xmlNodePtr ownerElem,
6071 		    const xmlChar *name)
6072 {
6073     xmlAttrPtr attr;
6074 
6075     attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
6076     if (attr == NULL)
6077 	return(0);
6078     return(xmlSchemaPValAttrNodeID(ctxt, attr));
6079 
6080 }
6081 
6082 /**
6083  * xmlGetMaxOccurs:
6084  * @ctxt:  a schema validation context
6085  * @node:  a subtree containing XML Schema information
6086  *
6087  * Get the maxOccurs property
6088  *
6089  * Returns the default if not found, or the value
6090  */
6091 static int
xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int min,int max,int def,const char * expected)6092 xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
6093 		int min, int max, int def, const char *expected)
6094 {
6095     const xmlChar *val, *cur;
6096     int ret = 0;
6097     xmlAttrPtr attr;
6098 
6099     attr = xmlSchemaGetPropNode(node, "maxOccurs");
6100     if (attr == NULL)
6101 	return (def);
6102     val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6103 
6104     if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
6105 	if (max != UNBOUNDED) {
6106 	    xmlSchemaPSimpleTypeErr(ctxt,
6107 		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6108 		/* XML_SCHEMAP_INVALID_MINOCCURS, */
6109 		NULL, (xmlNodePtr) attr, NULL, expected,
6110 		val, NULL, NULL, NULL);
6111 	    return (def);
6112 	} else
6113 	    return (UNBOUNDED);  /* encoding it with -1 might be another option */
6114     }
6115 
6116     cur = val;
6117     while (IS_BLANK_CH(*cur))
6118         cur++;
6119     if (*cur == 0) {
6120         xmlSchemaPSimpleTypeErr(ctxt,
6121 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6122 	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
6123 	    NULL, (xmlNodePtr) attr, NULL, expected,
6124 	    val, NULL, NULL, NULL);
6125 	return (def);
6126     }
6127     while ((*cur >= '0') && (*cur <= '9')) {
6128         if (ret > INT_MAX / 10) {
6129             ret = INT_MAX;
6130         } else {
6131             int digit = *cur - '0';
6132             ret *= 10;
6133             if (ret > INT_MAX - digit)
6134                 ret = INT_MAX;
6135             else
6136                 ret += digit;
6137         }
6138         cur++;
6139     }
6140     while (IS_BLANK_CH(*cur))
6141         cur++;
6142     /*
6143     * TODO: Restrict the maximal value to Integer.
6144     */
6145     if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
6146 	xmlSchemaPSimpleTypeErr(ctxt,
6147 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6148 	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
6149 	    NULL, (xmlNodePtr) attr, NULL, expected,
6150 	    val, NULL, NULL, NULL);
6151         return (def);
6152     }
6153     return (ret);
6154 }
6155 
6156 /**
6157  * xmlGetMinOccurs:
6158  * @ctxt:  a schema validation context
6159  * @node:  a subtree containing XML Schema information
6160  *
6161  * Get the minOccurs property
6162  *
6163  * Returns the default if not found, or the value
6164  */
6165 static int
xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int min,int max,int def,const char * expected)6166 xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
6167 		int min, int max, int def, const char *expected)
6168 {
6169     const xmlChar *val, *cur;
6170     int ret = 0;
6171     xmlAttrPtr attr;
6172 
6173     attr = xmlSchemaGetPropNode(node, "minOccurs");
6174     if (attr == NULL)
6175 	return (def);
6176     val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6177     cur = val;
6178     while (IS_BLANK_CH(*cur))
6179         cur++;
6180     if (*cur == 0) {
6181         xmlSchemaPSimpleTypeErr(ctxt,
6182 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6183 	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
6184 	    NULL, (xmlNodePtr) attr, NULL, expected,
6185 	    val, NULL, NULL, NULL);
6186         return (def);
6187     }
6188     while ((*cur >= '0') && (*cur <= '9')) {
6189         if (ret > INT_MAX / 10) {
6190             ret = INT_MAX;
6191         } else {
6192             int digit = *cur - '0';
6193             ret *= 10;
6194             if (ret > INT_MAX - digit)
6195                 ret = INT_MAX;
6196             else
6197                 ret += digit;
6198         }
6199         cur++;
6200     }
6201     while (IS_BLANK_CH(*cur))
6202         cur++;
6203     /*
6204     * TODO: Restrict the maximal value to Integer.
6205     */
6206     if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
6207 	xmlSchemaPSimpleTypeErr(ctxt,
6208 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6209 	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
6210 	    NULL, (xmlNodePtr) attr, NULL, expected,
6211 	    val, NULL, NULL, NULL);
6212         return (def);
6213     }
6214     return (ret);
6215 }
6216 
6217 /**
6218  * xmlSchemaPGetBoolNodeValue:
6219  * @ctxt:  a schema validation context
6220  * @ownerItem:  the owner as a schema item
6221  * @node: the node holding the value
6222  *
6223  * Converts a boolean string value into 1 or 0.
6224  *
6225  * Returns 0 or 1.
6226  */
6227 static int
xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,xmlSchemaBasicItemPtr ownerItem,xmlNodePtr node)6228 xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
6229 			   xmlSchemaBasicItemPtr ownerItem,
6230 			   xmlNodePtr node)
6231 {
6232     xmlChar *value = NULL;
6233     int res = 0;
6234 
6235     value = xmlNodeGetContent(node);
6236     /*
6237     * 3.2.2.1 Lexical representation
6238     * An instance of a datatype that is defined as `boolean`
6239     * can have the following legal literals {true, false, 1, 0}.
6240     */
6241     if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
6242         res = 1;
6243     else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
6244         res = 0;
6245     else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
6246 	res = 1;
6247     else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
6248         res = 0;
6249     else {
6250         xmlSchemaPSimpleTypeErr(ctxt,
6251 	    XML_SCHEMAP_INVALID_BOOLEAN,
6252 	    ownerItem, node,
6253 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6254 	    NULL, BAD_CAST value,
6255 	    NULL, NULL, NULL);
6256     }
6257     if (value != NULL)
6258 	xmlFree(value);
6259     return (res);
6260 }
6261 
6262 /**
6263  * xmlGetBooleanProp:
6264  * @ctxt:  a schema validation context
6265  * @node:  a subtree containing XML Schema information
6266  * @name:  the attribute name
6267  * @def:  the default value
6268  *
6269  * Evaluate if a boolean property is set
6270  *
6271  * Returns the default if not found, 0 if found to be false,
6272  * 1 if found to be true
6273  */
6274 static int
xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,const char * name,int def)6275 xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
6276 		  xmlNodePtr node,
6277                   const char *name, int def)
6278 {
6279     const xmlChar *val;
6280 
6281     val = xmlSchemaGetProp(ctxt, node, name);
6282     if (val == NULL)
6283         return (def);
6284     /*
6285     * 3.2.2.1 Lexical representation
6286     * An instance of a datatype that is defined as `boolean`
6287     * can have the following legal literals {true, false, 1, 0}.
6288     */
6289     if (xmlStrEqual(val, BAD_CAST "true"))
6290         def = 1;
6291     else if (xmlStrEqual(val, BAD_CAST "false"))
6292         def = 0;
6293     else if (xmlStrEqual(val, BAD_CAST "1"))
6294 	def = 1;
6295     else if (xmlStrEqual(val, BAD_CAST "0"))
6296         def = 0;
6297     else {
6298         xmlSchemaPSimpleTypeErr(ctxt,
6299 	    XML_SCHEMAP_INVALID_BOOLEAN,
6300 	    NULL,
6301 	    (xmlNodePtr) xmlSchemaGetPropNode(node, name),
6302 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6303 	    NULL, val, NULL, NULL, NULL);
6304     }
6305     return (def);
6306 }
6307 
6308 /************************************************************************
6309  *									*
6310  *		Schema extraction from an Infoset			*
6311  *									*
6312  ************************************************************************/
6313 static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
6314                                                  ctxt, xmlSchemaPtr schema,
6315                                                  xmlNodePtr node,
6316 						 int topLevel);
6317 static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
6318                                                   ctxt,
6319                                                   xmlSchemaPtr schema,
6320                                                   xmlNodePtr node,
6321 						  int topLevel);
6322 static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
6323                                                   ctxt,
6324                                                   xmlSchemaPtr schema,
6325                                                   xmlNodePtr node,
6326 						  xmlSchemaTypeType parentType);
6327 static xmlSchemaBasicItemPtr
6328 xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
6329 			     xmlSchemaPtr schema,
6330 			     xmlNodePtr node,
6331 			     xmlSchemaItemListPtr uses,
6332 			     int parentType);
6333 static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
6334                                            xmlSchemaPtr schema,
6335                                            xmlNodePtr node);
6336 static xmlSchemaWildcardPtr
6337 xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6338                            xmlSchemaPtr schema, xmlNodePtr node);
6339 
6340 /**
6341  * xmlSchemaPValAttrNodeValue:
6342  *
6343  * @pctxt:  a schema parser context
6344  * @ownerItem: the schema object owner if existent
6345  * @attr:  the schema attribute node being validated
6346  * @value: the value
6347  * @type: the built-in type to be validated against
6348  *
6349  * Validates a value against the given built-in type.
6350  * This one is intended to be used internally for validation
6351  * of schema attribute values during parsing of the schema.
6352  *
6353  * Returns 0 if the value is valid, a positive error code
6354  * number otherwise and -1 in case of an internal or API error.
6355  */
6356 static int
xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,const xmlChar * value,xmlSchemaTypePtr type)6357 xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
6358 			   xmlSchemaBasicItemPtr ownerItem,
6359 			   xmlAttrPtr attr,
6360 			   const xmlChar *value,
6361 			   xmlSchemaTypePtr type)
6362 {
6363 
6364     int ret = 0;
6365 
6366     /*
6367     * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
6368     * one is really meant to be used internally, so better not.
6369     */
6370     if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
6371 	return (-1);
6372     if (type->type != XML_SCHEMA_TYPE_BASIC) {
6373 	PERROR_INT("xmlSchemaPValAttrNodeValue",
6374 	    "the given type is not a built-in type");
6375 	return (-1);
6376     }
6377     switch (type->builtInType) {
6378 	case XML_SCHEMAS_NCNAME:
6379 	case XML_SCHEMAS_QNAME:
6380 	case XML_SCHEMAS_ANYURI:
6381 	case XML_SCHEMAS_TOKEN:
6382 	case XML_SCHEMAS_LANGUAGE:
6383 	    ret = xmlSchemaValPredefTypeNode(type, value, NULL,
6384 		(xmlNodePtr) attr);
6385 	    break;
6386 	default: {
6387 	    PERROR_INT("xmlSchemaPValAttrNodeValue",
6388 		"validation using the given type is not supported while "
6389 		"parsing a schema");
6390 	    return (-1);
6391 	}
6392     }
6393     /*
6394     * TODO: Should we use the S4S error codes instead?
6395     */
6396     if (ret < 0) {
6397 	PERROR_INT("xmlSchemaPValAttrNodeValue",
6398 	    "failed to validate a schema attribute value");
6399 	return (-1);
6400     } else if (ret > 0) {
6401 	if (WXS_IS_LIST(type))
6402 	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
6403 	else
6404 	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
6405 	xmlSchemaPSimpleTypeErr(pctxt,
6406 	    ret, ownerItem, (xmlNodePtr) attr,
6407 	    type, NULL, value, NULL, NULL, NULL);
6408     }
6409     return (ret);
6410 }
6411 
6412 /**
6413  * xmlSchemaPValAttrNode:
6414  *
6415  * @ctxt:  a schema parser context
6416  * @ownerItem: the schema object owner if existent
6417  * @attr:  the schema attribute node being validated
6418  * @type: the built-in type to be validated against
6419  * @value: the resulting value if any
6420  *
6421  * Extracts and validates a value against the given built-in type.
6422  * This one is intended to be used internally for validation
6423  * of schema attribute values during parsing of the schema.
6424  *
6425  * Returns 0 if the value is valid, a positive error code
6426  * number otherwise and -1 in case of an internal or API error.
6427  */
6428 static int
xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,xmlSchemaTypePtr type,const xmlChar ** value)6429 xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
6430 			   xmlSchemaBasicItemPtr ownerItem,
6431 			   xmlAttrPtr attr,
6432 			   xmlSchemaTypePtr type,
6433 			   const xmlChar **value)
6434 {
6435     const xmlChar *val;
6436 
6437     if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
6438 	return (-1);
6439 
6440     val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6441     if (value != NULL)
6442 	*value = val;
6443 
6444     return (xmlSchemaPValAttrNodeValue(ctxt, ownerItem, attr,
6445 	val, type));
6446 }
6447 
6448 /**
6449  * xmlSchemaPValAttr:
6450  *
6451  * @ctxt:  a schema parser context
6452  * @node: the element node of the attribute
6453  * @ownerItem: the schema object owner if existent
6454  * @ownerElem: the owner element node
6455  * @name:  the name of the schema attribute node
6456  * @type: the built-in type to be validated against
6457  * @value: the resulting value if any
6458  *
6459  * Extracts and validates a value against the given built-in type.
6460  * This one is intended to be used internally for validation
6461  * of schema attribute values during parsing of the schema.
6462  *
6463  * Returns 0 if the value is valid, a positive error code
6464  * number otherwise and -1 in case of an internal or API error.
6465  */
6466 static int
xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,xmlSchemaBasicItemPtr ownerItem,xmlNodePtr ownerElem,const char * name,xmlSchemaTypePtr type,const xmlChar ** value)6467 xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
6468 		       xmlSchemaBasicItemPtr ownerItem,
6469 		       xmlNodePtr ownerElem,
6470 		       const char *name,
6471 		       xmlSchemaTypePtr type,
6472 		       const xmlChar **value)
6473 {
6474     xmlAttrPtr attr;
6475 
6476     if ((ctxt == NULL) || (type == NULL)) {
6477 	if (value != NULL)
6478 	    *value = NULL;
6479 	return (-1);
6480     }
6481     if (type->type != XML_SCHEMA_TYPE_BASIC) {
6482 	if (value != NULL)
6483 	    *value = NULL;
6484 	xmlSchemaPErr(ctxt, ownerElem,
6485 	    XML_SCHEMAP_INTERNAL,
6486 	    "Internal error: xmlSchemaPValAttr, the given "
6487 	    "type '%s' is not a built-in type.\n",
6488 	    type->name, NULL);
6489 	return (-1);
6490     }
6491     attr = xmlSchemaGetPropNode(ownerElem, name);
6492     if (attr == NULL) {
6493 	if (value != NULL)
6494 	    *value = NULL;
6495 	return (0);
6496     }
6497     return (xmlSchemaPValAttrNode(ctxt, ownerItem, attr,
6498 	type, value));
6499 }
6500 
6501 static int
xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema ATTRIBUTE_UNUSED,xmlNodePtr node,xmlAttrPtr attr,const xmlChar * namespaceName)6502 xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
6503 		  xmlSchemaPtr schema ATTRIBUTE_UNUSED,
6504 		  xmlNodePtr node,
6505 		  xmlAttrPtr attr,
6506 		  const xmlChar *namespaceName)
6507 {
6508     /* TODO: Pointer comparison instead? */
6509     if (xmlStrEqual(pctxt->targetNamespace, namespaceName))
6510 	return (0);
6511     if (xmlStrEqual(xmlSchemaNs, namespaceName))
6512 	return (0);
6513     /*
6514     * Check if the referenced namespace was <import>ed.
6515     */
6516     if (WXS_BUCKET(pctxt)->relations != NULL) {
6517 	xmlSchemaSchemaRelationPtr rel;
6518 
6519 	rel = WXS_BUCKET(pctxt)->relations;
6520 	do {
6521 	    if (WXS_IS_BUCKET_IMPMAIN(rel->type) &&
6522 		xmlStrEqual(namespaceName, rel->importNamespace))
6523 		return (0);
6524 	    rel = rel->next;
6525 	} while (rel != NULL);
6526     }
6527     /*
6528     * No matching <import>ed namespace found.
6529     */
6530     {
6531 	xmlNodePtr n = (attr != NULL) ? (xmlNodePtr) attr : node;
6532 
6533 	if (namespaceName == NULL)
6534 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
6535 		XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6536 		"References from this schema to components in no "
6537 		"namespace are not allowed, since not indicated by an "
6538 		"import statement", NULL, NULL);
6539 	else
6540 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
6541 		XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6542 		"References from this schema to components in the "
6543 		"namespace '%s' are not allowed, since not indicated by an "
6544 		"import statement", namespaceName, NULL);
6545     }
6546     return (XML_SCHEMAP_SRC_RESOLVE);
6547 }
6548 
6549 /**
6550  * xmlSchemaParseLocalAttributes:
6551  * @ctxt:  a schema validation context
6552  * @schema:  the schema being built
6553  * @node:  a subtree containing XML Schema information
6554  * @type:  the hosting type where the attributes will be anchored
6555  *
6556  * Parses attribute uses and attribute declarations and
6557  * attribute group references.
6558  */
6559 static int
xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr * child,xmlSchemaItemListPtr * list,int parentType,int * hasRefs)6560 xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6561                         xmlNodePtr *child, xmlSchemaItemListPtr *list,
6562 			int parentType, int *hasRefs)
6563 {
6564     void *item;
6565 
6566     while ((IS_SCHEMA((*child), "attribute")) ||
6567            (IS_SCHEMA((*child), "attributeGroup"))) {
6568         if (IS_SCHEMA((*child), "attribute")) {
6569 	    item = xmlSchemaParseLocalAttribute(ctxt, schema, *child,
6570 		*list, parentType);
6571         } else {
6572             item = xmlSchemaParseAttributeGroupRef(ctxt, schema, *child);
6573 	    if ((item != NULL) && (hasRefs != NULL))
6574 		*hasRefs = 1;
6575         }
6576 	if (item != NULL) {
6577 	    if (*list == NULL) {
6578 		/* TODO: Customize grow factor. */
6579 		*list = xmlSchemaItemListCreate();
6580 		if (*list == NULL)
6581 		    return(-1);
6582 	    }
6583 	    if (xmlSchemaItemListAddSize(*list, 2, item) == -1)
6584 		return(-1);
6585 	}
6586         *child = (*child)->next;
6587     }
6588     return (0);
6589 }
6590 
6591 /**
6592  * xmlSchemaParseAnnotation:
6593  * @ctxt:  a schema validation context
6594  * @schema:  the schema being built
6595  * @node:  a subtree containing XML Schema information
6596  *
6597  * parse a XML schema Attribute declaration
6598  * *WARNING* this interface is highly subject to change
6599  *
6600  * Returns -1 in case of error, 0 if the declaration is improper and
6601  *         1 in case of success.
6602  */
6603 static xmlSchemaAnnotPtr
xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int needed)6604 xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int needed)
6605 {
6606     xmlSchemaAnnotPtr ret;
6607     xmlNodePtr child = NULL;
6608     xmlAttrPtr attr;
6609     int barked = 0;
6610 
6611     /*
6612     * INFO: S4S completed.
6613     */
6614     /*
6615     * id = ID
6616     * {any attributes with non-schema namespace . . .}>
6617     * Content: (appinfo | documentation)*
6618     */
6619     if ((ctxt == NULL) || (node == NULL))
6620         return (NULL);
6621     if (needed)
6622 	ret = xmlSchemaNewAnnot(ctxt, node);
6623     else
6624 	ret = NULL;
6625     attr = node->properties;
6626     while (attr != NULL) {
6627 	if (((attr->ns == NULL) &&
6628 	    (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
6629 	    ((attr->ns != NULL) &&
6630 	    xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
6631 
6632 	    xmlSchemaPIllegalAttrErr(ctxt,
6633 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6634 	}
6635 	attr = attr->next;
6636     }
6637     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6638     /*
6639     * And now for the children...
6640     */
6641     child = node->children;
6642     while (child != NULL) {
6643 	if (IS_SCHEMA(child, "appinfo")) {
6644 	    /* TODO: make available the content of "appinfo". */
6645 	    /*
6646 	    * source = anyURI
6647 	    * {any attributes with non-schema namespace . . .}>
6648 	    * Content: ({any})*
6649 	    */
6650 	    attr = child->properties;
6651 	    while (attr != NULL) {
6652 		if (((attr->ns == NULL) &&
6653 		     (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
6654 		     ((attr->ns != NULL) &&
6655 		      xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
6656 
6657 		    xmlSchemaPIllegalAttrErr(ctxt,
6658 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6659 		}
6660 		attr = attr->next;
6661 	    }
6662 	    xmlSchemaPValAttr(ctxt, NULL, child, "source",
6663 		xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
6664 	    child = child->next;
6665 	} else if (IS_SCHEMA(child, "documentation")) {
6666 	    /* TODO: make available the content of "documentation". */
6667 	    /*
6668 	    * source = anyURI
6669 	    * {any attributes with non-schema namespace . . .}>
6670 	    * Content: ({any})*
6671 	    */
6672 	    attr = child->properties;
6673 	    while (attr != NULL) {
6674 		if (attr->ns == NULL) {
6675 		    if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
6676 			xmlSchemaPIllegalAttrErr(ctxt,
6677 			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6678 		    }
6679 		} else {
6680 		    if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
6681 			(xmlStrEqual(attr->name, BAD_CAST "lang") &&
6682 			(!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
6683 
6684 			xmlSchemaPIllegalAttrErr(ctxt,
6685 			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6686 		    }
6687 		}
6688 		attr = attr->next;
6689 	    }
6690 	    /*
6691 	    * Attribute "xml:lang".
6692 	    */
6693 	    attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
6694 	    if (attr != NULL)
6695 		xmlSchemaPValAttrNode(ctxt, NULL, attr,
6696 		xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
6697 	    child = child->next;
6698 	} else {
6699 	    if (!barked)
6700 		xmlSchemaPContentErr(ctxt,
6701 		    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6702 		    NULL, node, child, NULL, "(appinfo | documentation)*");
6703 	    barked = 1;
6704 	    child = child->next;
6705 	}
6706     }
6707 
6708     return (ret);
6709 }
6710 
6711 /**
6712  * xmlSchemaParseFacet:
6713  * @ctxt:  a schema validation context
6714  * @schema:  the schema being built
6715  * @node:  a subtree containing XML Schema information
6716  *
6717  * parse a XML schema Facet declaration
6718  * *WARNING* this interface is highly subject to change
6719  *
6720  * Returns the new type structure or NULL in case of error
6721  */
6722 static xmlSchemaFacetPtr
xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)6723 xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6724                     xmlNodePtr node)
6725 {
6726     xmlSchemaFacetPtr facet;
6727     xmlNodePtr child = NULL;
6728     const xmlChar *value;
6729 
6730     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6731         return (NULL);
6732 
6733     facet = xmlSchemaNewFacet();
6734     if (facet == NULL) {
6735         xmlSchemaPErrMemory(ctxt, "allocating facet", node);
6736         return (NULL);
6737     }
6738     facet->node = node;
6739     value = xmlSchemaGetProp(ctxt, node, "value");
6740     if (value == NULL) {
6741         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
6742                        "Facet %s has no value\n", node->name, NULL);
6743         xmlSchemaFreeFacet(facet);
6744         return (NULL);
6745     }
6746     if (IS_SCHEMA(node, "minInclusive")) {
6747         facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
6748     } else if (IS_SCHEMA(node, "minExclusive")) {
6749         facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
6750     } else if (IS_SCHEMA(node, "maxInclusive")) {
6751         facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
6752     } else if (IS_SCHEMA(node, "maxExclusive")) {
6753         facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
6754     } else if (IS_SCHEMA(node, "totalDigits")) {
6755         facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
6756     } else if (IS_SCHEMA(node, "fractionDigits")) {
6757         facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
6758     } else if (IS_SCHEMA(node, "pattern")) {
6759         facet->type = XML_SCHEMA_FACET_PATTERN;
6760     } else if (IS_SCHEMA(node, "enumeration")) {
6761         facet->type = XML_SCHEMA_FACET_ENUMERATION;
6762     } else if (IS_SCHEMA(node, "whiteSpace")) {
6763         facet->type = XML_SCHEMA_FACET_WHITESPACE;
6764     } else if (IS_SCHEMA(node, "length")) {
6765         facet->type = XML_SCHEMA_FACET_LENGTH;
6766     } else if (IS_SCHEMA(node, "maxLength")) {
6767         facet->type = XML_SCHEMA_FACET_MAXLENGTH;
6768     } else if (IS_SCHEMA(node, "minLength")) {
6769         facet->type = XML_SCHEMA_FACET_MINLENGTH;
6770     } else {
6771         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
6772                        "Unknown facet type %s\n", node->name, NULL);
6773         xmlSchemaFreeFacet(facet);
6774         return (NULL);
6775     }
6776     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6777     facet->value = value;
6778     if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
6779 	(facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
6780 	const xmlChar *fixed;
6781 
6782 	fixed = xmlSchemaGetProp(ctxt, node, "fixed");
6783 	if (fixed != NULL) {
6784 	    if (xmlStrEqual(fixed, BAD_CAST "true"))
6785 		facet->fixed = 1;
6786 	}
6787     }
6788     child = node->children;
6789 
6790     if (IS_SCHEMA(child, "annotation")) {
6791         facet->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6792         child = child->next;
6793     }
6794     if (child != NULL) {
6795         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
6796                        "Facet %s has unexpected child content\n",
6797                        node->name, NULL);
6798     }
6799     return (facet);
6800 }
6801 
6802 /**
6803  * xmlSchemaParseWildcardNs:
6804  * @ctxt:  a schema parser context
6805  * @wildc:  the wildcard, already created
6806  * @node:  a subtree containing XML Schema information
6807  *
6808  * Parses the attribute "processContents" and "namespace"
6809  * of a xsd:anyAttribute and xsd:any.
6810  * *WARNING* this interface is highly subject to change
6811  *
6812  * Returns 0 if everything goes fine, a positive error code
6813  * if something is not valid and -1 if an internal error occurs.
6814  */
6815 static int
xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema ATTRIBUTE_UNUSED,xmlSchemaWildcardPtr wildc,xmlNodePtr node)6816 xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
6817 			 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
6818 			 xmlSchemaWildcardPtr wildc,
6819 			 xmlNodePtr node)
6820 {
6821     const xmlChar *pc, *ns, *dictnsItem;
6822     int ret = 0;
6823     xmlChar *nsItem;
6824     xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
6825     xmlAttrPtr attr;
6826 
6827     pc = xmlSchemaGetProp(ctxt, node, "processContents");
6828     if ((pc == NULL)
6829         || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
6830         wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6831     } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
6832         wildc->processContents = XML_SCHEMAS_ANY_SKIP;
6833     } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
6834         wildc->processContents = XML_SCHEMAS_ANY_LAX;
6835     } else {
6836         xmlSchemaPSimpleTypeErr(ctxt,
6837 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6838 	    NULL, node,
6839 	    NULL, "(strict | skip | lax)", pc,
6840 	    NULL, NULL, NULL);
6841         wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6842 	ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
6843     }
6844     /*
6845      * Build the namespace constraints.
6846      */
6847     attr = xmlSchemaGetPropNode(node, "namespace");
6848     ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6849     if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
6850 	wildc->any = 1;
6851     else if (xmlStrEqual(ns, BAD_CAST "##other")) {
6852 	wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
6853 	if (wildc->negNsSet == NULL) {
6854 	    return (-1);
6855 	}
6856 	wildc->negNsSet->value = ctxt->targetNamespace;
6857     } else {
6858 	const xmlChar *end, *cur;
6859 
6860 	cur = ns;
6861 	do {
6862 	    while (IS_BLANK_CH(*cur))
6863 		cur++;
6864 	    end = cur;
6865 	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6866 		end++;
6867 	    if (end == cur)
6868 		break;
6869 	    nsItem = xmlStrndup(cur, end - cur);
6870 	    if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
6871 		    (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
6872 		xmlSchemaPSimpleTypeErr(ctxt,
6873 		    XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
6874 		    NULL, (xmlNodePtr) attr,
6875 		    NULL,
6876 		    "((##any | ##other) | List of (xs:anyURI | "
6877 		    "(##targetNamespace | ##local)))",
6878 		    nsItem, NULL, NULL, NULL);
6879 		ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
6880 	    } else {
6881 		if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
6882 		    dictnsItem = ctxt->targetNamespace;
6883 		} else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
6884 		    dictnsItem = NULL;
6885 		} else {
6886 		    /*
6887 		    * Validate the item (anyURI).
6888 		    */
6889 		    xmlSchemaPValAttrNodeValue(ctxt, NULL, attr,
6890 			nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
6891 		    dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
6892 		}
6893 		/*
6894 		* Avoid duplicate namespaces.
6895 		*/
6896 		tmp = wildc->nsSet;
6897 		while (tmp != NULL) {
6898 		    if (dictnsItem == tmp->value)
6899 			break;
6900 		    tmp = tmp->next;
6901 		}
6902 		if (tmp == NULL) {
6903 		    tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
6904 		    if (tmp == NULL) {
6905 			xmlFree(nsItem);
6906 			return (-1);
6907 		    }
6908 		    tmp->value = dictnsItem;
6909 		    tmp->next = NULL;
6910 		    if (wildc->nsSet == NULL)
6911 			wildc->nsSet = tmp;
6912 		    else if (lastNs != NULL)
6913 			lastNs->next = tmp;
6914 		    lastNs = tmp;
6915 		}
6916 
6917 	    }
6918 	    xmlFree(nsItem);
6919 	    cur = end;
6920 	} while (*cur != 0);
6921     }
6922     return (ret);
6923 }
6924 
6925 static int
xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,xmlNodePtr node,int minOccurs,int maxOccurs)6926 xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
6927 				 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
6928 				 xmlNodePtr node,
6929 				 int minOccurs,
6930 				 int maxOccurs) {
6931 
6932     if ((maxOccurs == 0) && ( minOccurs == 0))
6933 	return (0);
6934     if (maxOccurs != UNBOUNDED) {
6935 	/*
6936 	* TODO: Maybe we should better not create the particle,
6937 	* if min/max is invalid, since it could confuse the build of the
6938 	* content model.
6939 	*/
6940 	/*
6941 	* 3.9.6 Schema Component Constraint: Particle Correct
6942 	*
6943 	*/
6944 	if (maxOccurs < 1) {
6945 	    /*
6946 	    * 2.2 {max occurs} must be greater than or equal to 1.
6947 	    */
6948 	    xmlSchemaPCustomAttrErr(ctxt,
6949 		XML_SCHEMAP_P_PROPS_CORRECT_2_2,
6950 		NULL, NULL,
6951 		xmlSchemaGetPropNode(node, "maxOccurs"),
6952 		"The value must be greater than or equal to 1");
6953 	    return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6954 	} else if (minOccurs > maxOccurs) {
6955 	    /*
6956 	    * 2.1 {min occurs} must not be greater than {max occurs}.
6957 	    */
6958 	    xmlSchemaPCustomAttrErr(ctxt,
6959 		XML_SCHEMAP_P_PROPS_CORRECT_2_1,
6960 		NULL, NULL,
6961 		xmlSchemaGetPropNode(node, "minOccurs"),
6962 		"The value must not be greater than the value of 'maxOccurs'");
6963 	    return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6964 	}
6965     }
6966     return (0);
6967 }
6968 
6969 /**
6970  * xmlSchemaParseAny:
6971  * @ctxt:  a schema validation context
6972  * @schema:  the schema being built
6973  * @node:  a subtree containing XML Schema information
6974  *
6975  * Parsea a XML schema <any> element. A particle and wildcard
6976  * will be created (except if minOccurs==maxOccurs==0, in this case
6977  * nothing will be created).
6978  * *WARNING* this interface is highly subject to change
6979  *
6980  * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
6981  */
6982 static xmlSchemaParticlePtr
xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)6983 xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6984                   xmlNodePtr node)
6985 {
6986     xmlSchemaParticlePtr particle;
6987     xmlNodePtr child = NULL;
6988     xmlSchemaWildcardPtr wild;
6989     int min, max;
6990     xmlAttrPtr attr;
6991     xmlSchemaAnnotPtr annot = NULL;
6992 
6993     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6994         return (NULL);
6995     /*
6996     * Check for illegal attributes.
6997     */
6998     attr = node->properties;
6999     while (attr != NULL) {
7000 	if (attr->ns == NULL) {
7001 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7002 		(!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
7003 		(!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
7004 	        (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
7005 		(!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
7006 		xmlSchemaPIllegalAttrErr(ctxt,
7007 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7008 	    }
7009 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7010 	    xmlSchemaPIllegalAttrErr(ctxt,
7011 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7012 	}
7013 	attr = attr->next;
7014     }
7015     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
7016     /*
7017     * minOccurs/maxOccurs.
7018     */
7019     max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
7020 	"(xs:nonNegativeInteger | unbounded)");
7021     min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
7022 	"xs:nonNegativeInteger");
7023     xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
7024     /*
7025     * Create & parse the wildcard.
7026     */
7027     wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
7028     if (wild == NULL)
7029 	return (NULL);
7030     xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
7031     /*
7032     * And now for the children...
7033     */
7034     child = node->children;
7035     if (IS_SCHEMA(child, "annotation")) {
7036         annot = xmlSchemaParseAnnotation(ctxt, child, 1);
7037         child = child->next;
7038     }
7039     if (child != NULL) {
7040 	xmlSchemaPContentErr(ctxt,
7041 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7042 	    NULL, node, child,
7043 	    NULL, "(annotation?)");
7044     }
7045     /*
7046     * No component if minOccurs==maxOccurs==0.
7047     */
7048     if ((min == 0) && (max == 0)) {
7049 	/* Don't free the wildcard, since it's already on the list. */
7050 	return (NULL);
7051     }
7052     /*
7053     * Create the particle.
7054     */
7055     particle = xmlSchemaAddParticle(ctxt, node, min, max);
7056     if (particle == NULL)
7057         return (NULL);
7058     particle->annot = annot;
7059     particle->children = (xmlSchemaTreeItemPtr) wild;
7060 
7061     return (particle);
7062 }
7063 
7064 /**
7065  * xmlSchemaParseNotation:
7066  * @ctxt:  a schema validation context
7067  * @schema:  the schema being built
7068  * @node:  a subtree containing XML Schema information
7069  *
7070  * parse a XML schema Notation declaration
7071  *
7072  * Returns the new structure or NULL in case of error
7073  */
7074 static xmlSchemaNotationPtr
xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)7075 xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
7076                        xmlNodePtr node)
7077 {
7078     const xmlChar *name;
7079     xmlSchemaNotationPtr ret;
7080     xmlNodePtr child = NULL;
7081 
7082     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7083         return (NULL);
7084     name = xmlSchemaGetProp(ctxt, node, "name");
7085     if (name == NULL) {
7086         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
7087                        "Notation has no name\n", NULL, NULL);
7088         return (NULL);
7089     }
7090     ret = xmlSchemaAddNotation(ctxt, schema, name,
7091 	ctxt->targetNamespace, node);
7092     if (ret == NULL)
7093         return (NULL);
7094     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
7095 
7096     child = node->children;
7097     if (IS_SCHEMA(child, "annotation")) {
7098         ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
7099         child = child->next;
7100     }
7101     if (child != NULL) {
7102 	xmlSchemaPContentErr(ctxt,
7103 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7104 	    NULL, node, child,
7105 	    NULL, "(annotation?)");
7106     }
7107 
7108     return (ret);
7109 }
7110 
7111 /**
7112  * xmlSchemaParseAnyAttribute:
7113  * @ctxt:  a schema validation context
7114  * @schema:  the schema being built
7115  * @node:  a subtree containing XML Schema information
7116  *
7117  * parse a XML schema AnyAttribute declaration
7118  * *WARNING* this interface is highly subject to change
7119  *
7120  * Returns a wildcard or NULL.
7121  */
7122 static xmlSchemaWildcardPtr
xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)7123 xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
7124                            xmlSchemaPtr schema, xmlNodePtr node)
7125 {
7126     xmlSchemaWildcardPtr ret;
7127     xmlNodePtr child = NULL;
7128     xmlAttrPtr attr;
7129 
7130     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7131         return (NULL);
7132 
7133     ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
7134 	node);
7135     if (ret == NULL) {
7136         return (NULL);
7137     }
7138     /*
7139     * Check for illegal attributes.
7140     */
7141     attr = node->properties;
7142     while (attr != NULL) {
7143 	if (attr->ns == NULL) {
7144 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7145 	        (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
7146 		(!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
7147 		xmlSchemaPIllegalAttrErr(ctxt,
7148 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7149 	    }
7150 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7151 	    xmlSchemaPIllegalAttrErr(ctxt,
7152 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7153 	}
7154 	attr = attr->next;
7155     }
7156     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
7157     /*
7158     * Parse the namespace list.
7159     */
7160     if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
7161 	return (NULL);
7162     /*
7163     * And now for the children...
7164     */
7165     child = node->children;
7166     if (IS_SCHEMA(child, "annotation")) {
7167         ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
7168         child = child->next;
7169     }
7170     if (child != NULL) {
7171 	xmlSchemaPContentErr(ctxt,
7172 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7173 	    NULL, node, child,
7174 	    NULL, "(annotation?)");
7175     }
7176 
7177     return (ret);
7178 }
7179 
7180 
7181 /**
7182  * xmlSchemaParseAttribute:
7183  * @ctxt:  a schema validation context
7184  * @schema:  the schema being built
7185  * @node:  a subtree containing XML Schema information
7186  *
7187  * parse a XML schema Attribute declaration
7188  * *WARNING* this interface is highly subject to change
7189  *
7190  * Returns the attribute declaration.
7191  */
7192 static xmlSchemaBasicItemPtr
xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlSchemaItemListPtr uses,int parentType)7193 xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
7194 			     xmlSchemaPtr schema,
7195 			     xmlNodePtr node,
7196 			     xmlSchemaItemListPtr uses,
7197 			     int parentType)
7198 {
7199     const xmlChar *attrValue, *name = NULL, *ns = NULL;
7200     xmlSchemaAttributeUsePtr use = NULL;
7201     xmlNodePtr child = NULL;
7202     xmlAttrPtr attr;
7203     const xmlChar *tmpNs = NULL, *tmpName = NULL, *defValue = NULL;
7204     int isRef = 0, occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7205     int	nberrors, hasForm = 0, defValueType = 0;
7206 
7207 #define WXS_ATTR_DEF_VAL_DEFAULT 1
7208 #define WXS_ATTR_DEF_VAL_FIXED 2
7209 
7210     /*
7211      * 3.2.3 Constraints on XML Representations of Attribute Declarations
7212      */
7213 
7214     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7215         return (NULL);
7216     attr = xmlSchemaGetPropNode(node, "ref");
7217     if (attr != NULL) {
7218 	if (xmlSchemaPValAttrNodeQName(pctxt, schema,
7219 	    NULL, attr, &tmpNs, &tmpName) != 0) {
7220 	    return (NULL);
7221 	}
7222 	if (xmlSchemaCheckReference(pctxt, schema, node, attr, tmpNs) != 0)
7223 	    return(NULL);
7224 	isRef = 1;
7225     }
7226     nberrors = pctxt->nberrors;
7227     /*
7228     * Check for illegal attributes.
7229     */
7230     attr = node->properties;
7231     while (attr != NULL) {
7232 	if (attr->ns == NULL) {
7233 	    if (isRef) {
7234 		if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7235 		    xmlSchemaPValAttrNodeID(pctxt, attr);
7236 		    goto attr_next;
7237 		} else if (xmlStrEqual(attr->name, BAD_CAST "ref")) {
7238 		    goto attr_next;
7239 		}
7240 	    } else {
7241 		if (xmlStrEqual(attr->name, BAD_CAST "name")) {
7242 		    goto attr_next;
7243 		} else if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7244 		    xmlSchemaPValAttrNodeID(pctxt, attr);
7245 		    goto attr_next;
7246 		} else if (xmlStrEqual(attr->name, BAD_CAST "type")) {
7247 		    xmlSchemaPValAttrNodeQName(pctxt, schema, NULL,
7248 			attr, &tmpNs, &tmpName);
7249 		    goto attr_next;
7250 		} else if (xmlStrEqual(attr->name, BAD_CAST "form")) {
7251 		    /*
7252 		    * Evaluate the target namespace
7253 		    */
7254 		    hasForm = 1;
7255 		    attrValue = xmlSchemaGetNodeContent(pctxt,
7256 			(xmlNodePtr) attr);
7257 		    if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
7258 			ns = pctxt->targetNamespace;
7259 		    } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified"))
7260 		    {
7261 			xmlSchemaPSimpleTypeErr(pctxt,
7262 			    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7263 			    NULL, (xmlNodePtr) attr,
7264 			    NULL, "(qualified | unqualified)",
7265 			    attrValue, NULL, NULL, NULL);
7266 		    }
7267 		    goto attr_next;
7268 		}
7269 	    }
7270 	    if (xmlStrEqual(attr->name, BAD_CAST "use")) {
7271 
7272 		attrValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7273 		/* TODO: Maybe we need to normalize the value beforehand. */
7274 		if (xmlStrEqual(attrValue, BAD_CAST "optional"))
7275 		    occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7276 		else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
7277 		    occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
7278 		else if (xmlStrEqual(attrValue, BAD_CAST "required"))
7279 		    occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
7280 		else {
7281 		    xmlSchemaPSimpleTypeErr(pctxt,
7282 			XML_SCHEMAP_INVALID_ATTR_USE,
7283 			NULL, (xmlNodePtr) attr,
7284 			NULL, "(optional | prohibited | required)",
7285 			attrValue, NULL, NULL, NULL);
7286 		}
7287 		goto attr_next;
7288 	    } else if (xmlStrEqual(attr->name, BAD_CAST "default")) {
7289 		/*
7290 		* 3.2.3 : 1
7291 		* default and fixed must not both be present.
7292 		*/
7293 		if (defValue) {
7294 		    xmlSchemaPMutualExclAttrErr(pctxt,
7295 			XML_SCHEMAP_SRC_ATTRIBUTE_1,
7296 			NULL, attr, "default", "fixed");
7297 		} else {
7298 		    defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7299 		    defValueType = WXS_ATTR_DEF_VAL_DEFAULT;
7300 		}
7301 		goto attr_next;
7302 	    } else if (xmlStrEqual(attr->name, BAD_CAST "fixed")) {
7303 		/*
7304 		* 3.2.3 : 1
7305 		* default and fixed must not both be present.
7306 		*/
7307 		if (defValue) {
7308 		    xmlSchemaPMutualExclAttrErr(pctxt,
7309 			XML_SCHEMAP_SRC_ATTRIBUTE_1,
7310 			NULL, attr, "default", "fixed");
7311 		} else {
7312 		    defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7313 		    defValueType = WXS_ATTR_DEF_VAL_FIXED;
7314 		}
7315 		goto attr_next;
7316 	    }
7317 	} else if (! xmlStrEqual(attr->ns->href, xmlSchemaNs))
7318 	    goto attr_next;
7319 
7320 	xmlSchemaPIllegalAttrErr(pctxt,
7321 	    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7322 
7323 attr_next:
7324 	attr = attr->next;
7325     }
7326     /*
7327     * 3.2.3 : 2
7328     * If default and use are both present, use must have
7329     * the actual value optional.
7330     */
7331     if ((defValueType == WXS_ATTR_DEF_VAL_DEFAULT) &&
7332 	(occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
7333 	xmlSchemaPSimpleTypeErr(pctxt,
7334 	    XML_SCHEMAP_SRC_ATTRIBUTE_2,
7335 	    NULL, node, NULL,
7336 	    "(optional | prohibited | required)", NULL,
7337 	    "The value of the attribute 'use' must be 'optional' "
7338 	    "if the attribute 'default' is present",
7339 	    NULL, NULL);
7340     }
7341     /*
7342     * We want correct attributes.
7343     */
7344     if (nberrors != pctxt->nberrors)
7345 	return(NULL);
7346     if (! isRef) {
7347 	xmlSchemaAttributePtr attrDecl;
7348 
7349 	/* TODO: move XML_SCHEMAS_QUALIF_ATTR to the parser. */
7350 	if ((! hasForm) && (schema->flags & XML_SCHEMAS_QUALIF_ATTR))
7351 	    ns = pctxt->targetNamespace;
7352 	/*
7353 	* 3.2.6 Schema Component Constraint: xsi: Not Allowed
7354 	* TODO: Move this to the component layer.
7355 	*/
7356 	if (xmlStrEqual(ns, xmlSchemaInstanceNs)) {
7357 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
7358 		XML_SCHEMAP_NO_XSI,
7359 		node, NULL,
7360 		"The target namespace must not match '%s'",
7361 		xmlSchemaInstanceNs, NULL);
7362 	}
7363 	attr = xmlSchemaGetPropNode(node, "name");
7364 	if (attr == NULL) {
7365 	    xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7366 		NULL, node, "name", NULL);
7367 	    return (NULL);
7368 	}
7369 	if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7370 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7371 	    return (NULL);
7372 	}
7373 	/*
7374 	* 3.2.6 Schema Component Constraint: xmlns Not Allowed
7375 	* TODO: Move this to the component layer.
7376 	*/
7377 	if (xmlStrEqual(name, BAD_CAST "xmlns")) {
7378 	    xmlSchemaPSimpleTypeErr(pctxt,
7379 		XML_SCHEMAP_NO_XMLNS,
7380 		NULL, (xmlNodePtr) attr,
7381 		xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7382 		"The value of the attribute must not match 'xmlns'",
7383 		NULL, NULL);
7384 	    return (NULL);
7385 	}
7386 	if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED)
7387 	    goto check_children;
7388 	/*
7389 	* Create the attribute use component.
7390 	*/
7391 	use = xmlSchemaAddAttributeUse(pctxt, node);
7392 	if (use == NULL)
7393 	    return(NULL);
7394 	use->occurs = occurs;
7395 	/*
7396 	* Create the attribute declaration.
7397 	*/
7398 	attrDecl = xmlSchemaAddAttribute(pctxt, schema, name, ns, node, 0);
7399 	if (attrDecl == NULL)
7400 	    return (NULL);
7401 	if (tmpName != NULL) {
7402 	    attrDecl->typeName = tmpName;
7403 	    attrDecl->typeNs = tmpNs;
7404 	}
7405 	use->attrDecl = attrDecl;
7406 	/*
7407 	* Value constraint.
7408 	*/
7409 	if (defValue != NULL) {
7410 	    attrDecl->defValue = defValue;
7411 	    if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7412 		attrDecl->flags |= XML_SCHEMAS_ATTR_FIXED;
7413 	}
7414     } else if (occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7415 	xmlSchemaQNameRefPtr ref;
7416 
7417 	/*
7418 	* Create the attribute use component.
7419 	*/
7420 	use = xmlSchemaAddAttributeUse(pctxt, node);
7421 	if (use == NULL)
7422 	    return(NULL);
7423 	/*
7424 	* We need to resolve the reference at later stage.
7425 	*/
7426 	WXS_ADD_PENDING(pctxt, use);
7427 	use->occurs = occurs;
7428 	/*
7429 	* Create a QName reference to the attribute declaration.
7430 	*/
7431 	ref = xmlSchemaNewQNameRef(pctxt, XML_SCHEMA_TYPE_ATTRIBUTE,
7432 	    tmpName, tmpNs);
7433 	if (ref == NULL)
7434 	    return(NULL);
7435 	/*
7436 	* Assign the reference. This will be substituted for the
7437 	* referenced attribute declaration when the QName is resolved.
7438 	*/
7439 	use->attrDecl = WXS_ATTR_CAST ref;
7440 	/*
7441 	* Value constraint.
7442 	*/
7443 	if (defValue != NULL)
7444 	    use->defValue = defValue;
7445 	if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7446 	    use->flags |= XML_SCHEMA_ATTR_USE_FIXED;
7447     }
7448 
7449 check_children:
7450     /*
7451     * And now for the children...
7452     */
7453     child = node->children;
7454     if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7455 	xmlSchemaAttributeUseProhibPtr prohib;
7456 
7457 	if (IS_SCHEMA(child, "annotation")) {
7458 	    xmlSchemaParseAnnotation(pctxt, child, 0);
7459 	    child = child->next;
7460 	}
7461 	if (child != NULL) {
7462 	    xmlSchemaPContentErr(pctxt,
7463 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7464 		NULL, node, child, NULL,
7465 		"(annotation?)");
7466 	}
7467 	/*
7468 	* Check for pointlessness of attribute prohibitions.
7469 	*/
7470 	if (parentType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
7471 	    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7472 		XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7473 		node, NULL,
7474 		"Skipping attribute use prohibition, since it is "
7475 		"pointless inside an <attributeGroup>",
7476 		NULL, NULL, NULL);
7477 	    return(NULL);
7478 	} else if (parentType == XML_SCHEMA_TYPE_EXTENSION) {
7479 	    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7480 		XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7481 		node, NULL,
7482 		"Skipping attribute use prohibition, since it is "
7483 		"pointless when extending a type",
7484 		NULL, NULL, NULL);
7485 	    return(NULL);
7486 	}
7487 	if (! isRef) {
7488 	    tmpName = name;
7489 	    tmpNs = ns;
7490 	}
7491 	/*
7492 	* Check for duplicate attribute prohibitions.
7493 	*/
7494 	if (uses) {
7495 	    int i;
7496 
7497 	    for (i = 0; i < uses->nbItems; i++) {
7498 		use = uses->items[i];
7499 		if ((use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) &&
7500 		    (tmpName == (WXS_ATTR_PROHIB_CAST use)->name) &&
7501 		    (tmpNs == (WXS_ATTR_PROHIB_CAST use)->targetNamespace))
7502 		{
7503 		    xmlChar *str = NULL;
7504 
7505 		    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7506 			XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7507 			node, NULL,
7508 			"Skipping duplicate attribute use prohibition '%s'",
7509 			xmlSchemaFormatQName(&str, tmpNs, tmpName),
7510 			NULL, NULL);
7511 		    FREE_AND_NULL(str)
7512 		    return(NULL);
7513 		}
7514 	    }
7515 	}
7516 	/*
7517 	* Create the attribute prohibition helper component.
7518 	*/
7519 	prohib = xmlSchemaAddAttributeUseProhib(pctxt);
7520 	if (prohib == NULL)
7521 	    return(NULL);
7522 	prohib->node = node;
7523 	prohib->name = tmpName;
7524 	prohib->targetNamespace = tmpNs;
7525 	if (isRef) {
7526 	    /*
7527 	    * We need at least to resolve to the attribute declaration.
7528 	    */
7529 	    WXS_ADD_PENDING(pctxt, prohib);
7530 	}
7531 	return(WXS_BASIC_CAST prohib);
7532     } else {
7533 	if (IS_SCHEMA(child, "annotation")) {
7534 	    /*
7535 	    * TODO: Should this go into the attr decl?
7536 	    */
7537 	    use->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7538 	    child = child->next;
7539 	}
7540 	if (isRef) {
7541 	    if (child != NULL) {
7542 		if (IS_SCHEMA(child, "simpleType"))
7543 		    /*
7544 		    * 3.2.3 : 3.2
7545 		    * If ref is present, then all of <simpleType>,
7546 		    * form and type must be absent.
7547 		    */
7548 		    xmlSchemaPContentErr(pctxt,
7549 			XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
7550 			NULL, node, child, NULL,
7551 			"(annotation?)");
7552 		else
7553 		    xmlSchemaPContentErr(pctxt,
7554 			XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7555 			NULL, node, child, NULL,
7556 			"(annotation?)");
7557 	    }
7558 	} else {
7559 	    if (IS_SCHEMA(child, "simpleType")) {
7560 		if (WXS_ATTRUSE_DECL(use)->typeName != NULL) {
7561 		    /*
7562 		    * 3.2.3 : 4
7563 		    * type and <simpleType> must not both be present.
7564 		    */
7565 		    xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7566 			NULL, node, child,
7567 			"The attribute 'type' and the <simpleType> child "
7568 			"are mutually exclusive", NULL);
7569 		} else
7570 		    WXS_ATTRUSE_TYPEDEF(use) =
7571 			xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7572 		child = child->next;
7573 	    }
7574 	    if (child != NULL)
7575 		xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7576 		NULL, node, child, NULL,
7577 		"(annotation?, simpleType?)");
7578 	}
7579     }
7580     return (WXS_BASIC_CAST use);
7581 }
7582 
7583 
7584 static xmlSchemaAttributePtr
xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)7585 xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt,
7586 			      xmlSchemaPtr schema,
7587 			      xmlNodePtr node)
7588 {
7589     const xmlChar *attrValue;
7590     xmlSchemaAttributePtr ret;
7591     xmlNodePtr child = NULL;
7592     xmlAttrPtr attr;
7593 
7594     /*
7595      * Note that the w3c spec assumes the schema to be validated with schema
7596      * for schemas beforehand.
7597      *
7598      * 3.2.3 Constraints on XML Representations of Attribute Declarations
7599      */
7600     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7601         return (NULL);
7602     /*
7603     * 3.2.3 : 3.1
7604     * One of ref or name must be present, but not both
7605     */
7606     attr = xmlSchemaGetPropNode(node, "name");
7607     if (attr == NULL) {
7608 	xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7609 	    NULL, node, "name", NULL);
7610 	return (NULL);
7611     }
7612     if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7613 	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
7614 	return (NULL);
7615     }
7616     /*
7617     * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7618     * TODO: Move this to the component layer.
7619     */
7620     if (xmlStrEqual(attrValue, BAD_CAST "xmlns")) {
7621 	xmlSchemaPSimpleTypeErr(pctxt,
7622 	    XML_SCHEMAP_NO_XMLNS,
7623 	    NULL, (xmlNodePtr) attr,
7624 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7625 	    "The value of the attribute must not match 'xmlns'",
7626 	    NULL, NULL);
7627 	return (NULL);
7628     }
7629     /*
7630     * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7631     * TODO: Move this to the component layer.
7632     *       Or better leave it here and add it to the component layer
7633     *       if we have a schema construction API.
7634     */
7635     if (xmlStrEqual(pctxt->targetNamespace, xmlSchemaInstanceNs)) {
7636 	xmlSchemaCustomErr(ACTXT_CAST pctxt,
7637 	    XML_SCHEMAP_NO_XSI, node, NULL,
7638 	    "The target namespace must not match '%s'",
7639 	    xmlSchemaInstanceNs, NULL);
7640     }
7641 
7642     ret = xmlSchemaAddAttribute(pctxt, schema, attrValue,
7643 	pctxt->targetNamespace, node, 1);
7644     if (ret == NULL)
7645 	return (NULL);
7646     ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
7647 
7648     /*
7649     * Check for illegal attributes.
7650     */
7651     attr = node->properties;
7652     while (attr != NULL) {
7653 	if (attr->ns == NULL) {
7654 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7655 		(!xmlStrEqual(attr->name, BAD_CAST "default")) &&
7656 		(!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
7657 		(!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7658 		(!xmlStrEqual(attr->name, BAD_CAST "type")))
7659 	    {
7660 		xmlSchemaPIllegalAttrErr(pctxt,
7661 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7662 	    }
7663 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7664 	    xmlSchemaPIllegalAttrErr(pctxt,
7665 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7666 	}
7667 	attr = attr->next;
7668     }
7669     xmlSchemaPValAttrQName(pctxt, schema, NULL,
7670 	node, "type", &ret->typeNs, &ret->typeName);
7671 
7672     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7673     /*
7674     * Attribute "fixed".
7675     */
7676     ret->defValue = xmlSchemaGetProp(pctxt, node, "fixed");
7677     if (ret->defValue != NULL)
7678 	ret->flags |= XML_SCHEMAS_ATTR_FIXED;
7679     /*
7680     * Attribute "default".
7681     */
7682     attr = xmlSchemaGetPropNode(node, "default");
7683     if (attr != NULL) {
7684 	/*
7685 	* 3.2.3 : 1
7686 	* default and fixed must not both be present.
7687 	*/
7688 	if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
7689 	    xmlSchemaPMutualExclAttrErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
7690 		WXS_BASIC_CAST ret, attr, "default", "fixed");
7691 	} else
7692 	    ret->defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7693     }
7694     /*
7695     * And now for the children...
7696     */
7697     child = node->children;
7698     if (IS_SCHEMA(child, "annotation")) {
7699         ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7700         child = child->next;
7701     }
7702     if (IS_SCHEMA(child, "simpleType")) {
7703 	if (ret->typeName != NULL) {
7704 	    /*
7705 	    * 3.2.3 : 4
7706 	    * type and <simpleType> must not both be present.
7707 	    */
7708 	    xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7709 		NULL, node, child,
7710 		"The attribute 'type' and the <simpleType> child "
7711 		"are mutually exclusive", NULL);
7712 	} else
7713 	    ret->subtypes = xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7714 	child = child->next;
7715     }
7716     if (child != NULL)
7717 	xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7718 	    NULL, node, child, NULL,
7719 	    "(annotation?, simpleType?)");
7720 
7721     return (ret);
7722 }
7723 
7724 /**
7725  * xmlSchemaParseAttributeGroupRef:
7726  * @ctxt:  a schema validation context
7727  * @schema:  the schema being built
7728  * @node:  a subtree containing XML Schema information
7729  *
7730  * Parse an attribute group definition reference.
7731  * Note that a reference to an attribute group does not
7732  * correspond to any component at all.
7733  * *WARNING* this interface is highly subject to change
7734  *
7735  * Returns the attribute group or NULL in case of error.
7736  */
7737 static xmlSchemaQNameRefPtr
xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)7738 xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
7739 				xmlSchemaPtr schema,
7740 				xmlNodePtr node)
7741 {
7742     xmlSchemaQNameRefPtr ret;
7743     xmlNodePtr child = NULL;
7744     xmlAttrPtr attr;
7745     const xmlChar *refNs = NULL, *ref = NULL;
7746 
7747     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7748         return (NULL);
7749 
7750     attr = xmlSchemaGetPropNode(node, "ref");
7751     if (attr == NULL) {
7752 	xmlSchemaPMissingAttrErr(pctxt,
7753 	    XML_SCHEMAP_S4S_ATTR_MISSING,
7754 	    NULL, node, "ref", NULL);
7755 	return (NULL);
7756     }
7757     xmlSchemaPValAttrNodeQName(pctxt, schema,
7758 	NULL, attr, &refNs, &ref);
7759     if (xmlSchemaCheckReference(pctxt, schema, node, attr, refNs) != 0)
7760 	return(NULL);
7761 
7762     /*
7763     * Check for illegal attributes.
7764     */
7765     attr = node->properties;
7766     while (attr != NULL) {
7767 	if (attr->ns == NULL) {
7768 	    if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
7769 		(!xmlStrEqual(attr->name, BAD_CAST "id")))
7770 	    {
7771 		xmlSchemaPIllegalAttrErr(pctxt,
7772 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7773 	    }
7774 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7775 	    xmlSchemaPIllegalAttrErr(pctxt,
7776 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7777 	}
7778 	attr = attr->next;
7779     }
7780     /* Attribute ID */
7781     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7782 
7783     /*
7784     * And now for the children...
7785     */
7786     child = node->children;
7787     if (IS_SCHEMA(child, "annotation")) {
7788 	/*
7789 	* TODO: We do not have a place to store the annotation, do we?
7790 	*/
7791         xmlSchemaParseAnnotation(pctxt, child, 0);
7792         child = child->next;
7793     }
7794     if (child != NULL) {
7795 	xmlSchemaPContentErr(pctxt,
7796 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7797 	    NULL, node, child, NULL,
7798 	    "(annotation?)");
7799     }
7800 
7801     /*
7802     * Handle attribute group redefinitions.
7803     */
7804     if (pctxt->isRedefine && pctxt->redef &&
7805 	(pctxt->redef->item->type ==
7806 	    XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
7807 	(ref == pctxt->redef->refName) &&
7808 	(refNs == pctxt->redef->refTargetNs))
7809     {
7810 	/*
7811 	* SPEC src-redefine:
7812 	* (7.1) "If it has an <attributeGroup> among its contents
7813 	* the `actual value` of whose ref [attribute] is the same
7814 	* as the `actual value` of its own name attribute plus
7815 	* target namespace, then it must have exactly one such group."
7816 	*/
7817 	if (pctxt->redefCounter != 0) {
7818 	    xmlChar *str = NULL;
7819 
7820 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
7821 		XML_SCHEMAP_SRC_REDEFINE, node, NULL,
7822 		"The redefining attribute group definition "
7823 		"'%s' must not contain more than one "
7824 		"reference to the redefined definition",
7825 		xmlSchemaFormatQName(&str, refNs, ref), NULL);
7826 	    FREE_AND_NULL(str);
7827 	    return(NULL);
7828 	}
7829 	pctxt->redefCounter++;
7830 	/*
7831 	* URGENT TODO: How to ensure that the reference will not be
7832 	* handled by the normal component resolution mechanism?
7833 	*/
7834 	ret = xmlSchemaNewQNameRef(pctxt,
7835 	    XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7836 	if (ret == NULL)
7837 	    return(NULL);
7838 	ret->node = node;
7839 	pctxt->redef->reference = WXS_BASIC_CAST ret;
7840     } else {
7841 	/*
7842 	* Create a QName-reference helper component. We will substitute this
7843 	* component for the attribute uses of the referenced attribute group
7844 	* definition.
7845 	*/
7846 	ret = xmlSchemaNewQNameRef(pctxt,
7847 	    XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7848 	if (ret == NULL)
7849 	    return(NULL);
7850 	ret->node = node;
7851 	/* Add to pending items, to be able to resolve the reference. */
7852 	WXS_ADD_PENDING(pctxt, ret);
7853     }
7854     return (ret);
7855 }
7856 
7857 /**
7858  * xmlSchemaParseAttributeGroupDefinition:
7859  * @pctxt:  a schema validation context
7860  * @schema:  the schema being built
7861  * @node:  a subtree containing XML Schema information
7862  *
7863  * parse a XML schema Attribute Group declaration
7864  * *WARNING* this interface is highly subject to change
7865  *
7866  * Returns the attribute group definition or NULL in case of error.
7867  */
7868 static xmlSchemaAttributeGroupPtr
xmlSchemaParseAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)7869 xmlSchemaParseAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
7870 				       xmlSchemaPtr schema,
7871 				       xmlNodePtr node)
7872 {
7873     const xmlChar *name;
7874     xmlSchemaAttributeGroupPtr ret;
7875     xmlNodePtr child = NULL;
7876     xmlAttrPtr attr;
7877     int hasRefs = 0;
7878 
7879     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7880         return (NULL);
7881 
7882     attr = xmlSchemaGetPropNode(node, "name");
7883     if (attr == NULL) {
7884 	xmlSchemaPMissingAttrErr(pctxt,
7885 	    XML_SCHEMAP_S4S_ATTR_MISSING,
7886 	    NULL, node, "name", NULL);
7887 	return (NULL);
7888     }
7889     /*
7890     * The name is crucial, exit if invalid.
7891     */
7892     if (xmlSchemaPValAttrNode(pctxt,
7893 	NULL, attr,
7894 	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7895 	return (NULL);
7896     }
7897     ret = xmlSchemaAddAttributeGroupDefinition(pctxt, schema,
7898 	name, pctxt->targetNamespace, node);
7899     if (ret == NULL)
7900 	return (NULL);
7901     /*
7902     * Check for illegal attributes.
7903     */
7904     attr = node->properties;
7905     while (attr != NULL) {
7906 	if (attr->ns == NULL) {
7907 	    if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7908 		(!xmlStrEqual(attr->name, BAD_CAST "id")))
7909 	    {
7910 		xmlSchemaPIllegalAttrErr(pctxt,
7911 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7912 	    }
7913 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7914 	    xmlSchemaPIllegalAttrErr(pctxt,
7915 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7916 	}
7917 	attr = attr->next;
7918     }
7919     /* Attribute ID */
7920     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7921     /*
7922     * And now for the children...
7923     */
7924     child = node->children;
7925     if (IS_SCHEMA(child, "annotation")) {
7926         ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7927         child = child->next;
7928     }
7929     /*
7930     * Parse contained attribute decls/refs.
7931     */
7932     if (xmlSchemaParseLocalAttributes(pctxt, schema, &child,
7933 	(xmlSchemaItemListPtr *) &(ret->attrUses),
7934 	XML_SCHEMA_TYPE_ATTRIBUTEGROUP, &hasRefs) == -1)
7935 	return(NULL);
7936     if (hasRefs)
7937 	ret->flags |= XML_SCHEMAS_ATTRGROUP_HAS_REFS;
7938     /*
7939     * Parse the attribute wildcard.
7940     */
7941     if (IS_SCHEMA(child, "anyAttribute")) {
7942 	ret->attributeWildcard = xmlSchemaParseAnyAttribute(pctxt,
7943 	    schema, child);
7944 	child = child->next;
7945     }
7946     if (child != NULL) {
7947 	xmlSchemaPContentErr(pctxt,
7948 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7949 	    NULL, node, child, NULL,
7950 	    "(annotation?, ((attribute | attributeGroup)*, anyAttribute?))");
7951     }
7952     return (ret);
7953 }
7954 
7955 /**
7956  * xmlSchemaPValAttrFormDefault:
7957  * @value:  the value
7958  * @flags: the flags to be modified
7959  * @flagQualified: the specific flag for "qualified"
7960  *
7961  * Returns 0 if the value is valid, 1 otherwise.
7962  */
7963 static int
xmlSchemaPValAttrFormDefault(const xmlChar * value,int * flags,int flagQualified)7964 xmlSchemaPValAttrFormDefault(const xmlChar *value,
7965 			     int *flags,
7966 			     int flagQualified)
7967 {
7968     if (xmlStrEqual(value, BAD_CAST "qualified")) {
7969 	if  ((*flags & flagQualified) == 0)
7970 	    *flags |= flagQualified;
7971     } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
7972 	return (1);
7973 
7974     return (0);
7975 }
7976 
7977 /**
7978  * xmlSchemaPValAttrBlockFinal:
7979  * @value:  the value
7980  * @flags: the flags to be modified
7981  * @flagAll: the specific flag for "#all"
7982  * @flagExtension: the specific flag for "extension"
7983  * @flagRestriction: the specific flag for "restriction"
7984  * @flagSubstitution: the specific flag for "substitution"
7985  * @flagList: the specific flag for "list"
7986  * @flagUnion: the specific flag for "union"
7987  *
7988  * Validates the value of the attribute "final" and "block". The value
7989  * is converted into the specified flag values and returned in @flags.
7990  *
7991  * Returns 0 if the value is valid, 1 otherwise.
7992  */
7993 
7994 static int
xmlSchemaPValAttrBlockFinal(const xmlChar * value,int * flags,int flagAll,int flagExtension,int flagRestriction,int flagSubstitution,int flagList,int flagUnion)7995 xmlSchemaPValAttrBlockFinal(const xmlChar *value,
7996 			    int *flags,
7997 			    int flagAll,
7998 			    int flagExtension,
7999 			    int flagRestriction,
8000 			    int flagSubstitution,
8001 			    int flagList,
8002 			    int flagUnion)
8003 {
8004     int ret = 0;
8005 
8006     /*
8007     * TODO: This does not check for duplicate entries.
8008     */
8009     if ((flags == NULL) || (value == NULL))
8010 	return (-1);
8011     if (value[0] == 0)
8012 	return (0);
8013     if (xmlStrEqual(value, BAD_CAST "#all")) {
8014 	if (flagAll != -1)
8015 	    *flags |= flagAll;
8016 	else {
8017 	    if (flagExtension != -1)
8018 		*flags |= flagExtension;
8019 	    if (flagRestriction != -1)
8020 		*flags |= flagRestriction;
8021 	    if (flagSubstitution != -1)
8022 		*flags |= flagSubstitution;
8023 	    if (flagList != -1)
8024 		*flags |= flagList;
8025 	    if (flagUnion != -1)
8026 		*flags |= flagUnion;
8027 	}
8028     } else {
8029 	const xmlChar *end, *cur = value;
8030 	xmlChar *item;
8031 
8032 	do {
8033 	    while (IS_BLANK_CH(*cur))
8034 		cur++;
8035 	    end = cur;
8036 	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
8037 		end++;
8038 	    if (end == cur)
8039 		break;
8040 	    item = xmlStrndup(cur, end - cur);
8041 	    if (xmlStrEqual(item, BAD_CAST "extension")) {
8042 		if (flagExtension != -1) {
8043 		    if ((*flags & flagExtension) == 0)
8044 			*flags |= flagExtension;
8045 		} else
8046 		    ret = 1;
8047 	    } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
8048 		if (flagRestriction != -1) {
8049 		    if ((*flags & flagRestriction) == 0)
8050 			*flags |= flagRestriction;
8051 		} else
8052 		    ret = 1;
8053 	    } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
8054 		if (flagSubstitution != -1) {
8055 		    if ((*flags & flagSubstitution) == 0)
8056 			*flags |= flagSubstitution;
8057 		} else
8058 		    ret = 1;
8059 	    } else if (xmlStrEqual(item, BAD_CAST "list")) {
8060 		if (flagList != -1) {
8061 		    if ((*flags & flagList) == 0)
8062 			*flags |= flagList;
8063 		} else
8064 		    ret = 1;
8065 	    } else if (xmlStrEqual(item, BAD_CAST "union")) {
8066 		if (flagUnion != -1) {
8067 		    if ((*flags & flagUnion) == 0)
8068 			*flags |= flagUnion;
8069 		} else
8070 		    ret = 1;
8071 	    } else
8072 		ret = 1;
8073 	    if (item != NULL)
8074 		xmlFree(item);
8075 	    cur = end;
8076 	} while ((ret == 0) && (*cur != 0));
8077     }
8078 
8079     return (ret);
8080 }
8081 
8082 static int
xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,xmlSchemaIDCPtr idc,xmlSchemaIDCSelectPtr selector,xmlAttrPtr attr,int isField)8083 xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
8084 			     xmlSchemaIDCPtr idc,
8085 			     xmlSchemaIDCSelectPtr selector,
8086 			     xmlAttrPtr attr,
8087 			     int isField)
8088 {
8089     xmlNodePtr node;
8090 
8091     /*
8092     * c-selector-xpath:
8093     * Schema Component Constraint: Selector Value OK
8094     *
8095     * TODO: 1 The {selector} must be a valid XPath expression, as defined
8096     * in [XPath].
8097     */
8098     if (selector == NULL) {
8099 	xmlSchemaPErr(ctxt, idc->node,
8100 	    XML_SCHEMAP_INTERNAL,
8101 	    "Internal error: xmlSchemaCheckCSelectorXPath, "
8102 	    "the selector is not specified.\n", NULL, NULL);
8103 	return (-1);
8104     }
8105     if (attr == NULL)
8106 	node = idc->node;
8107     else
8108 	node = (xmlNodePtr) attr;
8109     if (selector->xpath == NULL) {
8110 	xmlSchemaPCustomErr(ctxt,
8111 	    /* TODO: Adjust error code. */
8112 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8113 	    NULL, node,
8114 	    "The XPath expression of the selector is not valid", NULL);
8115 	return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
8116     } else {
8117 	const xmlChar **nsArray = NULL;
8118 	xmlNsPtr *nsList = NULL;
8119 	/*
8120 	* Compile the XPath expression.
8121 	*/
8122 	/*
8123 	* TODO: We need the array of in-scope namespaces for compilation.
8124 	* TODO: Call xmlPatterncompile with different options for selector/
8125 	* field.
8126 	*/
8127 	if (attr == NULL)
8128 	    nsList = NULL;
8129 	else
8130 	    nsList = xmlGetNsList(attr->doc, attr->parent);
8131 	/*
8132 	* Build an array of prefixes and namespaces.
8133 	*/
8134 	if (nsList != NULL) {
8135 	    int i, count = 0;
8136 
8137 	    for (i = 0; nsList[i] != NULL; i++)
8138 		count++;
8139 
8140 	    nsArray = (const xmlChar **) xmlMalloc(
8141 		(count * 2 + 1) * sizeof(const xmlChar *));
8142 	    if (nsArray == NULL) {
8143 		xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
8144 		    NULL);
8145 		xmlFree(nsList);
8146 		return (-1);
8147 	    }
8148 	    for (i = 0; i < count; i++) {
8149 		nsArray[2 * i] = nsList[i]->href;
8150 		nsArray[2 * i + 1] = nsList[i]->prefix;
8151 	    }
8152 	    nsArray[count * 2] = NULL;
8153 	    xmlFree(nsList);
8154 	}
8155 	/*
8156 	* TODO: Differentiate between "selector" and "field".
8157 	*/
8158 	if (isField)
8159 	    selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
8160 		NULL, XML_PATTERN_XSFIELD, nsArray);
8161 	else
8162 	    selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
8163 		NULL, XML_PATTERN_XSSEL, nsArray);
8164 	if (nsArray != NULL)
8165 	    xmlFree((xmlChar **) nsArray);
8166 
8167 	if (selector->xpathComp == NULL) {
8168 	    xmlSchemaPCustomErr(ctxt,
8169 		/* TODO: Adjust error code? */
8170 		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8171 		NULL, node,
8172 		"The XPath expression '%s' could not be "
8173 		"compiled", selector->xpath);
8174 	    return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
8175 	}
8176     }
8177     return (0);
8178 }
8179 
8180 #define ADD_ANNOTATION(annot)   \
8181     xmlSchemaAnnotPtr cur = item->annot; \
8182     if (item->annot == NULL) {  \
8183 	item->annot = annot;    \
8184 	return (annot);         \
8185     }                           \
8186     cur = item->annot;          \
8187     if (cur->next != NULL) {    \
8188 	cur = cur->next;	\
8189     }                           \
8190     cur->next = annot;
8191 
8192 /**
8193  * xmlSchemaAssignAnnotation:
8194  * @item: the schema component
8195  * @annot: the annotation
8196  *
8197  * Adds the annotation to the given schema component.
8198  *
8199  * Returns the given annotation.
8200  */
8201 static xmlSchemaAnnotPtr
xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,xmlSchemaAnnotPtr annot)8202 xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
8203 		       xmlSchemaAnnotPtr annot)
8204 {
8205     if ((annItem == NULL) || (annot == NULL))
8206 	return (NULL);
8207     switch (annItem->type) {
8208 	case XML_SCHEMA_TYPE_ELEMENT: {
8209 		xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
8210 		ADD_ANNOTATION(annot)
8211 	    }
8212 	    break;
8213 	case XML_SCHEMA_TYPE_ATTRIBUTE: {
8214 		xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
8215 		ADD_ANNOTATION(annot)
8216 	    }
8217 	    break;
8218 	case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
8219 	case XML_SCHEMA_TYPE_ANY: {
8220 		xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
8221 		ADD_ANNOTATION(annot)
8222 	    }
8223 	    break;
8224 	case XML_SCHEMA_TYPE_PARTICLE:
8225 	case XML_SCHEMA_TYPE_IDC_KEY:
8226 	case XML_SCHEMA_TYPE_IDC_KEYREF:
8227 	case XML_SCHEMA_TYPE_IDC_UNIQUE: {
8228 		xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
8229 		ADD_ANNOTATION(annot)
8230 	    }
8231 	    break;
8232 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
8233 		xmlSchemaAttributeGroupPtr item =
8234 		    (xmlSchemaAttributeGroupPtr) annItem;
8235 		ADD_ANNOTATION(annot)
8236 	    }
8237 	    break;
8238 	case XML_SCHEMA_TYPE_NOTATION: {
8239 		xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
8240 		ADD_ANNOTATION(annot)
8241 	    }
8242 	    break;
8243 	case XML_SCHEMA_FACET_MININCLUSIVE:
8244 	case XML_SCHEMA_FACET_MINEXCLUSIVE:
8245 	case XML_SCHEMA_FACET_MAXINCLUSIVE:
8246 	case XML_SCHEMA_FACET_MAXEXCLUSIVE:
8247 	case XML_SCHEMA_FACET_TOTALDIGITS:
8248 	case XML_SCHEMA_FACET_FRACTIONDIGITS:
8249 	case XML_SCHEMA_FACET_PATTERN:
8250 	case XML_SCHEMA_FACET_ENUMERATION:
8251 	case XML_SCHEMA_FACET_WHITESPACE:
8252 	case XML_SCHEMA_FACET_LENGTH:
8253 	case XML_SCHEMA_FACET_MAXLENGTH:
8254 	case XML_SCHEMA_FACET_MINLENGTH: {
8255 		xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
8256 		ADD_ANNOTATION(annot)
8257 	    }
8258 	    break;
8259 	case XML_SCHEMA_TYPE_SIMPLE:
8260 	case XML_SCHEMA_TYPE_COMPLEX: {
8261 		xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
8262 		ADD_ANNOTATION(annot)
8263 	    }
8264 	    break;
8265 	case XML_SCHEMA_TYPE_GROUP: {
8266 		xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
8267 		ADD_ANNOTATION(annot)
8268 	    }
8269 	    break;
8270 	case XML_SCHEMA_TYPE_SEQUENCE:
8271 	case XML_SCHEMA_TYPE_CHOICE:
8272 	case XML_SCHEMA_TYPE_ALL: {
8273 		xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
8274 		ADD_ANNOTATION(annot)
8275 	    }
8276 	    break;
8277 	default:
8278 	     xmlSchemaPCustomErr(NULL,
8279 		XML_SCHEMAP_INTERNAL,
8280 		NULL, NULL,
8281 		"Internal error: xmlSchemaAddAnnotation, "
8282 		"The item is not a annotated schema component", NULL);
8283 	     break;
8284     }
8285     return (annot);
8286 }
8287 
8288 /**
8289  * xmlSchemaParseIDCSelectorAndField:
8290  * @ctxt:  a schema validation context
8291  * @schema:  the schema being built
8292  * @node:  a subtree containing XML Schema information
8293  *
8294  * Parses a XML Schema identity-constraint definition's
8295  * <selector> and <field> elements.
8296  *
8297  * Returns the parsed identity-constraint definition.
8298  */
8299 static xmlSchemaIDCSelectPtr
xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,xmlSchemaIDCPtr idc,xmlNodePtr node,int isField)8300 xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
8301 			  xmlSchemaIDCPtr idc,
8302 			  xmlNodePtr node,
8303 			  int isField)
8304 {
8305     xmlSchemaIDCSelectPtr item;
8306     xmlNodePtr child = NULL;
8307     xmlAttrPtr attr;
8308 
8309     /*
8310     * Check for illegal attributes.
8311     */
8312     attr = node->properties;
8313     while (attr != NULL) {
8314 	if (attr->ns == NULL) {
8315 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8316 		(!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
8317 		xmlSchemaPIllegalAttrErr(ctxt,
8318 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8319 	    }
8320 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8321 	    xmlSchemaPIllegalAttrErr(ctxt,
8322 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8323 	}
8324 	attr = attr->next;
8325     }
8326     /*
8327     * Create the item.
8328     */
8329     item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
8330     if (item == NULL) {
8331         xmlSchemaPErrMemory(ctxt,
8332 	    "allocating a 'selector' of an identity-constraint definition",
8333 	    NULL);
8334         return (NULL);
8335     }
8336     memset(item, 0, sizeof(xmlSchemaIDCSelect));
8337     /*
8338     * Attribute "xpath" (mandatory).
8339     */
8340     attr = xmlSchemaGetPropNode(node, "xpath");
8341     if (attr == NULL) {
8342 	xmlSchemaPMissingAttrErr(ctxt,
8343 	    XML_SCHEMAP_S4S_ATTR_MISSING,
8344 	    NULL, node,
8345 	    "name", NULL);
8346     } else {
8347 	item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8348 	/*
8349 	* URGENT TODO: "field"s have an other syntax than "selector"s.
8350 	*/
8351 
8352 	if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
8353 	    isField) == -1) {
8354 	    xmlSchemaPErr(ctxt,
8355 		(xmlNodePtr) attr,
8356 		XML_SCHEMAP_INTERNAL,
8357 		"Internal error: xmlSchemaParseIDCSelectorAndField, "
8358 		"validating the XPath expression of a IDC selector.\n",
8359 		NULL, NULL);
8360 	}
8361 
8362     }
8363     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8364     /*
8365     * And now for the children...
8366     */
8367     child = node->children;
8368     if (IS_SCHEMA(child, "annotation")) {
8369 	/*
8370 	* Add the annotation to the parent IDC.
8371 	*/
8372 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
8373 	    xmlSchemaParseAnnotation(ctxt, child, 1));
8374 	child = child->next;
8375     }
8376     if (child != NULL) {
8377 	xmlSchemaPContentErr(ctxt,
8378 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8379 	    NULL, node, child,
8380 	    NULL, "(annotation?)");
8381     }
8382 
8383     return (item);
8384 }
8385 
8386 /**
8387  * xmlSchemaParseIDC:
8388  * @ctxt:  a schema validation context
8389  * @schema:  the schema being built
8390  * @node:  a subtree containing XML Schema information
8391  *
8392  * Parses a XML Schema identity-constraint definition.
8393  *
8394  * Returns the parsed identity-constraint definition.
8395  */
8396 static xmlSchemaIDCPtr
xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlSchemaTypeType idcCategory,const xmlChar * targetNamespace)8397 xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
8398 		  xmlSchemaPtr schema,
8399 		  xmlNodePtr node,
8400 		  xmlSchemaTypeType idcCategory,
8401 		  const xmlChar *targetNamespace)
8402 {
8403     xmlSchemaIDCPtr item = NULL;
8404     xmlNodePtr child = NULL;
8405     xmlAttrPtr attr;
8406     const xmlChar *name = NULL;
8407     xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
8408 
8409     /*
8410     * Check for illegal attributes.
8411     */
8412     attr = node->properties;
8413     while (attr != NULL) {
8414 	if (attr->ns == NULL) {
8415 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8416 		(!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8417 		((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
8418 		 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
8419 		xmlSchemaPIllegalAttrErr(ctxt,
8420 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8421 	    }
8422 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8423 	    xmlSchemaPIllegalAttrErr(ctxt,
8424 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8425 	}
8426 	attr = attr->next;
8427     }
8428     /*
8429     * Attribute "name" (mandatory).
8430     */
8431     attr = xmlSchemaGetPropNode(node, "name");
8432     if (attr == NULL) {
8433 	xmlSchemaPMissingAttrErr(ctxt,
8434 	    XML_SCHEMAP_S4S_ATTR_MISSING,
8435 	    NULL, node,
8436 	    "name", NULL);
8437 	return (NULL);
8438     } else if (xmlSchemaPValAttrNode(ctxt,
8439 	NULL, attr,
8440 	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8441 	return (NULL);
8442     }
8443     /* Create the component. */
8444     item = xmlSchemaAddIDC(ctxt, schema, name, targetNamespace,
8445 	idcCategory, node);
8446     if (item == NULL)
8447 	return(NULL);
8448 
8449     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8450     if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
8451 	/*
8452 	* Attribute "refer" (mandatory).
8453 	*/
8454 	attr = xmlSchemaGetPropNode(node, "refer");
8455 	if (attr == NULL) {
8456 	    xmlSchemaPMissingAttrErr(ctxt,
8457 		XML_SCHEMAP_S4S_ATTR_MISSING,
8458 		NULL, node,
8459 		"refer", NULL);
8460 	} else {
8461 	    /*
8462 	    * Create a reference item.
8463 	    */
8464 	    item->ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_IDC_KEY,
8465 		NULL, NULL);
8466 	    if (item->ref == NULL)
8467 		return (NULL);
8468 	    xmlSchemaPValAttrNodeQName(ctxt, schema,
8469 		NULL, attr,
8470 		&(item->ref->targetNamespace),
8471 		&(item->ref->name));
8472 	    xmlSchemaCheckReference(ctxt, schema, node, attr,
8473 		item->ref->targetNamespace);
8474 	}
8475     }
8476     /*
8477     * And now for the children...
8478     */
8479     child = node->children;
8480     if (IS_SCHEMA(child, "annotation")) {
8481 	item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
8482 	child = child->next;
8483     }
8484     if (child == NULL) {
8485 	xmlSchemaPContentErr(ctxt,
8486 		XML_SCHEMAP_S4S_ELEM_MISSING,
8487 		NULL, node, child,
8488 		"A child element is missing",
8489 		"(annotation?, (selector, field+))");
8490     }
8491     /*
8492     * Child element <selector>.
8493     */
8494     if (IS_SCHEMA(child, "selector")) {
8495 	item->selector = xmlSchemaParseIDCSelectorAndField(ctxt,
8496 	    item, child, 0);
8497 	child = child->next;
8498 	/*
8499 	* Child elements <field>.
8500 	*/
8501 	if (IS_SCHEMA(child, "field")) {
8502 	    do {
8503 		field = xmlSchemaParseIDCSelectorAndField(ctxt,
8504 		    item, child, 1);
8505 		if (field != NULL) {
8506 		    field->index = item->nbFields;
8507 		    item->nbFields++;
8508 		    if (lastField != NULL)
8509 			lastField->next = field;
8510 		    else
8511 			item->fields = field;
8512 		    lastField = field;
8513 		}
8514 		child = child->next;
8515 	    } while (IS_SCHEMA(child, "field"));
8516 	} else {
8517 	    xmlSchemaPContentErr(ctxt,
8518 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8519 		NULL, node, child,
8520 		NULL, "(annotation?, (selector, field+))");
8521 	}
8522     }
8523     if (child != NULL) {
8524 	xmlSchemaPContentErr(ctxt,
8525 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8526 	    NULL, node, child,
8527 	    NULL, "(annotation?, (selector, field+))");
8528     }
8529 
8530     return (item);
8531 }
8532 
8533 /**
8534  * xmlSchemaParseElement:
8535  * @ctxt:  a schema validation context
8536  * @schema:  the schema being built
8537  * @node:  a subtree containing XML Schema information
8538  * @topLevel: indicates if this is global declaration
8539  *
8540  * Parses a XML schema element declaration.
8541  * *WARNING* this interface is highly subject to change
8542  *
8543  * Returns the element declaration or a particle; NULL in case
8544  * of an error or if the particle has minOccurs==maxOccurs==0.
8545  */
8546 static xmlSchemaBasicItemPtr
xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int * isElemRef,int topLevel)8547 xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8548                       xmlNodePtr node, int *isElemRef, int topLevel)
8549 {
8550     xmlSchemaElementPtr decl = NULL;
8551     xmlSchemaParticlePtr particle = NULL;
8552     xmlSchemaAnnotPtr annot = NULL;
8553     xmlNodePtr child = NULL;
8554     xmlAttrPtr attr, nameAttr;
8555     int min, max, isRef = 0;
8556     xmlChar *des = NULL;
8557 
8558     /* 3.3.3 Constraints on XML Representations of Element Declarations */
8559     /* TODO: Complete implementation of 3.3.6 */
8560 
8561     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8562         return (NULL);
8563 
8564     if (isElemRef != NULL)
8565 	*isElemRef = 0;
8566     /*
8567     * If we get a "ref" attribute on a local <element> we will assume it's
8568     * a reference - even if there's a "name" attribute; this seems to be more
8569     * robust.
8570     */
8571     nameAttr = xmlSchemaGetPropNode(node, "name");
8572     attr = xmlSchemaGetPropNode(node, "ref");
8573     if ((topLevel) || (attr == NULL)) {
8574 	if (nameAttr == NULL) {
8575 	    xmlSchemaPMissingAttrErr(ctxt,
8576 		XML_SCHEMAP_S4S_ATTR_MISSING,
8577 		NULL, node, "name", NULL);
8578 	    return (NULL);
8579 	}
8580     } else
8581 	isRef = 1;
8582 
8583     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8584     child = node->children;
8585     if (IS_SCHEMA(child, "annotation")) {
8586 	annot = xmlSchemaParseAnnotation(ctxt, child, 1);
8587 	child = child->next;
8588     }
8589     /*
8590     * Skip particle part if a global declaration.
8591     */
8592     if (topLevel)
8593 	goto declaration_part;
8594     /*
8595     * The particle part ==================================================
8596     */
8597     min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
8598     max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
8599     xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
8600     particle = xmlSchemaAddParticle(ctxt, node, min, max);
8601     if (particle == NULL)
8602 	goto return_null;
8603 
8604     /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
8605 
8606     if (isRef) {
8607 	const xmlChar *refNs = NULL, *ref = NULL;
8608 	xmlSchemaQNameRefPtr refer = NULL;
8609 	/*
8610 	* The reference part =============================================
8611 	*/
8612 	if (isElemRef != NULL)
8613 	    *isElemRef = 1;
8614 
8615 	xmlSchemaPValAttrNodeQName(ctxt, schema,
8616 	    NULL, attr, &refNs, &ref);
8617 	xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
8618 	/*
8619 	* SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
8620 	*/
8621 	if (nameAttr != NULL) {
8622 	    xmlSchemaPMutualExclAttrErr(ctxt,
8623 		XML_SCHEMAP_SRC_ELEMENT_2_1, NULL, nameAttr, "ref", "name");
8624 	}
8625 	/*
8626 	* Check for illegal attributes.
8627 	*/
8628 	attr = node->properties;
8629 	while (attr != NULL) {
8630 	    if (attr->ns == NULL) {
8631 		if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
8632 		    xmlStrEqual(attr->name, BAD_CAST "name") ||
8633 		    xmlStrEqual(attr->name, BAD_CAST "id") ||
8634 		    xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
8635 		    xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
8636 		{
8637 		    attr = attr->next;
8638 		    continue;
8639 		} else {
8640 		    /* SPEC (3.3.3 : 2.2) */
8641 		    xmlSchemaPCustomAttrErr(ctxt,
8642 			XML_SCHEMAP_SRC_ELEMENT_2_2,
8643 			NULL, NULL, attr,
8644 			"Only the attributes 'minOccurs', 'maxOccurs' and "
8645 			"'id' are allowed in addition to 'ref'");
8646 		    break;
8647 		}
8648 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8649 		xmlSchemaPIllegalAttrErr(ctxt,
8650 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8651 	    }
8652 	    attr = attr->next;
8653 	}
8654 	/*
8655 	* No children except <annotation> expected.
8656 	*/
8657 	if (child != NULL) {
8658 	    xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8659 		NULL, node, child, NULL, "(annotation?)");
8660 	}
8661 	if ((min == 0) && (max == 0))
8662 	    goto return_null;
8663 	/*
8664 	* Create the reference item and attach it to the particle.
8665 	*/
8666 	refer = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_ELEMENT,
8667 	    ref, refNs);
8668 	if (refer == NULL)
8669 	    goto return_null;
8670 	particle->children = (xmlSchemaTreeItemPtr) refer;
8671 	particle->annot = annot;
8672 	/*
8673 	* Add the particle to pending components, since the reference
8674 	* need to be resolved.
8675 	*/
8676 	WXS_ADD_PENDING(ctxt, particle);
8677 	return ((xmlSchemaBasicItemPtr) particle);
8678     }
8679     /*
8680     * The declaration part ===============================================
8681     */
8682 declaration_part:
8683     {
8684 	const xmlChar *ns = NULL, *fixed, *name, *attrValue;
8685 	xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
8686 
8687 	if (xmlSchemaPValAttrNode(ctxt, NULL, nameAttr,
8688 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
8689 	    goto return_null;
8690 	/*
8691 	* Evaluate the target namespace.
8692 	*/
8693 	if (topLevel) {
8694 	    ns = ctxt->targetNamespace;
8695 	} else {
8696 	    attr = xmlSchemaGetPropNode(node, "form");
8697 	    if (attr != NULL) {
8698 		attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8699 		if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
8700 		    ns = ctxt->targetNamespace;
8701 		} else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
8702 		    xmlSchemaPSimpleTypeErr(ctxt,
8703 			XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8704 			NULL, (xmlNodePtr) attr,
8705 			NULL, "(qualified | unqualified)",
8706 			attrValue, NULL, NULL, NULL);
8707 		}
8708 	    } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
8709 		ns = ctxt->targetNamespace;
8710 	}
8711 	decl = xmlSchemaAddElement(ctxt, name, ns, node, topLevel);
8712 	if (decl == NULL) {
8713 	    goto return_null;
8714 	}
8715 	/*
8716 	* Check for illegal attributes.
8717 	*/
8718 	attr = node->properties;
8719 	while (attr != NULL) {
8720 	    if (attr->ns == NULL) {
8721 		if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8722 		    (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
8723 		    (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8724 		    (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
8725 		    (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
8726 		    (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
8727 		    (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
8728 		{
8729 		    if (topLevel == 0) {
8730 			if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8731 			    (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
8732 			    (!xmlStrEqual(attr->name, BAD_CAST "form")))
8733 			{
8734 			    xmlSchemaPIllegalAttrErr(ctxt,
8735 				XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8736 			}
8737 		    } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
8738 			(!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
8739 			(!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
8740 
8741 			xmlSchemaPIllegalAttrErr(ctxt,
8742 			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8743 		    }
8744 		}
8745 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8746 
8747 		xmlSchemaPIllegalAttrErr(ctxt,
8748 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8749 	    }
8750 	    attr = attr->next;
8751 	}
8752 	/*
8753 	* Extract/validate attributes.
8754 	*/
8755 	if (topLevel) {
8756 	    /*
8757 	    * Process top attributes of global element declarations here.
8758 	    */
8759 	    decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
8760 	    decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
8761 	    xmlSchemaPValAttrQName(ctxt, schema,
8762 		NULL, node, "substitutionGroup",
8763 		&(decl->substGroupNs), &(decl->substGroup));
8764 	    if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
8765 		decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
8766 	    /*
8767 	    * Attribute "final".
8768 	    */
8769 	    attr = xmlSchemaGetPropNode(node, "final");
8770 	    if (attr == NULL) {
8771 		if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8772 		    decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
8773 		if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8774 		    decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
8775 	    } else {
8776 		attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8777 		if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
8778 		    -1,
8779 		    XML_SCHEMAS_ELEM_FINAL_EXTENSION,
8780 		    XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
8781 		    xmlSchemaPSimpleTypeErr(ctxt,
8782 			XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8783 			NULL, (xmlNodePtr) attr,
8784 			NULL, "(#all | List of (extension | restriction))",
8785 			attrValue, NULL, NULL, NULL);
8786 		}
8787 	    }
8788 	}
8789 	/*
8790 	* Attribute "block".
8791 	*/
8792 	attr = xmlSchemaGetPropNode(node, "block");
8793 	if (attr == NULL) {
8794 	    /*
8795 	    * Apply default "block" values.
8796 	    */
8797 	    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8798 		decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
8799 	    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8800 		decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
8801 	    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8802 		decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
8803 	} else {
8804 	    attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8805 	    if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
8806 		-1,
8807 		XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
8808 		XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
8809 		XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
8810 		xmlSchemaPSimpleTypeErr(ctxt,
8811 		    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8812 		    NULL, (xmlNodePtr) attr,
8813 		    NULL, "(#all | List of (extension | "
8814 		    "restriction | substitution))", attrValue,
8815 		    NULL, NULL, NULL);
8816 	    }
8817 	}
8818 	if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
8819 	    decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
8820 
8821 	attr = xmlSchemaGetPropNode(node, "type");
8822 	if (attr != NULL) {
8823 	    xmlSchemaPValAttrNodeQName(ctxt, schema,
8824 		NULL, attr,
8825 		&(decl->namedTypeNs), &(decl->namedType));
8826 	    xmlSchemaCheckReference(ctxt, schema, node,
8827 		attr, decl->namedTypeNs);
8828 	}
8829 	decl->value = xmlSchemaGetProp(ctxt, node, "default");
8830 	attr = xmlSchemaGetPropNode(node, "fixed");
8831 	if (attr != NULL) {
8832 	    fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8833 	    if (decl->value != NULL) {
8834 		/*
8835 		* 3.3.3 : 1
8836 		* default and fixed must not both be present.
8837 		*/
8838 		xmlSchemaPMutualExclAttrErr(ctxt,
8839 		    XML_SCHEMAP_SRC_ELEMENT_1,
8840 		    NULL, attr, "default", "fixed");
8841 	    } else {
8842 		decl->flags |= XML_SCHEMAS_ELEM_FIXED;
8843 		decl->value = fixed;
8844 	    }
8845 	}
8846 	/*
8847 	* And now for the children...
8848 	*/
8849 	if (IS_SCHEMA(child, "complexType")) {
8850 	    /*
8851 	    * 3.3.3 : 3
8852 	    * "type" and either <simpleType> or <complexType> are mutually
8853 	    * exclusive
8854 	    */
8855 	    if (decl->namedType != NULL) {
8856 		xmlSchemaPContentErr(ctxt,
8857 		    XML_SCHEMAP_SRC_ELEMENT_3,
8858 		    NULL, node, child,
8859 		    "The attribute 'type' and the <complexType> child are "
8860 		    "mutually exclusive", NULL);
8861 	    } else
8862 		WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
8863 	    child = child->next;
8864 	} else if (IS_SCHEMA(child, "simpleType")) {
8865 	    /*
8866 	    * 3.3.3 : 3
8867 	    * "type" and either <simpleType> or <complexType> are
8868 	    * mutually exclusive
8869 	    */
8870 	    if (decl->namedType != NULL) {
8871 		xmlSchemaPContentErr(ctxt,
8872 		    XML_SCHEMAP_SRC_ELEMENT_3,
8873 		    NULL, node, child,
8874 		    "The attribute 'type' and the <simpleType> child are "
8875 		    "mutually exclusive", NULL);
8876 	    } else
8877 		WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8878 	    child = child->next;
8879 	}
8880 	while ((IS_SCHEMA(child, "unique")) ||
8881 	    (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
8882 	    if (IS_SCHEMA(child, "unique")) {
8883 		curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8884 		    XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
8885 	    } else if (IS_SCHEMA(child, "key")) {
8886 		curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8887 		    XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
8888 	    } else if (IS_SCHEMA(child, "keyref")) {
8889 		curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8890 		    XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
8891 	    }
8892 	    if (lastIDC != NULL)
8893 		lastIDC->next = curIDC;
8894 	    else
8895 		decl->idcs = (void *) curIDC;
8896 	    lastIDC = curIDC;
8897 	    child = child->next;
8898 	}
8899 	if (child != NULL) {
8900 	    xmlSchemaPContentErr(ctxt,
8901 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8902 		NULL, node, child,
8903 		NULL, "(annotation?, ((simpleType | complexType)?, "
8904 		"(unique | key | keyref)*))");
8905 	}
8906 	decl->annot = annot;
8907     }
8908     /*
8909     * NOTE: Element Declaration Representation OK 4. will be checked at a
8910     * different layer.
8911     */
8912     FREE_AND_NULL(des)
8913     if (topLevel)
8914 	return ((xmlSchemaBasicItemPtr) decl);
8915     else {
8916 	particle->children = (xmlSchemaTreeItemPtr) decl;
8917 	return ((xmlSchemaBasicItemPtr) particle);
8918     }
8919 
8920 return_null:
8921     FREE_AND_NULL(des);
8922     if (annot != NULL) {
8923 	if (particle != NULL)
8924 	    particle->annot = NULL;
8925 	if (decl != NULL)
8926 	    decl->annot = NULL;
8927 	xmlSchemaFreeAnnot(annot);
8928     }
8929     return (NULL);
8930 }
8931 
8932 /**
8933  * xmlSchemaParseUnion:
8934  * @ctxt:  a schema validation context
8935  * @schema:  the schema being built
8936  * @node:  a subtree containing XML Schema information
8937  *
8938  * parse a XML schema Union definition
8939  * *WARNING* this interface is highly subject to change
8940  *
8941  * Returns -1 in case of internal error, 0 in case of success and a positive
8942  * error code otherwise.
8943  */
8944 static int
xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)8945 xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8946                     xmlNodePtr node)
8947 {
8948     xmlSchemaTypePtr type;
8949     xmlNodePtr child = NULL;
8950     xmlAttrPtr attr;
8951     const xmlChar *cur = NULL;
8952 
8953     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8954         return (-1);
8955     /* Not a component, don't create it. */
8956     type = ctxt->ctxtType;
8957     /*
8958     * Mark the simple type as being of variety "union".
8959     */
8960     type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
8961     /*
8962     * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
8963     * then the `simple ur-type definition`."
8964     */
8965     type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
8966     /*
8967     * Check for illegal attributes.
8968     */
8969     attr = node->properties;
8970     while (attr != NULL) {
8971 	if (attr->ns == NULL) {
8972 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8973 		(!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
8974 		xmlSchemaPIllegalAttrErr(ctxt,
8975 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8976 	    }
8977 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8978 	    xmlSchemaPIllegalAttrErr(ctxt,
8979 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8980 	}
8981 	attr = attr->next;
8982     }
8983     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8984     /*
8985     * Attribute "memberTypes". This is a list of QNames.
8986     * TODO: Check the value to contain anything.
8987     */
8988     attr = xmlSchemaGetPropNode(node, "memberTypes");
8989     if (attr != NULL) {
8990 	const xmlChar *end;
8991 	xmlChar *tmp;
8992 	const xmlChar *localName, *nsName;
8993 	xmlSchemaTypeLinkPtr link, lastLink = NULL;
8994 	xmlSchemaQNameRefPtr ref;
8995 
8996 	cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8997 	type->base = cur;
8998 	do {
8999 	    while (IS_BLANK_CH(*cur))
9000 		cur++;
9001 	    end = cur;
9002 	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
9003 		end++;
9004 	    if (end == cur)
9005 		break;
9006 	    tmp = xmlStrndup(cur, end - cur);
9007 	    if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
9008 		NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
9009 		/*
9010 		* Create the member type link.
9011 		*/
9012 		link = (xmlSchemaTypeLinkPtr)
9013 		    xmlMalloc(sizeof(xmlSchemaTypeLink));
9014 		if (link == NULL) {
9015 		    xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
9016 			"allocating a type link", NULL);
9017 		    return (-1);
9018 		}
9019 		link->type = NULL;
9020 		link->next = NULL;
9021 		if (lastLink == NULL)
9022 		    type->memberTypes = link;
9023 		else
9024 		    lastLink->next = link;
9025 		lastLink = link;
9026 		/*
9027 		* Create a reference item.
9028 		*/
9029 		ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_SIMPLE,
9030 		    localName, nsName);
9031 		if (ref == NULL) {
9032 		    FREE_AND_NULL(tmp)
9033 		    return (-1);
9034 		}
9035 		/*
9036 		* Assign the reference to the link, it will be resolved
9037 		* later during fixup of the union simple type.
9038 		*/
9039 		link->type = (xmlSchemaTypePtr) ref;
9040 	    }
9041 	    FREE_AND_NULL(tmp)
9042 	    cur = end;
9043 	} while (*cur != 0);
9044 
9045     }
9046     /*
9047     * And now for the children...
9048     */
9049     child = node->children;
9050     if (IS_SCHEMA(child, "annotation")) {
9051 	/*
9052 	* Add the annotation to the simple type ancestor.
9053 	*/
9054 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9055 	    xmlSchemaParseAnnotation(ctxt, child, 1));
9056         child = child->next;
9057     }
9058     if (IS_SCHEMA(child, "simpleType")) {
9059 	xmlSchemaTypePtr subtype, last = NULL;
9060 
9061 	/*
9062 	* Anchor the member types in the "subtypes" field of the
9063 	* simple type.
9064 	*/
9065 	while (IS_SCHEMA(child, "simpleType")) {
9066 	    subtype = (xmlSchemaTypePtr)
9067 		xmlSchemaParseSimpleType(ctxt, schema, child, 0);
9068 	    if (subtype != NULL) {
9069 		if (last == NULL) {
9070 		    type->subtypes = subtype;
9071 		    last = subtype;
9072 		} else {
9073 		    last->next = subtype;
9074 		    last = subtype;
9075 		}
9076 		last->next = NULL;
9077 	    }
9078 	    child = child->next;
9079 	}
9080     }
9081     if (child != NULL) {
9082 	xmlSchemaPContentErr(ctxt,
9083 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9084 	    NULL, node, child, NULL, "(annotation?, simpleType*)");
9085     }
9086     if ((attr == NULL) && (type->subtypes == NULL)) {
9087 	 /*
9088 	* src-union-memberTypes-or-simpleTypes
9089 	* Either the memberTypes [attribute] of the <union> element must
9090 	* be non-empty or there must be at least one simpleType [child].
9091 	*/
9092 	xmlSchemaPCustomErr(ctxt,
9093 	    XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
9094 	    NULL, node,
9095 	    "Either the attribute 'memberTypes' or "
9096 	    "at least one <simpleType> child must be present", NULL);
9097     }
9098     return (0);
9099 }
9100 
9101 /**
9102  * xmlSchemaParseList:
9103  * @ctxt:  a schema validation context
9104  * @schema:  the schema being built
9105  * @node:  a subtree containing XML Schema information
9106  *
9107  * parse a XML schema List definition
9108  * *WARNING* this interface is highly subject to change
9109  *
9110  * Returns -1 in case of error, 0 if the declaration is improper and
9111  *         1 in case of success.
9112  */
9113 static xmlSchemaTypePtr
xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)9114 xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9115                    xmlNodePtr node)
9116 {
9117     xmlSchemaTypePtr type;
9118     xmlNodePtr child = NULL;
9119     xmlAttrPtr attr;
9120 
9121     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9122         return (NULL);
9123     /* Not a component, don't create it. */
9124     type = ctxt->ctxtType;
9125     /*
9126     * Mark the type as being of variety "list".
9127     */
9128     type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
9129     /*
9130     * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
9131     * then the `simple ur-type definition`."
9132     */
9133     type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
9134     /*
9135     * Check for illegal attributes.
9136     */
9137     attr = node->properties;
9138     while (attr != NULL) {
9139 	if (attr->ns == NULL) {
9140 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9141 		(!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
9142 		xmlSchemaPIllegalAttrErr(ctxt,
9143 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9144 	    }
9145 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9146 	    xmlSchemaPIllegalAttrErr(ctxt,
9147 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9148 	}
9149 	attr = attr->next;
9150     }
9151 
9152     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9153 
9154     /*
9155     * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
9156     * fields for holding the reference to the itemType.
9157     *
9158     * REVAMP TODO: Use the "base" and "baseNs" fields, since we will remove
9159     * the "ref" fields.
9160     */
9161     xmlSchemaPValAttrQName(ctxt, schema, NULL,
9162 	node, "itemType", &(type->baseNs), &(type->base));
9163     /*
9164     * And now for the children...
9165     */
9166     child = node->children;
9167     if (IS_SCHEMA(child, "annotation")) {
9168 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9169 	    xmlSchemaParseAnnotation(ctxt, child, 1));
9170         child = child->next;
9171     }
9172     if (IS_SCHEMA(child, "simpleType")) {
9173 	/*
9174 	* src-list-itemType-or-simpleType
9175 	* Either the itemType [attribute] or the <simpleType> [child] of
9176 	* the <list> element must be present, but not both.
9177 	*/
9178 	if (type->base != NULL) {
9179 	    xmlSchemaPCustomErr(ctxt,
9180 		XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9181 		NULL, node,
9182 		"The attribute 'itemType' and the <simpleType> child "
9183 		"are mutually exclusive", NULL);
9184 	} else {
9185 	    type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
9186 	}
9187         child = child->next;
9188     } else if (type->base == NULL) {
9189 	xmlSchemaPCustomErr(ctxt,
9190 	    XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9191 	    NULL, node,
9192 	    "Either the attribute 'itemType' or the <simpleType> child "
9193 	    "must be present", NULL);
9194     }
9195     if (child != NULL) {
9196 	xmlSchemaPContentErr(ctxt,
9197 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9198 	    NULL, node, child, NULL, "(annotation?, simpleType?)");
9199     }
9200     if ((type->base == NULL) &&
9201 	(type->subtypes == NULL) &&
9202 	(xmlSchemaGetPropNode(node, "itemType") == NULL)) {
9203 	xmlSchemaPCustomErr(ctxt,
9204 	    XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9205 	    NULL, node,
9206 	    "Either the attribute 'itemType' or the <simpleType> child "
9207 	    "must be present", NULL);
9208     }
9209     return (NULL);
9210 }
9211 
9212 /**
9213  * xmlSchemaParseSimpleType:
9214  * @ctxt:  a schema validation context
9215  * @schema:  the schema being built
9216  * @node:  a subtree containing XML Schema information
9217  *
9218  * parse a XML schema Simple Type definition
9219  * *WARNING* this interface is highly subject to change
9220  *
9221  * Returns -1 in case of error, 0 if the declaration is improper and
9222  * 1 in case of success.
9223  */
9224 static xmlSchemaTypePtr
xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int topLevel)9225 xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9226                          xmlNodePtr node, int topLevel)
9227 {
9228     xmlSchemaTypePtr type, oldCtxtType;
9229     xmlNodePtr child = NULL;
9230     const xmlChar *attrValue = NULL;
9231     xmlAttrPtr attr;
9232     int hasRestriction = 0;
9233 
9234     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9235         return (NULL);
9236 
9237     if (topLevel) {
9238 	attr = xmlSchemaGetPropNode(node, "name");
9239 	if (attr == NULL) {
9240 	    xmlSchemaPMissingAttrErr(ctxt,
9241 		XML_SCHEMAP_S4S_ATTR_MISSING,
9242 		NULL, node,
9243 		"name", NULL);
9244 	    return (NULL);
9245 	} else {
9246 	    if (xmlSchemaPValAttrNode(ctxt,
9247 		NULL, attr,
9248 		xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
9249 		return (NULL);
9250 	    /*
9251 	    * Skip built-in types.
9252 	    */
9253 	    if (ctxt->isS4S) {
9254 		xmlSchemaTypePtr biType;
9255 
9256 		if (ctxt->isRedefine) {
9257 		    /*
9258 		    * REDEFINE: Disallow redefinition of built-in-types.
9259 		    * TODO: It seems that the spec does not say anything
9260 		    * about this case.
9261 		    */
9262 		    xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
9263 			NULL, node,
9264 			"Redefinition of built-in simple types is not "
9265 			"supported", NULL);
9266 		    return(NULL);
9267 		}
9268 		biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
9269 		if (biType != NULL)
9270 		    return (biType);
9271 	    }
9272 	}
9273     }
9274     /*
9275     * TargetNamespace:
9276     * SPEC "The `actual value` of the targetNamespace [attribute]
9277     * of the <schema> ancestor element information item if present,
9278     * otherwise `absent`.
9279     */
9280     if (topLevel == 0) {
9281 #ifdef ENABLE_NAMED_LOCALS
9282         char buf[40];
9283 #endif
9284 	/*
9285 	* Parse as local simple type definition.
9286 	*/
9287 #ifdef ENABLE_NAMED_LOCALS
9288         snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
9289 	type = xmlSchemaAddType(ctxt, schema,
9290 	    XML_SCHEMA_TYPE_SIMPLE,
9291 	    xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
9292 	    ctxt->targetNamespace, node, 0);
9293 #else
9294 	type = xmlSchemaAddType(ctxt, schema,
9295 	    XML_SCHEMA_TYPE_SIMPLE,
9296 	    NULL, ctxt->targetNamespace, node, 0);
9297 #endif
9298 	if (type == NULL)
9299 	    return (NULL);
9300 	type->type = XML_SCHEMA_TYPE_SIMPLE;
9301 	type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
9302 	/*
9303 	* Check for illegal attributes.
9304 	*/
9305 	attr = node->properties;
9306 	while (attr != NULL) {
9307 	    if (attr->ns == NULL) {
9308 		if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
9309 		    xmlSchemaPIllegalAttrErr(ctxt,
9310 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9311 		}
9312 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9313 		    xmlSchemaPIllegalAttrErr(ctxt,
9314 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9315 	    }
9316 	    attr = attr->next;
9317 	}
9318     } else {
9319 	/*
9320 	* Parse as global simple type definition.
9321 	*
9322 	* Note that attrValue is the value of the attribute "name" here.
9323 	*/
9324 	type = xmlSchemaAddType(ctxt, schema, XML_SCHEMA_TYPE_SIMPLE,
9325 	    attrValue, ctxt->targetNamespace, node, 1);
9326 	if (type == NULL)
9327 	    return (NULL);
9328 	type->type = XML_SCHEMA_TYPE_SIMPLE;
9329 	type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
9330 	type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
9331 	/*
9332 	* Check for illegal attributes.
9333 	*/
9334 	attr = node->properties;
9335 	while (attr != NULL) {
9336 	    if (attr->ns == NULL) {
9337 		if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9338 		    (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
9339 		    (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
9340 		    xmlSchemaPIllegalAttrErr(ctxt,
9341 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9342 		}
9343 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9344 		xmlSchemaPIllegalAttrErr(ctxt,
9345 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9346 	    }
9347 	    attr = attr->next;
9348 	}
9349 	/*
9350 	* Attribute "final".
9351 	*/
9352 	attr = xmlSchemaGetPropNode(node, "final");
9353 	if (attr == NULL) {
9354 	    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9355 		type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
9356 	    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9357 		type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
9358 	    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9359 		type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
9360 	} else {
9361 	    attrValue = xmlSchemaGetProp(ctxt, node, "final");
9362 	    if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
9363 		-1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
9364 		XML_SCHEMAS_TYPE_FINAL_LIST,
9365 		XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
9366 
9367 		xmlSchemaPSimpleTypeErr(ctxt,
9368 		    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9369 		    WXS_BASIC_CAST type, (xmlNodePtr) attr,
9370 		    NULL, "(#all | List of (list | union | restriction)",
9371 		    attrValue, NULL, NULL, NULL);
9372 	    }
9373 	}
9374     }
9375     type->targetNamespace = ctxt->targetNamespace;
9376     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9377     /*
9378     * And now for the children...
9379     */
9380     oldCtxtType = ctxt->ctxtType;
9381 
9382     ctxt->ctxtType = type;
9383 
9384     child = node->children;
9385     if (IS_SCHEMA(child, "annotation")) {
9386         type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9387         child = child->next;
9388     }
9389     if (child == NULL) {
9390 	xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
9391 	    NULL, node, child, NULL,
9392 	    "(annotation?, (restriction | list | union))");
9393     } else if (IS_SCHEMA(child, "restriction")) {
9394         xmlSchemaParseRestriction(ctxt, schema, child,
9395 	    XML_SCHEMA_TYPE_SIMPLE);
9396 	hasRestriction = 1;
9397         child = child->next;
9398     } else if (IS_SCHEMA(child, "list")) {
9399         xmlSchemaParseList(ctxt, schema, child);
9400         child = child->next;
9401     } else if (IS_SCHEMA(child, "union")) {
9402         xmlSchemaParseUnion(ctxt, schema, child);
9403         child = child->next;
9404     }
9405     if (child != NULL) {
9406 	xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9407 	    NULL, node, child, NULL,
9408 	    "(annotation?, (restriction | list | union))");
9409     }
9410     /*
9411     * REDEFINE: SPEC src-redefine (5)
9412     * "Within the [children], each <simpleType> must have a
9413     * <restriction> among its [children] ... the `actual value` of whose
9414     * base [attribute] must be the same as the `actual value` of its own
9415     * name attribute plus target namespace;"
9416     */
9417     if (topLevel && ctxt->isRedefine && (! hasRestriction)) {
9418 	xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
9419 	    NULL, node, "This is a redefinition, thus the "
9420 	    "<simpleType> must have a <restriction> child", NULL);
9421     }
9422 
9423     ctxt->ctxtType = oldCtxtType;
9424     return (type);
9425 }
9426 
9427 /**
9428  * xmlSchemaParseModelGroupDefRef:
9429  * @ctxt:  the parser context
9430  * @schema: the schema being built
9431  * @node:  the node
9432  *
9433  * Parses a reference to a model group definition.
9434  *
9435  * We will return a particle component with a qname-component or
9436  * NULL in case of an error.
9437  */
9438 static xmlSchemaTreeItemPtr
xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)9439 xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
9440 			       xmlSchemaPtr schema,
9441 			       xmlNodePtr node)
9442 {
9443     xmlSchemaParticlePtr item;
9444     xmlNodePtr child = NULL;
9445     xmlAttrPtr attr;
9446     const xmlChar *ref = NULL, *refNs = NULL;
9447     int min, max;
9448 
9449     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9450         return (NULL);
9451 
9452     attr = xmlSchemaGetPropNode(node, "ref");
9453     if (attr == NULL) {
9454 	xmlSchemaPMissingAttrErr(ctxt,
9455 	    XML_SCHEMAP_S4S_ATTR_MISSING,
9456 	    NULL, node, "ref", NULL);
9457 	return (NULL);
9458     } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL,
9459 	attr, &refNs, &ref) != 0) {
9460 	return (NULL);
9461     }
9462     xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
9463     min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
9464     max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
9465 	"(xs:nonNegativeInteger | unbounded)");
9466     /*
9467     * Check for illegal attributes.
9468     */
9469     attr = node->properties;
9470     while (attr != NULL) {
9471 	if (attr->ns == NULL) {
9472 	    if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
9473 		(!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9474 		(!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
9475 		(!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
9476 		xmlSchemaPIllegalAttrErr(ctxt,
9477 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9478 	    }
9479 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9480 	    xmlSchemaPIllegalAttrErr(ctxt,
9481 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9482 	}
9483 	attr = attr->next;
9484     }
9485     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9486     item = xmlSchemaAddParticle(ctxt, node, min, max);
9487     if (item == NULL)
9488 	return (NULL);
9489     /*
9490     * Create a qname-reference and set as the term; it will be substituted
9491     * for the model group after the reference has been resolved.
9492     */
9493     item->children = (xmlSchemaTreeItemPtr)
9494 	xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_GROUP, ref, refNs);
9495     xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
9496     /*
9497     * And now for the children...
9498     */
9499     child = node->children;
9500     /* TODO: Is annotation even allowed for a model group reference? */
9501     if (IS_SCHEMA(child, "annotation")) {
9502 	/*
9503 	* TODO: What to do exactly with the annotation?
9504 	*/
9505 	item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9506 	child = child->next;
9507     }
9508     if (child != NULL) {
9509 	xmlSchemaPContentErr(ctxt,
9510 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9511 	    NULL, node, child, NULL,
9512 	    "(annotation?)");
9513     }
9514     /*
9515     * Corresponds to no component at all if minOccurs==maxOccurs==0.
9516     */
9517     if ((min == 0) && (max == 0))
9518 	return (NULL);
9519 
9520     return ((xmlSchemaTreeItemPtr) item);
9521 }
9522 
9523 /**
9524  * xmlSchemaParseModelGroupDefinition:
9525  * @ctxt:  a schema validation context
9526  * @schema:  the schema being built
9527  * @node:  a subtree containing XML Schema information
9528  *
9529  * Parses a XML schema model group definition.
9530  *
9531  * Note that the constraint src-redefine (6.2) can't be applied until
9532  * references have been resolved. So we will do this at the
9533  * component fixup level.
9534  *
9535  * *WARNING* this interface is highly subject to change
9536  *
9537  * Returns -1 in case of error, 0 if the declaration is improper and
9538  *         1 in case of success.
9539  */
9540 static xmlSchemaModelGroupDefPtr
xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)9541 xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
9542 				   xmlSchemaPtr schema,
9543 				   xmlNodePtr node)
9544 {
9545     xmlSchemaModelGroupDefPtr item;
9546     xmlNodePtr child = NULL;
9547     xmlAttrPtr attr;
9548     const xmlChar *name;
9549 
9550     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9551         return (NULL);
9552 
9553     attr = xmlSchemaGetPropNode(node, "name");
9554     if (attr == NULL) {
9555 	xmlSchemaPMissingAttrErr(ctxt,
9556 	    XML_SCHEMAP_S4S_ATTR_MISSING,
9557 	    NULL, node,
9558 	    "name", NULL);
9559 	return (NULL);
9560     } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
9561 	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
9562 	return (NULL);
9563     }
9564     item = xmlSchemaAddModelGroupDefinition(ctxt, schema, name,
9565 	ctxt->targetNamespace, node);
9566     if (item == NULL)
9567 	return (NULL);
9568     /*
9569     * Check for illegal attributes.
9570     */
9571     attr = node->properties;
9572     while (attr != NULL) {
9573 	if (attr->ns == NULL) {
9574 	    if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
9575 		(!xmlStrEqual(attr->name, BAD_CAST "id"))) {
9576 		xmlSchemaPIllegalAttrErr(ctxt,
9577 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9578 	    }
9579 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9580 	    xmlSchemaPIllegalAttrErr(ctxt,
9581 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9582 	}
9583 	attr = attr->next;
9584     }
9585     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9586     /*
9587     * And now for the children...
9588     */
9589     child = node->children;
9590     if (IS_SCHEMA(child, "annotation")) {
9591 	item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9592 	child = child->next;
9593     }
9594     if (IS_SCHEMA(child, "all")) {
9595 	item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9596 	    XML_SCHEMA_TYPE_ALL, 0);
9597 	child = child->next;
9598     } else if (IS_SCHEMA(child, "choice")) {
9599 	item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9600 	    XML_SCHEMA_TYPE_CHOICE, 0);
9601 	child = child->next;
9602     } else if (IS_SCHEMA(child, "sequence")) {
9603 	item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9604 	    XML_SCHEMA_TYPE_SEQUENCE, 0);
9605 	child = child->next;
9606     }
9607 
9608 
9609 
9610     if (child != NULL) {
9611 	xmlSchemaPContentErr(ctxt,
9612 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9613 	    NULL, node, child, NULL,
9614 	    "(annotation?, (all | choice | sequence)?)");
9615     }
9616     return (item);
9617 }
9618 
9619 /**
9620  * xmlSchemaCleanupDoc:
9621  * @ctxt:  a schema validation context
9622  * @node:  the root of the document.
9623  *
9624  * removes unwanted nodes in a schemas document tree
9625  */
9626 static void
xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr root)9627 xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
9628 {
9629     xmlNodePtr delete, cur;
9630 
9631     if ((ctxt == NULL) || (root == NULL)) return;
9632 
9633     /*
9634      * Remove all the blank text nodes
9635      */
9636     delete = NULL;
9637     cur = root;
9638     while (cur != NULL) {
9639         if (delete != NULL) {
9640             xmlUnlinkNode(delete);
9641             xmlFreeNode(delete);
9642             delete = NULL;
9643         }
9644         if (cur->type == XML_TEXT_NODE) {
9645             if (IS_BLANK_NODE(cur)) {
9646                 if (xmlNodeGetSpacePreserve(cur) != 1) {
9647                     delete = cur;
9648                 }
9649             }
9650         } else if ((cur->type != XML_ELEMENT_NODE) &&
9651                    (cur->type != XML_CDATA_SECTION_NODE)) {
9652             delete = cur;
9653             goto skip_children;
9654         }
9655 
9656         /*
9657          * Skip to next node
9658          */
9659         if (cur->children != NULL) {
9660             if ((cur->children->type != XML_ENTITY_DECL) &&
9661                 (cur->children->type != XML_ENTITY_REF_NODE) &&
9662                 (cur->children->type != XML_ENTITY_NODE)) {
9663                 cur = cur->children;
9664                 continue;
9665             }
9666         }
9667       skip_children:
9668         if (cur->next != NULL) {
9669             cur = cur->next;
9670             continue;
9671         }
9672 
9673         do {
9674             cur = cur->parent;
9675             if (cur == NULL)
9676                 break;
9677             if (cur == root) {
9678                 cur = NULL;
9679                 break;
9680             }
9681             if (cur->next != NULL) {
9682                 cur = cur->next;
9683                 break;
9684             }
9685         } while (cur != NULL);
9686     }
9687     if (delete != NULL) {
9688         xmlUnlinkNode(delete);
9689         xmlFreeNode(delete);
9690         delete = NULL;
9691     }
9692 }
9693 
9694 
9695 static void
xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)9696 xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
9697 {
9698     if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
9699 	schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
9700 
9701     if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
9702 	schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
9703 
9704     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
9705 	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
9706     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9707 	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
9708     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9709 	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
9710     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9711 	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
9712 
9713     if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
9714 	schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
9715     if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
9716 	schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
9717     if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
9718 	schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
9719 }
9720 
9721 static int
xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)9722 xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt,
9723 			     xmlSchemaPtr schema,
9724 			     xmlNodePtr node)
9725 {
9726     xmlAttrPtr attr;
9727     const xmlChar *val;
9728     int res = 0, oldErrs = ctxt->nberrors;
9729 
9730     /*
9731     * Those flags should be moved to the parser context flags,
9732     * since they are not visible at the component level. I.e.
9733     * they are used if processing schema *documents* only.
9734     */
9735     res = xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9736     HFAILURE;
9737 
9738     /*
9739     * Since the version is of type xs:token, we won't bother to
9740     * check it.
9741     */
9742     /* REMOVED:
9743     attr = xmlSchemaGetPropNode(node, "version");
9744     if (attr != NULL) {
9745 	res = xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9746 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &val);
9747 	HFAILURE;
9748     }
9749     */
9750     attr = xmlSchemaGetPropNode(node, "targetNamespace");
9751     if (attr != NULL) {
9752 	res = xmlSchemaPValAttrNode(ctxt, NULL, attr,
9753 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
9754 	HFAILURE;
9755 	if (res != 0) {
9756 	    ctxt->stop = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
9757 	    goto exit;
9758 	}
9759     }
9760     attr = xmlSchemaGetPropNode(node, "elementFormDefault");
9761     if (attr != NULL) {
9762 	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9763 	res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9764 	    XML_SCHEMAS_QUALIF_ELEM);
9765 	HFAILURE;
9766 	if (res != 0) {
9767 	    xmlSchemaPSimpleTypeErr(ctxt,
9768 		XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
9769 		NULL, (xmlNodePtr) attr, NULL,
9770 		"(qualified | unqualified)", val, NULL, NULL, NULL);
9771 	}
9772     }
9773     attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
9774     if (attr != NULL) {
9775 	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9776 	res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9777 	    XML_SCHEMAS_QUALIF_ATTR);
9778 	HFAILURE;
9779 	if (res != 0) {
9780 	    xmlSchemaPSimpleTypeErr(ctxt,
9781 		XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
9782 		NULL, (xmlNodePtr) attr, NULL,
9783 		"(qualified | unqualified)", val, NULL, NULL, NULL);
9784 	}
9785     }
9786     attr = xmlSchemaGetPropNode(node, "finalDefault");
9787     if (attr != NULL) {
9788 	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9789 	res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
9790 	    XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
9791 	    XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
9792 	    -1,
9793 	    XML_SCHEMAS_FINAL_DEFAULT_LIST,
9794 	    XML_SCHEMAS_FINAL_DEFAULT_UNION);
9795 	HFAILURE;
9796 	if (res != 0) {
9797 	    xmlSchemaPSimpleTypeErr(ctxt,
9798 		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9799 		NULL, (xmlNodePtr) attr, NULL,
9800 		"(#all | List of (extension | restriction | list | union))",
9801 		val, NULL, NULL, NULL);
9802 	}
9803     }
9804     attr = xmlSchemaGetPropNode(node, "blockDefault");
9805     if (attr != NULL) {
9806 	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9807 	res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
9808 	    XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
9809 	    XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
9810 	    XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1);
9811 	HFAILURE;
9812 	if (res != 0) {
9813 	    xmlSchemaPSimpleTypeErr(ctxt,
9814 		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9815 		NULL, (xmlNodePtr) attr, NULL,
9816 		"(#all | List of (extension | restriction | substitution))",
9817 		val, NULL, NULL, NULL);
9818 	}
9819     }
9820 
9821 exit:
9822     if (oldErrs != ctxt->nberrors)
9823 	res = ctxt->err;
9824     return(res);
9825 exit_failure:
9826     return(-1);
9827 }
9828 
9829 /**
9830  * xmlSchemaParseSchemaTopLevel:
9831  * @ctxt:  a schema validation context
9832  * @schema:  the schemas
9833  * @nodes:  the list of top level nodes
9834  *
9835  * Returns the internal XML Schema structure built from the resource or
9836  *         NULL in case of error
9837  */
9838 static int
xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr nodes)9839 xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
9840                              xmlSchemaPtr schema, xmlNodePtr nodes)
9841 {
9842     xmlNodePtr child;
9843     xmlSchemaAnnotPtr annot;
9844     int res = 0, oldErrs, tmpOldErrs;
9845 
9846     if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
9847         return(-1);
9848 
9849     oldErrs = ctxt->nberrors;
9850     child = nodes;
9851     while ((IS_SCHEMA(child, "include")) ||
9852 	   (IS_SCHEMA(child, "import")) ||
9853 	   (IS_SCHEMA(child, "redefine")) ||
9854 	   (IS_SCHEMA(child, "annotation"))) {
9855 	if (IS_SCHEMA(child, "annotation")) {
9856 	    annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9857 	    if (schema->annot == NULL)
9858 		schema->annot = annot;
9859 	    else
9860 		xmlSchemaFreeAnnot(annot);
9861 	} else if (IS_SCHEMA(child, "import")) {
9862 	    tmpOldErrs = ctxt->nberrors;
9863 	    res = xmlSchemaParseImport(ctxt, schema, child);
9864 	    HFAILURE;
9865 	    HSTOP(ctxt);
9866 	    if (tmpOldErrs != ctxt->nberrors)
9867 		goto exit;
9868 	} else if (IS_SCHEMA(child, "include")) {
9869 	    tmpOldErrs = ctxt->nberrors;
9870 	    res = xmlSchemaParseInclude(ctxt, schema, child);
9871 	    HFAILURE;
9872 	    HSTOP(ctxt);
9873 	    if (tmpOldErrs != ctxt->nberrors)
9874 		goto exit;
9875 	} else if (IS_SCHEMA(child, "redefine")) {
9876 	    tmpOldErrs = ctxt->nberrors;
9877 	    res = xmlSchemaParseRedefine(ctxt, schema, child);
9878 	    HFAILURE;
9879 	    HSTOP(ctxt);
9880 	    if (tmpOldErrs != ctxt->nberrors)
9881 		goto exit;
9882 	}
9883 	child = child->next;
9884     }
9885     /*
9886     * URGENT TODO: Change the functions to return int results.
9887     * We need especially to catch internal errors.
9888     */
9889     while (child != NULL) {
9890 	if (IS_SCHEMA(child, "complexType")) {
9891 	    xmlSchemaParseComplexType(ctxt, schema, child, 1);
9892 	    child = child->next;
9893 	} else if (IS_SCHEMA(child, "simpleType")) {
9894 	    xmlSchemaParseSimpleType(ctxt, schema, child, 1);
9895 	    child = child->next;
9896 	} else if (IS_SCHEMA(child, "element")) {
9897 	    xmlSchemaParseElement(ctxt, schema, child, NULL, 1);
9898 	    child = child->next;
9899 	} else if (IS_SCHEMA(child, "attribute")) {
9900 	    xmlSchemaParseGlobalAttribute(ctxt, schema, child);
9901 	    child = child->next;
9902 	} else if (IS_SCHEMA(child, "attributeGroup")) {
9903 	    xmlSchemaParseAttributeGroupDefinition(ctxt, schema, child);
9904 	    child = child->next;
9905 	} else if (IS_SCHEMA(child, "group")) {
9906 	    xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
9907 	    child = child->next;
9908 	} else if (IS_SCHEMA(child, "notation")) {
9909 	    xmlSchemaParseNotation(ctxt, schema, child);
9910 	    child = child->next;
9911 	} else {
9912 	    xmlSchemaPContentErr(ctxt,
9913 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9914 		NULL, child->parent, child,
9915 		NULL, "((include | import | redefine | annotation)*, "
9916 		"(((simpleType | complexType | group | attributeGroup) "
9917 		"| element | attribute | notation), annotation*)*)");
9918 	    child = child->next;
9919 	}
9920 	while (IS_SCHEMA(child, "annotation")) {
9921 	    /*
9922 	    * TODO: We should add all annotations.
9923 	    */
9924 	    annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9925 	    if (schema->annot == NULL)
9926 		schema->annot = annot;
9927 	    else
9928 		xmlSchemaFreeAnnot(annot);
9929 	    child = child->next;
9930 	}
9931     }
9932 exit:
9933     ctxt->ctxtType = NULL;
9934     if (oldErrs != ctxt->nberrors)
9935 	res = ctxt->err;
9936     return(res);
9937 exit_failure:
9938     return(-1);
9939 }
9940 
9941 static xmlSchemaSchemaRelationPtr
xmlSchemaSchemaRelationCreate(void)9942 xmlSchemaSchemaRelationCreate(void)
9943 {
9944     xmlSchemaSchemaRelationPtr ret;
9945 
9946     ret = (xmlSchemaSchemaRelationPtr)
9947 	xmlMalloc(sizeof(xmlSchemaSchemaRelation));
9948     if (ret == NULL) {
9949 	xmlSchemaPErrMemory(NULL, "allocating schema relation", NULL);
9950 	return(NULL);
9951     }
9952     memset(ret, 0, sizeof(xmlSchemaSchemaRelation));
9953     return(ret);
9954 }
9955 
9956 #if 0
9957 static void
9958 xmlSchemaSchemaRelationFree(xmlSchemaSchemaRelationPtr rel)
9959 {
9960     xmlFree(rel);
9961 }
9962 #endif
9963 
9964 static void
xmlSchemaRedefListFree(xmlSchemaRedefPtr redef)9965 xmlSchemaRedefListFree(xmlSchemaRedefPtr redef)
9966 {
9967     xmlSchemaRedefPtr prev;
9968 
9969     while (redef != NULL) {
9970 	prev = redef;
9971 	redef = redef->next;
9972 	xmlFree(prev);
9973     }
9974 }
9975 
9976 static void
xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con)9977 xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con)
9978 {
9979     /*
9980     * After the construction context has been freed, there will be
9981     * no schema graph available any more. Only the schema buckets
9982     * will stay alive, which are put into the "schemasImports" and
9983     * "includes" slots of the xmlSchema.
9984     */
9985     if (con->buckets != NULL)
9986 	xmlSchemaItemListFree(con->buckets);
9987     if (con->pending != NULL)
9988 	xmlSchemaItemListFree(con->pending);
9989     if (con->substGroups != NULL)
9990 	xmlHashFree(con->substGroups, xmlSchemaSubstGroupFreeEntry);
9991     if (con->redefs != NULL)
9992 	xmlSchemaRedefListFree(con->redefs);
9993     if (con->dict != NULL)
9994 	xmlDictFree(con->dict);
9995     xmlFree(con);
9996 }
9997 
9998 static xmlSchemaConstructionCtxtPtr
xmlSchemaConstructionCtxtCreate(xmlDictPtr dict)9999 xmlSchemaConstructionCtxtCreate(xmlDictPtr dict)
10000 {
10001     xmlSchemaConstructionCtxtPtr ret;
10002 
10003     ret = (xmlSchemaConstructionCtxtPtr)
10004 	xmlMalloc(sizeof(xmlSchemaConstructionCtxt));
10005     if (ret == NULL) {
10006         xmlSchemaPErrMemory(NULL,
10007 	    "allocating schema construction context", NULL);
10008         return (NULL);
10009     }
10010     memset(ret, 0, sizeof(xmlSchemaConstructionCtxt));
10011 
10012     ret->buckets = xmlSchemaItemListCreate();
10013     if (ret->buckets == NULL) {
10014 	xmlSchemaPErrMemory(NULL,
10015 	    "allocating list of schema buckets", NULL);
10016 	xmlFree(ret);
10017         return (NULL);
10018     }
10019     ret->pending = xmlSchemaItemListCreate();
10020     if (ret->pending == NULL) {
10021 	xmlSchemaPErrMemory(NULL,
10022 	    "allocating list of pending global components", NULL);
10023 	xmlSchemaConstructionCtxtFree(ret);
10024         return (NULL);
10025     }
10026     ret->dict = dict;
10027     xmlDictReference(dict);
10028     return(ret);
10029 }
10030 
10031 static xmlSchemaParserCtxtPtr
xmlSchemaParserCtxtCreate(void)10032 xmlSchemaParserCtxtCreate(void)
10033 {
10034     xmlSchemaParserCtxtPtr ret;
10035 
10036     ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10037     if (ret == NULL) {
10038         xmlSchemaPErrMemory(NULL, "allocating schema parser context",
10039                             NULL);
10040         return (NULL);
10041     }
10042     memset(ret, 0, sizeof(xmlSchemaParserCtxt));
10043     ret->type = XML_SCHEMA_CTXT_PARSER;
10044     ret->attrProhibs = xmlSchemaItemListCreate();
10045     if (ret->attrProhibs == NULL) {
10046 	xmlFree(ret);
10047 	return(NULL);
10048     }
10049     return(ret);
10050 }
10051 
10052 /**
10053  * xmlSchemaNewParserCtxtUseDict:
10054  * @URL:  the location of the schema
10055  * @dict: the dictionary to be used
10056  *
10057  * Create an XML Schemas parse context for that file/resource expected
10058  * to contain an XML Schemas file.
10059  *
10060  * Returns the parser context or NULL in case of error
10061  */
10062 static xmlSchemaParserCtxtPtr
xmlSchemaNewParserCtxtUseDict(const char * URL,xmlDictPtr dict)10063 xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
10064 {
10065     xmlSchemaParserCtxtPtr ret;
10066 
10067     ret = xmlSchemaParserCtxtCreate();
10068     if (ret == NULL)
10069         return (NULL);
10070     ret->dict = dict;
10071     xmlDictReference(dict);
10072     if (URL != NULL)
10073 	ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
10074     return (ret);
10075 }
10076 
10077 static int
xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)10078 xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
10079 {
10080     if (vctxt->pctxt == NULL) {
10081         if (vctxt->schema != NULL)
10082 	    vctxt->pctxt =
10083 		xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
10084 	else
10085 	    vctxt->pctxt = xmlSchemaNewParserCtxt("*");
10086 	if (vctxt->pctxt == NULL) {
10087 	    VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
10088 		"failed to create a temp. parser context");
10089 	    return (-1);
10090 	}
10091 	/* TODO: Pass user data. */
10092 	xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error,
10093 	    vctxt->warning, vctxt->errCtxt);
10094 	xmlSchemaSetParserStructuredErrors(vctxt->pctxt, vctxt->serror,
10095 	    vctxt->errCtxt);
10096     }
10097     return (0);
10098 }
10099 
10100 /**
10101  * xmlSchemaGetSchemaBucket:
10102  * @pctxt: the schema parser context
10103  * @schemaLocation: the URI of the schema document
10104  *
10105  * Returns a schema bucket if it was already parsed.
10106  *
10107  * Returns a schema bucket if it was already parsed from
10108  *         @schemaLocation, NULL otherwise.
10109  */
10110 static xmlSchemaBucketPtr
xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt,const xmlChar * schemaLocation)10111 xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10112 			    const xmlChar *schemaLocation)
10113 {
10114     xmlSchemaBucketPtr cur;
10115     xmlSchemaItemListPtr list;
10116 
10117     list = pctxt->constructor->buckets;
10118     if (list->nbItems == 0)
10119 	return(NULL);
10120     else {
10121 	int i;
10122 	for (i = 0; i < list->nbItems; i++) {
10123 	    cur = (xmlSchemaBucketPtr) list->items[i];
10124 	    /* Pointer comparison! */
10125 	    if (cur->schemaLocation == schemaLocation)
10126 		return(cur);
10127 	}
10128     }
10129     return(NULL);
10130 }
10131 
10132 static xmlSchemaBucketPtr
xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt,const xmlChar * schemaLocation,const xmlChar * targetNamespace)10133 xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10134 				     const xmlChar *schemaLocation,
10135 				     const xmlChar *targetNamespace)
10136 {
10137     xmlSchemaBucketPtr cur;
10138     xmlSchemaItemListPtr list;
10139 
10140     list = pctxt->constructor->buckets;
10141     if (list->nbItems == 0)
10142 	return(NULL);
10143     else {
10144 	int i;
10145 	for (i = 0; i < list->nbItems; i++) {
10146 	    cur = (xmlSchemaBucketPtr) list->items[i];
10147 	    /* Pointer comparison! */
10148 	    if ((cur->origTargetNamespace == NULL) &&
10149 		(cur->schemaLocation == schemaLocation) &&
10150 		(cur->targetNamespace == targetNamespace))
10151 		return(cur);
10152 	}
10153     }
10154     return(NULL);
10155 }
10156 
10157 
10158 #define IS_BAD_SCHEMA_DOC(b) \
10159     (((b)->doc == NULL) && ((b)->schemaLocation != NULL))
10160 
10161 static xmlSchemaBucketPtr
xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt,const xmlChar * targetNamespace,int imported)10162 xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt,
10163 				 const xmlChar *targetNamespace,
10164 				 int imported)
10165 {
10166     xmlSchemaBucketPtr cur;
10167     xmlSchemaItemListPtr list;
10168 
10169     list = pctxt->constructor->buckets;
10170     if (list->nbItems == 0)
10171 	return(NULL);
10172     else {
10173 	int i;
10174 	for (i = 0; i < list->nbItems; i++) {
10175 	    cur = (xmlSchemaBucketPtr) list->items[i];
10176 	    if ((! IS_BAD_SCHEMA_DOC(cur)) &&
10177 		(cur->origTargetNamespace == targetNamespace) &&
10178 		((imported && cur->imported) ||
10179 		 ((!imported) && (!cur->imported))))
10180 		return(cur);
10181 	}
10182     }
10183     return(NULL);
10184 }
10185 
10186 static int
xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlSchemaBucketPtr bucket)10187 xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt,
10188 		     xmlSchemaPtr schema,
10189 		     xmlSchemaBucketPtr bucket)
10190 {
10191     int oldFlags;
10192     xmlDocPtr oldDoc;
10193     xmlNodePtr node;
10194     int ret, oldErrs;
10195     xmlSchemaBucketPtr oldbucket = pctxt->constructor->bucket;
10196 
10197     /*
10198     * Save old values; reset the *main* schema.
10199     * URGENT TODO: This is not good; move the per-document information
10200     * to the parser. Get rid of passing the main schema to the
10201     * parsing functions.
10202     */
10203     oldFlags = schema->flags;
10204     oldDoc = schema->doc;
10205     if (schema->flags != 0)
10206 	xmlSchemaClearSchemaDefaults(schema);
10207     schema->doc = bucket->doc;
10208     pctxt->schema = schema;
10209     /*
10210     * Keep the current target namespace on the parser *not* on the
10211     * main schema.
10212     */
10213     pctxt->targetNamespace = bucket->targetNamespace;
10214     WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
10215 
10216     if ((bucket->targetNamespace != NULL) &&
10217 	xmlStrEqual(bucket->targetNamespace, xmlSchemaNs)) {
10218 	/*
10219 	* We are parsing the schema for schemas!
10220 	*/
10221 	pctxt->isS4S = 1;
10222     }
10223     /* Mark it as parsed, even if parsing fails. */
10224     bucket->parsed++;
10225     /* Compile the schema doc. */
10226     node = xmlDocGetRootElement(bucket->doc);
10227     ret = xmlSchemaParseSchemaElement(pctxt, schema, node);
10228     if (ret != 0)
10229 	goto exit;
10230     /* An empty schema; just get out. */
10231     if (node->children == NULL)
10232 	goto exit;
10233     oldErrs = pctxt->nberrors;
10234     ret = xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
10235     if (ret != 0)
10236 	goto exit;
10237     /*
10238     * TODO: Not nice, but I'm not 100% sure we will get always an error
10239     * as a result of the above functions; so better rely on pctxt->err
10240     * as well.
10241     */
10242     if ((ret == 0) && (oldErrs != pctxt->nberrors)) {
10243 	ret = pctxt->err;
10244 	goto exit;
10245     }
10246 
10247 exit:
10248     WXS_CONSTRUCTOR(pctxt)->bucket = oldbucket;
10249     /* Restore schema values. */
10250     schema->doc = oldDoc;
10251     schema->flags = oldFlags;
10252     return(ret);
10253 }
10254 
10255 static int
xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlSchemaBucketPtr bucket)10256 xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt,
10257 		     xmlSchemaPtr schema,
10258 		     xmlSchemaBucketPtr bucket)
10259 {
10260     xmlSchemaParserCtxtPtr newpctxt;
10261     int res = 0;
10262 
10263     if (bucket == NULL)
10264 	return(0);
10265     if (bucket->parsed) {
10266 	PERROR_INT("xmlSchemaParseNewDoc",
10267 	    "reparsing a schema doc");
10268 	return(-1);
10269     }
10270     if (bucket->doc == NULL) {
10271 	PERROR_INT("xmlSchemaParseNewDoc",
10272 	    "parsing a schema doc, but there's no doc");
10273 	return(-1);
10274     }
10275     if (pctxt->constructor == NULL) {
10276 	PERROR_INT("xmlSchemaParseNewDoc",
10277 	    "no constructor");
10278 	return(-1);
10279     }
10280     /* Create and init the temporary parser context. */
10281     newpctxt = xmlSchemaNewParserCtxtUseDict(
10282 	(const char *) bucket->schemaLocation, pctxt->dict);
10283     if (newpctxt == NULL)
10284 	return(-1);
10285     newpctxt->constructor = pctxt->constructor;
10286     /*
10287     * TODO: Can we avoid that the parser knows about the main schema?
10288     * It would be better if he knows about the current schema bucket
10289     * only.
10290     */
10291     newpctxt->schema = schema;
10292     xmlSchemaSetParserErrors(newpctxt, pctxt->error, pctxt->warning,
10293 	pctxt->errCtxt);
10294     xmlSchemaSetParserStructuredErrors(newpctxt, pctxt->serror,
10295 	pctxt->errCtxt);
10296     newpctxt->counter = pctxt->counter;
10297 
10298 
10299     res = xmlSchemaParseNewDocWithContext(newpctxt, schema, bucket);
10300 
10301     /* Channel back errors and cleanup the temporary parser context. */
10302     if (res != 0)
10303 	pctxt->err = res;
10304     pctxt->nberrors += newpctxt->nberrors;
10305     pctxt->counter = newpctxt->counter;
10306     newpctxt->constructor = NULL;
10307     /* Free the parser context. */
10308     xmlSchemaFreeParserCtxt(newpctxt);
10309     return(res);
10310 }
10311 
10312 static void
xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket,xmlSchemaSchemaRelationPtr rel)10313 xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket,
10314 				xmlSchemaSchemaRelationPtr rel)
10315 {
10316     xmlSchemaSchemaRelationPtr cur = bucket->relations;
10317 
10318     if (cur == NULL) {
10319 	bucket->relations = rel;
10320 	return;
10321     }
10322     while (cur->next != NULL)
10323 	cur = cur->next;
10324     cur->next = rel;
10325 }
10326 
10327 
10328 static const xmlChar *
xmlSchemaBuildAbsoluteURI(xmlDictPtr dict,const xmlChar * location,xmlNodePtr ctxtNode)10329 xmlSchemaBuildAbsoluteURI(xmlDictPtr dict, const xmlChar* location,
10330 			  xmlNodePtr ctxtNode)
10331 {
10332     /*
10333     * Build an absolute location URI.
10334     */
10335     if (location != NULL) {
10336 	if (ctxtNode == NULL)
10337 	    return(location);
10338 	else {
10339 	    xmlChar *base, *URI;
10340 	    const xmlChar *ret = NULL;
10341 
10342 	    base = xmlNodeGetBase(ctxtNode->doc, ctxtNode);
10343 	    if (base == NULL) {
10344 		URI = xmlBuildURI(location, ctxtNode->doc->URL);
10345 	    } else {
10346 		URI = xmlBuildURI(location, base);
10347 		xmlFree(base);
10348 	    }
10349 	    if (URI != NULL) {
10350 		ret = xmlDictLookup(dict, URI, -1);
10351 		xmlFree(URI);
10352 		return(ret);
10353 	    }
10354 	}
10355     }
10356     return(NULL);
10357 }
10358 
10359 
10360 
10361 /**
10362  * xmlSchemaAddSchemaDoc:
10363  * @pctxt:  a schema validation context
10364  * @schema:  the schema being built
10365  * @node:  a subtree containing XML Schema information
10366  *
10367  * Parse an included (and to-be-redefined) XML schema document.
10368  *
10369  * Returns 0 on success, a positive error code on errors and
10370  *         -1 in case of an internal or API error.
10371  */
10372 
10373 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)10374 xmlSchemaAddSchemaDoc(xmlSchemaParserCtxtPtr pctxt,
10375 		int type, /* import or include or redefine */
10376 		const xmlChar *schemaLocation,
10377 		xmlDocPtr schemaDoc,
10378 		const char *schemaBuffer,
10379 		int schemaBufferLen,
10380 		xmlNodePtr invokingNode,
10381 		const xmlChar *sourceTargetNamespace,
10382 		const xmlChar *importNamespace,
10383 		xmlSchemaBucketPtr *bucket)
10384 {
10385     const xmlChar *targetNamespace = NULL;
10386     xmlSchemaSchemaRelationPtr relation = NULL;
10387     xmlDocPtr doc = NULL;
10388     int res = 0, err = 0, located = 0, preserveDoc = 0;
10389     xmlSchemaBucketPtr bkt = NULL;
10390 
10391     if (bucket != NULL)
10392 	*bucket = NULL;
10393 
10394     switch (type) {
10395 	case XML_SCHEMA_SCHEMA_IMPORT:
10396 	case XML_SCHEMA_SCHEMA_MAIN:
10397 	    err = XML_SCHEMAP_SRC_IMPORT;
10398 	    break;
10399 	case XML_SCHEMA_SCHEMA_INCLUDE:
10400 	    err = XML_SCHEMAP_SRC_INCLUDE;
10401 	    break;
10402 	case XML_SCHEMA_SCHEMA_REDEFINE:
10403 	    err = XML_SCHEMAP_SRC_REDEFINE;
10404 	    break;
10405     }
10406 
10407 
10408     /* Special handling for the main schema:
10409     * skip the location and relation logic and just parse the doc.
10410     * We need just a bucket to be returned in this case.
10411     */
10412     if ((type == XML_SCHEMA_SCHEMA_MAIN) || (! WXS_HAS_BUCKETS(pctxt)))
10413 	goto doc_load;
10414 
10415     /* Note that we expect the location to be an absolute URI. */
10416     if (schemaLocation != NULL) {
10417 	bkt = xmlSchemaGetSchemaBucket(pctxt, schemaLocation);
10418 	if ((bkt != NULL) &&
10419 	    (pctxt->constructor->bucket == bkt)) {
10420 	    /* Report self-imports/inclusions/redefinitions. */
10421 
10422 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10423 		invokingNode, NULL,
10424 		"The schema must not import/include/redefine itself",
10425 		NULL, NULL);
10426 	    goto exit;
10427 	}
10428     }
10429     /*
10430     * Create a relation for the graph of schemas.
10431     */
10432     relation = xmlSchemaSchemaRelationCreate();
10433     if (relation == NULL)
10434 	return(-1);
10435     xmlSchemaSchemaRelationAddChild(pctxt->constructor->bucket,
10436 	relation);
10437     relation->type = type;
10438 
10439     /*
10440     * Save the namespace import information.
10441     */
10442     if (WXS_IS_BUCKET_IMPMAIN(type)) {
10443 	relation->importNamespace = importNamespace;
10444 	if (schemaLocation == NULL) {
10445 	    /*
10446 	    * No location; this is just an import of the namespace.
10447 	    * Note that we don't assign a bucket to the relation
10448 	    * in this case.
10449 	    */
10450 	    goto exit;
10451 	}
10452 	targetNamespace = importNamespace;
10453     }
10454 
10455     /* Did we already fetch the doc? */
10456     if (bkt != NULL) {
10457 	if ((WXS_IS_BUCKET_IMPMAIN(type)) && (! bkt->imported)) {
10458 	    /*
10459 	    * We included/redefined and then try to import a schema,
10460 	    * but the new location provided for import was different.
10461 	    */
10462 	    if (schemaLocation == NULL)
10463 		schemaLocation = BAD_CAST "in_memory_buffer";
10464 	    if (!xmlStrEqual(schemaLocation,
10465 		bkt->schemaLocation)) {
10466 		xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10467 		    invokingNode, NULL,
10468 		    "The schema document '%s' cannot be imported, since "
10469 		    "it was already included or redefined",
10470 		    schemaLocation, NULL);
10471 		goto exit;
10472 	    }
10473 	} else if ((! WXS_IS_BUCKET_IMPMAIN(type)) && (bkt->imported)) {
10474 	    /*
10475 	    * We imported and then try to include/redefine a schema,
10476 	    * but the new location provided for the include/redefine
10477 	    * was different.
10478 	    */
10479 	    if (schemaLocation == NULL)
10480 		schemaLocation = BAD_CAST "in_memory_buffer";
10481 	    if (!xmlStrEqual(schemaLocation,
10482 		bkt->schemaLocation)) {
10483 		xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10484 		    invokingNode, NULL,
10485 		    "The schema document '%s' cannot be included or "
10486 		    "redefined, since it was already imported",
10487 		    schemaLocation, NULL);
10488 		goto exit;
10489 	    }
10490 	}
10491     }
10492 
10493     if (WXS_IS_BUCKET_IMPMAIN(type)) {
10494 	/*
10495 	* Given that the schemaLocation [attribute] is only a hint, it is open
10496 	* to applications to ignore all but the first <import> for a given
10497 	* namespace, regardless of the `actual value` of schemaLocation, but
10498 	* such a strategy risks missing useful information when new
10499 	* schemaLocations are offered.
10500 	*
10501 	* We will use the first <import> that comes with a location.
10502 	* Further <import>s *with* a location, will result in an error.
10503 	* TODO: Better would be to just report a warning here, but
10504 	* we'll try it this way until someone complains.
10505 	*
10506 	* Schema Document Location Strategy:
10507 	* 3 Based on the namespace name, identify an existing schema document,
10508 	* either as a resource which is an XML document or a <schema> element
10509 	* information item, in some local schema repository;
10510 	* 5 Attempt to resolve the namespace name to locate such a resource.
10511 	*
10512 	* NOTE: (3) and (5) are not supported.
10513 	*/
10514 	if (bkt != NULL) {
10515 	    relation->bucket = bkt;
10516 	    goto exit;
10517 	}
10518 	bkt = xmlSchemaGetSchemaBucketByTNS(pctxt,
10519 	    importNamespace, 1);
10520 
10521 	if (bkt != NULL) {
10522 	    relation->bucket = bkt;
10523 	    if (bkt->schemaLocation == NULL) {
10524 		/* First given location of the schema; load the doc. */
10525 		bkt->schemaLocation = schemaLocation;
10526 	    } else {
10527 		if (!xmlStrEqual(schemaLocation,
10528 		    bkt->schemaLocation)) {
10529 		    /*
10530 		    * Additional location given; just skip it.
10531 		    * URGENT TODO: We should report a warning here.
10532 		    * res = XML_SCHEMAP_SRC_IMPORT;
10533 		    */
10534 		    if (schemaLocation == NULL)
10535 			schemaLocation = BAD_CAST "in_memory_buffer";
10536 
10537 		    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10538 			XML_SCHEMAP_WARN_SKIP_SCHEMA,
10539 			invokingNode, NULL,
10540 			"Skipping import of schema located at '%s' for the "
10541 			"namespace '%s', since this namespace was already "
10542 			"imported with the schema located at '%s'",
10543 			schemaLocation, importNamespace, bkt->schemaLocation);
10544 		}
10545 		goto exit;
10546 	    }
10547 	}
10548 	/*
10549 	* No bucket + first location: load the doc and create a
10550 	* bucket.
10551 	*/
10552     } else {
10553 	/* <include> and <redefine> */
10554 	if (bkt != NULL) {
10555 
10556 	    if ((bkt->origTargetNamespace == NULL) &&
10557 		(bkt->targetNamespace != sourceTargetNamespace)) {
10558 		xmlSchemaBucketPtr chamel;
10559 
10560 		/*
10561 		* Chameleon include/redefine: skip loading only if it was
10562 		* already build for the targetNamespace of the including
10563 		* schema.
10564 		*/
10565 		/*
10566 		* URGENT TODO: If the schema is a chameleon-include then copy
10567 		* the components into the including schema and modify the
10568 		* targetNamespace of those components, do nothing otherwise.
10569 		* NOTE: This is currently worked-around by compiling the
10570 		* chameleon for every distinct including targetNamespace; thus
10571 		* not performant at the moment.
10572 		* TODO: Check when the namespace in wildcards for chameleons
10573 		* needs to be converted: before we built wildcard intersections
10574 		* or after.
10575 		*   Answer: after!
10576 		*/
10577 		chamel = xmlSchemaGetChameleonSchemaBucket(pctxt,
10578 		    schemaLocation, sourceTargetNamespace);
10579 		if (chamel != NULL) {
10580 		    /* A fitting chameleon was already parsed; NOP. */
10581 		    relation->bucket = chamel;
10582 		    goto exit;
10583 		}
10584 		/*
10585 		* We need to parse the chameleon again for a different
10586 		* targetNamespace.
10587 		* CHAMELEON TODO: Optimize this by only parsing the
10588 		* chameleon once, and then copying the components to
10589 		* the new targetNamespace.
10590 		*/
10591 		bkt = NULL;
10592 	    } else {
10593 		relation->bucket = bkt;
10594 		goto exit;
10595 	    }
10596 	}
10597     }
10598     if ((bkt != NULL) && (bkt->doc != NULL)) {
10599 	PERROR_INT("xmlSchemaAddSchemaDoc",
10600 	    "trying to load a schema doc, but a doc is already "
10601 	    "assigned to the schema bucket");
10602 	goto exit_failure;
10603     }
10604 
10605 doc_load:
10606     /*
10607     * Load the document.
10608     */
10609     if (schemaDoc != NULL) {
10610 	doc = schemaDoc;
10611 	/* Don' free this one, since it was provided by the caller. */
10612 	preserveDoc = 1;
10613 	/* TODO: Does the context or the doc hold the location? */
10614 	if (schemaDoc->URL != NULL)
10615 	    schemaLocation = xmlDictLookup(pctxt->dict,
10616 		schemaDoc->URL, -1);
10617         else
10618 	    schemaLocation = BAD_CAST "in_memory_buffer";
10619     } else if ((schemaLocation != NULL) || (schemaBuffer != NULL)) {
10620 	xmlParserCtxtPtr parserCtxt;
10621 
10622 	parserCtxt = xmlNewParserCtxt();
10623 	if (parserCtxt == NULL) {
10624 	    xmlSchemaPErrMemory(NULL, "xmlSchemaGetDoc, "
10625 		"allocating a parser context", NULL);
10626 	    goto exit_failure;
10627 	}
10628 	if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
10629 	    /*
10630 	    * TODO: Do we have to burden the schema parser dict with all
10631 	    * the content of the schema doc?
10632 	    */
10633 	    xmlDictFree(parserCtxt->dict);
10634 	    parserCtxt->dict = pctxt->dict;
10635 	    xmlDictReference(parserCtxt->dict);
10636 	}
10637 	if (schemaLocation != NULL) {
10638 	    /* Parse from file. */
10639 	    doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
10640 		NULL, SCHEMAS_PARSE_OPTIONS);
10641 	} else if (schemaBuffer != NULL) {
10642 	    /* Parse from memory buffer. */
10643 	    doc = xmlCtxtReadMemory(parserCtxt, schemaBuffer, schemaBufferLen,
10644 		NULL, NULL, SCHEMAS_PARSE_OPTIONS);
10645 	    schemaLocation = BAD_CAST "in_memory_buffer";
10646 	    if (doc != NULL)
10647 		doc->URL = xmlStrdup(schemaLocation);
10648 	}
10649 	/*
10650 	* For <import>:
10651 	* 2.1 The referent is (a fragment of) a resource which is an
10652 	* XML document (see clause 1.1), which in turn corresponds to
10653 	* a <schema> element information item in a well-formed information
10654 	* set, which in turn corresponds to a valid schema.
10655 	* TODO: (2.1) fragments of XML documents are not supported.
10656 	*
10657 	* 2.2 The referent is a <schema> element information item in
10658 	* a well-formed information set, which in turn corresponds
10659 	* to a valid schema.
10660 	* TODO: (2.2) is not supported.
10661 	*/
10662 	if (doc == NULL) {
10663 	    xmlErrorPtr lerr;
10664 	    lerr = xmlGetLastError();
10665 	    /*
10666 	    * Check if this a parser error, or if the document could
10667 	    * just not be located.
10668 	    * TODO: Try to find specific error codes to react only on
10669 	    * localisation failures.
10670 	    */
10671 	    if ((lerr == NULL) || (lerr->domain != XML_FROM_IO)) {
10672 		/*
10673 		* We assume a parser error here.
10674 		*/
10675 		located = 1;
10676 		/* TODO: Error code ?? */
10677 		res = XML_SCHEMAP_SRC_IMPORT_2_1;
10678 		xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10679 		    invokingNode, NULL,
10680 		    "Failed to parse the XML resource '%s'",
10681 		    schemaLocation, NULL);
10682 	    }
10683 	}
10684 	xmlFreeParserCtxt(parserCtxt);
10685 	if ((doc == NULL) && located)
10686 	    goto exit_error;
10687     } else {
10688 	xmlSchemaPErr(pctxt, NULL,
10689 	    XML_SCHEMAP_NOTHING_TO_PARSE,
10690 	    "No information for parsing was provided with the "
10691 	    "given schema parser context.\n",
10692 	    NULL, NULL);
10693 	goto exit_failure;
10694     }
10695     /*
10696     * Preprocess the document.
10697     */
10698     if (doc != NULL) {
10699 	xmlNodePtr docElem = NULL;
10700 
10701 	located = 1;
10702 	docElem = xmlDocGetRootElement(doc);
10703 	if (docElem == NULL) {
10704 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOROOT,
10705 		invokingNode, NULL,
10706 		"The document '%s' has no document element",
10707 		schemaLocation, NULL);
10708 	    goto exit_error;
10709 	}
10710 	/*
10711 	* Remove all the blank text nodes.
10712 	*/
10713 	xmlSchemaCleanupDoc(pctxt, docElem);
10714 	/*
10715 	* Check the schema's top level element.
10716 	*/
10717 	if (!IS_SCHEMA(docElem, "schema")) {
10718 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOT_SCHEMA,
10719 		invokingNode, NULL,
10720 		"The XML document '%s' is not a schema document",
10721 		schemaLocation, NULL);
10722 	    goto exit_error;
10723 	}
10724 	/*
10725 	* Note that we don't apply a type check for the
10726 	* targetNamespace value here.
10727 	*/
10728 	targetNamespace = xmlSchemaGetProp(pctxt, docElem,
10729 	    "targetNamespace");
10730     }
10731 
10732 /* after_doc_loading: */
10733     if ((bkt == NULL) && located) {
10734 	/* Only create a bucket if the schema was located. */
10735         bkt = xmlSchemaBucketCreate(pctxt, type,
10736 	    targetNamespace);
10737 	if (bkt == NULL)
10738 	    goto exit_failure;
10739     }
10740     if (bkt != NULL) {
10741 	bkt->schemaLocation = schemaLocation;
10742 	bkt->located = located;
10743 	if (doc != NULL) {
10744 	    bkt->doc = doc;
10745 	    bkt->targetNamespace = targetNamespace;
10746 	    bkt->origTargetNamespace = targetNamespace;
10747 	    if (preserveDoc)
10748 		bkt->preserveDoc = 1;
10749 	}
10750 	if (WXS_IS_BUCKET_IMPMAIN(type))
10751 	    bkt->imported++;
10752 	    /*
10753 	    * Add it to the graph of schemas.
10754 	    */
10755 	if (relation != NULL)
10756 	    relation->bucket = bkt;
10757     }
10758 
10759 exit:
10760     /*
10761     * Return the bucket explicitly; this is needed for the
10762     * main schema.
10763     */
10764     if (bucket != NULL)
10765 	*bucket = bkt;
10766     return (0);
10767 
10768 exit_error:
10769     if ((doc != NULL) && (! preserveDoc)) {
10770 	xmlFreeDoc(doc);
10771 	if (bkt != NULL)
10772 	    bkt->doc = NULL;
10773     }
10774     return(pctxt->err);
10775 
10776 exit_failure:
10777     if ((doc != NULL) && (! preserveDoc)) {
10778 	xmlFreeDoc(doc);
10779 	if (bkt != NULL)
10780 	    bkt->doc = NULL;
10781     }
10782     return (-1);
10783 }
10784 
10785 /**
10786  * xmlSchemaParseImport:
10787  * @ctxt:  a schema validation context
10788  * @schema:  the schema being built
10789  * @node:  a subtree containing XML Schema information
10790  *
10791  * parse a XML schema Import definition
10792  * *WARNING* this interface is highly subject to change
10793  *
10794  * Returns 0 in case of success, a positive error code if
10795  * not valid and -1 in case of an internal error.
10796  */
10797 static int
xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)10798 xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
10799                      xmlNodePtr node)
10800 {
10801     xmlNodePtr child;
10802     const xmlChar *namespaceName = NULL, *schemaLocation = NULL;
10803     const xmlChar *thisTargetNamespace;
10804     xmlAttrPtr attr;
10805     int ret = 0;
10806     xmlSchemaBucketPtr bucket = NULL;
10807 
10808     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10809         return (-1);
10810 
10811     /*
10812     * Check for illegal attributes.
10813     */
10814     attr = node->properties;
10815     while (attr != NULL) {
10816 	if (attr->ns == NULL) {
10817 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10818 		(!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
10819 		(!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10820 		xmlSchemaPIllegalAttrErr(pctxt,
10821 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10822 	    }
10823 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10824 	    xmlSchemaPIllegalAttrErr(pctxt,
10825 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10826 	}
10827 	attr = attr->next;
10828     }
10829     /*
10830     * Extract and validate attributes.
10831     */
10832     if (xmlSchemaPValAttr(pctxt, NULL, node,
10833 	"namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10834 	&namespaceName) != 0) {
10835 	xmlSchemaPSimpleTypeErr(pctxt,
10836 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10837 	    NULL, node,
10838 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10839 	    NULL, namespaceName, NULL, NULL, NULL);
10840 	return (pctxt->err);
10841     }
10842 
10843     if (xmlSchemaPValAttr(pctxt, NULL, node,
10844 	"schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10845 	&schemaLocation) != 0) {
10846 	xmlSchemaPSimpleTypeErr(pctxt,
10847 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10848 	    NULL, node,
10849 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10850 	    NULL, schemaLocation, NULL, NULL, NULL);
10851 	return (pctxt->err);
10852     }
10853     /*
10854     * And now for the children...
10855     */
10856     child = node->children;
10857     if (IS_SCHEMA(child, "annotation")) {
10858         /*
10859          * the annotation here is simply discarded ...
10860 	 * TODO: really?
10861          */
10862         child = child->next;
10863     }
10864     if (child != NULL) {
10865 	xmlSchemaPContentErr(pctxt,
10866 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10867 	    NULL, node, child, NULL,
10868 	    "(annotation?)");
10869     }
10870     /*
10871     * Apply additional constraints.
10872     *
10873     * Note that it is important to use the original @targetNamespace
10874     * (or none at all), to rule out imports of schemas _with_ a
10875     * @targetNamespace if the importing schema is a chameleon schema
10876     * (with no @targetNamespace).
10877     */
10878     thisTargetNamespace = WXS_BUCKET(pctxt)->origTargetNamespace;
10879     if (namespaceName != NULL) {
10880 	/*
10881 	* 1.1 If the namespace [attribute] is present, then its `actual value`
10882 	* must not match the `actual value` of the enclosing <schema>'s
10883 	* targetNamespace [attribute].
10884 	*/
10885 	if (xmlStrEqual(thisTargetNamespace, namespaceName)) {
10886 	    xmlSchemaPCustomErr(pctxt,
10887 		XML_SCHEMAP_SRC_IMPORT_1_1,
10888 		NULL, node,
10889 		"The value of the attribute 'namespace' must not match "
10890 		"the target namespace '%s' of the importing schema",
10891 		thisTargetNamespace);
10892 	    return (pctxt->err);
10893 	}
10894     } else {
10895 	/*
10896 	* 1.2 If the namespace [attribute] is not present, then the enclosing
10897 	* <schema> must have a targetNamespace [attribute].
10898 	*/
10899 	if (thisTargetNamespace == NULL) {
10900 	    xmlSchemaPCustomErr(pctxt,
10901 		XML_SCHEMAP_SRC_IMPORT_1_2,
10902 		NULL, node,
10903 		"The attribute 'namespace' must be existent if "
10904 		"the importing schema has no target namespace",
10905 		NULL);
10906 	    return (pctxt->err);
10907 	}
10908     }
10909     /*
10910     * Locate and acquire the schema document.
10911     */
10912     if (schemaLocation != NULL)
10913 	schemaLocation = xmlSchemaBuildAbsoluteURI(pctxt->dict,
10914 	    schemaLocation, node);
10915     ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
10916 	schemaLocation, NULL, NULL, 0, node, thisTargetNamespace,
10917 	namespaceName, &bucket);
10918 
10919     if (ret != 0)
10920 	return(ret);
10921 
10922     /*
10923     * For <import>: "It is *not* an error for the application
10924     * schema reference strategy to fail."
10925     * So just don't parse if no schema document was found.
10926     * Note that we will get no bucket if the schema could not be
10927     * located or if there was no schemaLocation.
10928     */
10929     if ((bucket == NULL) && (schemaLocation != NULL)) {
10930 	xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10931 	    XML_SCHEMAP_WARN_UNLOCATED_SCHEMA,
10932 	    node, NULL,
10933 	    "Failed to locate a schema at location '%s'. "
10934 	    "Skipping the import", schemaLocation, NULL, NULL);
10935     }
10936 
10937     if ((bucket != NULL) && CAN_PARSE_SCHEMA(bucket)) {
10938 	ret = xmlSchemaParseNewDoc(pctxt, schema, bucket);
10939     }
10940 
10941     return (ret);
10942 }
10943 
10944 static int
xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlChar ** schemaLocation,int type)10945 xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,
10946 				     xmlSchemaPtr schema,
10947 				     xmlNodePtr node,
10948 				     xmlChar **schemaLocation,
10949 				     int type)
10950 {
10951     xmlAttrPtr attr;
10952 
10953     if ((pctxt == NULL) || (schema == NULL) || (node == NULL) ||
10954 	(schemaLocation == NULL))
10955         return (-1);
10956 
10957     *schemaLocation = NULL;
10958     /*
10959     * Check for illegal attributes.
10960     * Applies for both <include> and <redefine>.
10961     */
10962     attr = node->properties;
10963     while (attr != NULL) {
10964 	if (attr->ns == NULL) {
10965 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10966 		(!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10967 		xmlSchemaPIllegalAttrErr(pctxt,
10968 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10969 	    }
10970 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10971 	    xmlSchemaPIllegalAttrErr(pctxt,
10972 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10973 	}
10974 	attr = attr->next;
10975     }
10976     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
10977     /*
10978     * Preliminary step, extract the URI-Reference and make an URI
10979     * from the base.
10980     */
10981     /*
10982     * Attribute "schemaLocation" is mandatory.
10983     */
10984     attr = xmlSchemaGetPropNode(node, "schemaLocation");
10985     if (attr != NULL) {
10986         xmlChar *base = NULL;
10987         xmlChar *uri = NULL;
10988 
10989 	if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
10990 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10991 	    (const xmlChar **) schemaLocation) != 0)
10992 	    goto exit_error;
10993 	base = xmlNodeGetBase(node->doc, node);
10994 	if (base == NULL) {
10995 	    uri = xmlBuildURI(*schemaLocation, node->doc->URL);
10996 	} else {
10997 	    uri = xmlBuildURI(*schemaLocation, base);
10998 	    xmlFree(base);
10999 	}
11000 	if (uri == NULL) {
11001 	    PERROR_INT("xmlSchemaParseIncludeOrRedefine",
11002 		"could not build an URI from the schemaLocation")
11003 	    goto exit_failure;
11004 	}
11005 	(*schemaLocation) = (xmlChar *) xmlDictLookup(pctxt->dict, uri, -1);
11006 	xmlFree(uri);
11007     } else {
11008 	xmlSchemaPMissingAttrErr(pctxt,
11009 	    XML_SCHEMAP_S4S_ATTR_MISSING,
11010 	    NULL, node, "schemaLocation", NULL);
11011 	goto exit_error;
11012     }
11013     /*
11014     * Report self-inclusion and self-redefinition.
11015     */
11016     if (xmlStrEqual(*schemaLocation, pctxt->URL)) {
11017 	if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11018 	    xmlSchemaPCustomErr(pctxt,
11019 		XML_SCHEMAP_SRC_REDEFINE,
11020 		NULL, node,
11021 		"The schema document '%s' cannot redefine itself.",
11022 		*schemaLocation);
11023 	} else {
11024 	    xmlSchemaPCustomErr(pctxt,
11025 		XML_SCHEMAP_SRC_INCLUDE,
11026 		NULL, node,
11027 		"The schema document '%s' cannot include itself.",
11028 		*schemaLocation);
11029 	}
11030 	goto exit_error;
11031     }
11032 
11033     return(0);
11034 exit_error:
11035     return(pctxt->err);
11036 exit_failure:
11037     return(-1);
11038 }
11039 
11040 static int
xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node,int type)11041 xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,
11042 				xmlSchemaPtr schema,
11043 				xmlNodePtr node,
11044 				int type)
11045 {
11046     xmlNodePtr child = NULL;
11047     const xmlChar *schemaLocation = NULL;
11048     int res = 0; /* hasRedefinitions = 0 */
11049     int isChameleon = 0, wasChameleon = 0;
11050     xmlSchemaBucketPtr bucket = NULL;
11051 
11052     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
11053         return (-1);
11054 
11055     /*
11056     * Parse attributes. Note that the returned schemaLocation will
11057     * be already converted to an absolute URI.
11058     */
11059     res = xmlSchemaParseIncludeOrRedefineAttrs(pctxt, schema,
11060 	node, (xmlChar **) (&schemaLocation), type);
11061     if (res != 0)
11062 	return(res);
11063     /*
11064     * Load and add the schema document.
11065     */
11066     res = xmlSchemaAddSchemaDoc(pctxt, type, schemaLocation, NULL,
11067 	NULL, 0, node, pctxt->targetNamespace, NULL, &bucket);
11068     if (res != 0)
11069 	return(res);
11070     /*
11071     * If we get no schema bucket back, then this means that the schema
11072     * document could not be located or was broken XML or was not
11073     * a schema document.
11074     */
11075     if ((bucket == NULL) || (bucket->doc == NULL)) {
11076 	if (type == XML_SCHEMA_SCHEMA_INCLUDE) {
11077 	    /*
11078 	    * WARNING for <include>:
11079 	    * We will raise an error if the schema cannot be located
11080 	    * for inclusions, since the that was the feedback from the
11081 	    * schema people. I.e. the following spec piece will *not* be
11082 	    * satisfied:
11083 	    * SPEC src-include: "It is not an error for the `actual value` of the
11084 	    * schemaLocation [attribute] to fail to resolve it all, in which
11085 	    * case no corresponding inclusion is performed.
11086 	    * So do we need a warning report here?"
11087 	    */
11088 	    res = XML_SCHEMAP_SRC_INCLUDE;
11089 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
11090 		node, NULL,
11091 		"Failed to load the document '%s' for inclusion",
11092 		schemaLocation, NULL);
11093 	} else {
11094 	    /*
11095 	    * NOTE: This was changed to raise an error even if no redefinitions
11096 	    * are specified.
11097 	    *
11098 	    * SPEC src-redefine (1)
11099 	    * "If there are any element information items among the [children]
11100 	    * other than <annotation> then the `actual value` of the
11101 	    * schemaLocation [attribute] must successfully resolve."
11102 	    * TODO: Ask the WG if a the location has always to resolve
11103 	    * here as well!
11104 	    */
11105 	    res = XML_SCHEMAP_SRC_REDEFINE;
11106 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
11107 		node, NULL,
11108 		"Failed to load the document '%s' for redefinition",
11109 		schemaLocation, NULL);
11110 	}
11111     } else {
11112 	/*
11113 	* Check targetNamespace sanity before parsing the new schema.
11114 	* TODO: Note that we won't check further content if the
11115 	* targetNamespace was bad.
11116 	*/
11117 	if (bucket->origTargetNamespace != NULL) {
11118 	    /*
11119 	    * SPEC src-include (2.1)
11120 	    * "SII has a targetNamespace [attribute], and its `actual
11121 	    * value` is identical to the `actual value` of the targetNamespace
11122 	    * [attribute] of SII' (which must have such an [attribute])."
11123 	    */
11124 	    if (pctxt->targetNamespace == NULL) {
11125 		xmlSchemaCustomErr(ACTXT_CAST pctxt,
11126 		    XML_SCHEMAP_SRC_INCLUDE,
11127 		    node, NULL,
11128 		    "The target namespace of the included/redefined schema "
11129 		    "'%s' has to be absent, since the including/redefining "
11130 		    "schema has no target namespace",
11131 		    schemaLocation, NULL);
11132 		goto exit_error;
11133 	    } else if (!xmlStrEqual(bucket->origTargetNamespace,
11134 		pctxt->targetNamespace)) {
11135 		/* TODO: Change error function. */
11136 		xmlSchemaPCustomErrExt(pctxt,
11137 		    XML_SCHEMAP_SRC_INCLUDE,
11138 		    NULL, node,
11139 		    "The target namespace '%s' of the included/redefined "
11140 		    "schema '%s' differs from '%s' of the "
11141 		    "including/redefining schema",
11142 		    bucket->origTargetNamespace, schemaLocation,
11143 		    pctxt->targetNamespace);
11144 		goto exit_error;
11145 	    }
11146 	} else if (pctxt->targetNamespace != NULL) {
11147 	    /*
11148 	    * Chameleons: the original target namespace will
11149 	    * differ from the resulting namespace.
11150 	    */
11151 	    isChameleon = 1;
11152 	    if (bucket->parsed &&
11153 		bucket->origTargetNamespace != NULL) {
11154 		xmlSchemaCustomErr(ACTXT_CAST pctxt,
11155 		    XML_SCHEMAP_SRC_INCLUDE,
11156 		    node, NULL,
11157 		    "The target namespace of the included/redefined schema "
11158 		    "'%s' has to be absent or the same as the "
11159 		    "including/redefining schema's target namespace",
11160 		    schemaLocation, NULL);
11161 		goto exit_error;
11162 	    }
11163 	    bucket->targetNamespace = pctxt->targetNamespace;
11164 	}
11165     }
11166     /*
11167     * Parse the schema.
11168     */
11169     if (bucket && (!bucket->parsed) && (bucket->doc != NULL)) {
11170 	if (isChameleon) {
11171 	    /* TODO: Get rid of this flag on the schema itself. */
11172 	    if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
11173 		schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11174 	    } else
11175 		wasChameleon = 1;
11176 	}
11177 	xmlSchemaParseNewDoc(pctxt, schema, bucket);
11178 	/* Restore chameleon flag. */
11179 	if (isChameleon && (!wasChameleon))
11180 	    schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11181     }
11182     /*
11183     * And now for the children...
11184     */
11185     child = node->children;
11186     if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11187 	/*
11188 	* Parse (simpleType | complexType | group | attributeGroup))*
11189 	*/
11190 	pctxt->redefined = bucket;
11191 	/*
11192 	* How to proceed if the redefined schema was not located?
11193 	*/
11194 	pctxt->isRedefine = 1;
11195 	while (IS_SCHEMA(child, "annotation") ||
11196 	    IS_SCHEMA(child, "simpleType") ||
11197 	    IS_SCHEMA(child, "complexType") ||
11198 	    IS_SCHEMA(child, "group") ||
11199 	    IS_SCHEMA(child, "attributeGroup")) {
11200 	    if (IS_SCHEMA(child, "annotation")) {
11201 		/*
11202 		* TODO: discard or not?
11203 		*/
11204 	    } else if (IS_SCHEMA(child, "simpleType")) {
11205 		xmlSchemaParseSimpleType(pctxt, schema, child, 1);
11206 	    } else if (IS_SCHEMA(child, "complexType")) {
11207 		xmlSchemaParseComplexType(pctxt, schema, child, 1);
11208 		/* hasRedefinitions = 1; */
11209 	    } else if (IS_SCHEMA(child, "group")) {
11210 		/* hasRedefinitions = 1; */
11211 		xmlSchemaParseModelGroupDefinition(pctxt,
11212 		    schema, child);
11213 	    } else if (IS_SCHEMA(child, "attributeGroup")) {
11214 		/* hasRedefinitions = 1; */
11215 		xmlSchemaParseAttributeGroupDefinition(pctxt, schema,
11216 		    child);
11217 	    }
11218 	    child = child->next;
11219 	}
11220 	pctxt->redefined = NULL;
11221 	pctxt->isRedefine = 0;
11222     } else {
11223 	if (IS_SCHEMA(child, "annotation")) {
11224 	    /*
11225 	    * TODO: discard or not?
11226 	    */
11227 	    child = child->next;
11228 	}
11229     }
11230     if (child != NULL) {
11231 	res = XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED;
11232 	if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11233 	    xmlSchemaPContentErr(pctxt, res,
11234 		NULL, node, child, NULL,
11235 		"(annotation | (simpleType | complexType | group | attributeGroup))*");
11236 	} else {
11237 	     xmlSchemaPContentErr(pctxt, res,
11238 		NULL, node, child, NULL,
11239 		"(annotation?)");
11240 	}
11241     }
11242     return(res);
11243 
11244 exit_error:
11245     return(pctxt->err);
11246 }
11247 
11248 static int
xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)11249 xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11250                        xmlNodePtr node)
11251 {
11252     int res;
11253 #ifndef ENABLE_REDEFINE
11254     TODO
11255     return(0);
11256 #endif
11257     res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11258 	XML_SCHEMA_SCHEMA_REDEFINE);
11259     if (res != 0)
11260 	return(res);
11261     return(0);
11262 }
11263 
11264 static int
xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)11265 xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11266                        xmlNodePtr node)
11267 {
11268     int res;
11269 
11270     res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11271 	XML_SCHEMA_SCHEMA_INCLUDE);
11272     if (res != 0)
11273 	return(res);
11274     return(0);
11275 }
11276 
11277 /**
11278  * xmlSchemaParseModelGroup:
11279  * @ctxt:  a schema validation context
11280  * @schema:  the schema being built
11281  * @node:  a subtree containing XML Schema information
11282  * @type: the "compositor" type
11283  * @particleNeeded: if a a model group with a particle
11284  *
11285  * parse a XML schema Sequence definition.
11286  * Applies parts of:
11287  *   Schema Representation Constraint:
11288  *     Redefinition Constraints and Semantics (src-redefine)
11289  *     (6.1), (6.1.1), (6.1.2)
11290  *
11291  *   Schema Component Constraint:
11292  *     All Group Limited (cos-all-limited) (2)
11293  *     TODO: Actually this should go to component-level checks,
11294  *     but is done here due to performance. Move it to an other layer
11295  *     is schema construction via an API is implemented.
11296  *
11297  * *WARNING* this interface is highly subject to change
11298  *
11299  * Returns -1 in case of error, 0 if the declaration is improper and
11300  *         1 in case of success.
11301  */
11302 static xmlSchemaTreeItemPtr
xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlSchemaTypeType type,int withParticle)11303 xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11304 			 xmlNodePtr node, xmlSchemaTypeType type,
11305 			 int withParticle)
11306 {
11307     xmlSchemaModelGroupPtr item;
11308     xmlSchemaParticlePtr particle = NULL;
11309     xmlNodePtr child = NULL;
11310     xmlAttrPtr attr;
11311     int min = 1, max = 1, isElemRef, hasRefs = 0;
11312 
11313     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11314         return (NULL);
11315     /*
11316     * Create a model group with the given compositor.
11317     */
11318     item = xmlSchemaAddModelGroup(ctxt, schema, type, node);
11319     if (item == NULL)
11320 	return (NULL);
11321 
11322     if (withParticle) {
11323 	if (type == XML_SCHEMA_TYPE_ALL) {
11324 	    min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
11325 	    max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
11326 	} else {
11327 	    /* choice + sequence */
11328 	    min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
11329 	    max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
11330 		"(xs:nonNegativeInteger | unbounded)");
11331 	}
11332 	xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
11333 	/*
11334 	* Create a particle
11335 	*/
11336 	particle = xmlSchemaAddParticle(ctxt, node, min, max);
11337 	if (particle == NULL)
11338 	    return (NULL);
11339 	particle->children = (xmlSchemaTreeItemPtr) item;
11340 	/*
11341 	* Check for illegal attributes.
11342 	*/
11343 	attr = node->properties;
11344 	while (attr != NULL) {
11345 	    if (attr->ns == NULL) {
11346 		if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11347 		    (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
11348 		    (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
11349 		    xmlSchemaPIllegalAttrErr(ctxt,
11350 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11351 		}
11352 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11353 		xmlSchemaPIllegalAttrErr(ctxt,
11354 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11355 	    }
11356 	    attr = attr->next;
11357 	}
11358     } else {
11359 	/*
11360 	* Check for illegal attributes.
11361 	*/
11362 	attr = node->properties;
11363 	while (attr != NULL) {
11364 	    if (attr->ns == NULL) {
11365 		if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
11366 		    xmlSchemaPIllegalAttrErr(ctxt,
11367 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11368 		}
11369 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11370 		xmlSchemaPIllegalAttrErr(ctxt,
11371 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11372 	    }
11373 	    attr = attr->next;
11374 	}
11375     }
11376 
11377     /*
11378     * Extract and validate attributes.
11379     */
11380     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11381     /*
11382     * And now for the children...
11383     */
11384     child = node->children;
11385     if (IS_SCHEMA(child, "annotation")) {
11386         item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
11387         child = child->next;
11388     }
11389     if (type == XML_SCHEMA_TYPE_ALL) {
11390 	xmlSchemaParticlePtr part, last = NULL;
11391 
11392 	while (IS_SCHEMA(child, "element")) {
11393 	    part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
11394 		schema, child, &isElemRef, 0);
11395 	    /*
11396 	    * SPEC cos-all-limited (2)
11397 	    * "The {max occurs} of all the particles in the {particles}
11398 	    * of the ('all') group must be 0 or 1.
11399 	    */
11400 	    if (part != NULL) {
11401 		if (isElemRef)
11402 		    hasRefs++;
11403 		if (part->minOccurs > 1) {
11404 		    xmlSchemaPCustomErr(ctxt,
11405 			XML_SCHEMAP_COS_ALL_LIMITED,
11406 			NULL, child,
11407 			"Invalid value for minOccurs (must be 0 or 1)",
11408 			NULL);
11409 		    /* Reset to 1. */
11410 		    part->minOccurs = 1;
11411 		}
11412 		if (part->maxOccurs > 1) {
11413 		    xmlSchemaPCustomErr(ctxt,
11414 			XML_SCHEMAP_COS_ALL_LIMITED,
11415 			NULL, child,
11416 			"Invalid value for maxOccurs (must be 0 or 1)",
11417 			NULL);
11418 		    /* Reset to 1. */
11419 		    part->maxOccurs = 1;
11420 		}
11421 		if (last == NULL)
11422 		    item->children = (xmlSchemaTreeItemPtr) part;
11423 		else
11424 		    last->next = (xmlSchemaTreeItemPtr) part;
11425 		last = part;
11426 	    }
11427 	    child = child->next;
11428 	}
11429 	if (child != NULL) {
11430 	    xmlSchemaPContentErr(ctxt,
11431 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11432 		NULL, node, child, NULL,
11433 		"(annotation?, (annotation?, element*)");
11434 	}
11435     } else {
11436 	/* choice + sequence */
11437 	xmlSchemaTreeItemPtr part = NULL, last = NULL;
11438 
11439 	while ((IS_SCHEMA(child, "element")) ||
11440 	    (IS_SCHEMA(child, "group")) ||
11441 	    (IS_SCHEMA(child, "any")) ||
11442 	    (IS_SCHEMA(child, "choice")) ||
11443 	    (IS_SCHEMA(child, "sequence"))) {
11444 
11445 	    if (IS_SCHEMA(child, "element")) {
11446 		part = (xmlSchemaTreeItemPtr)
11447 		    xmlSchemaParseElement(ctxt, schema, child, &isElemRef, 0);
11448 		if (part && isElemRef)
11449 		    hasRefs++;
11450 	    } else if (IS_SCHEMA(child, "group")) {
11451 		part =
11452 		    xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11453 		if (part != NULL)
11454 		    hasRefs++;
11455 		/*
11456 		* Handle redefinitions.
11457 		*/
11458 		if (ctxt->isRedefine && ctxt->redef &&
11459 		    (ctxt->redef->item->type == XML_SCHEMA_TYPE_GROUP) &&
11460 		    part && part->children)
11461 		{
11462 		    if ((xmlSchemaGetQNameRefName(part->children) ==
11463 			    ctxt->redef->refName) &&
11464 			(xmlSchemaGetQNameRefTargetNs(part->children) ==
11465 			    ctxt->redef->refTargetNs))
11466 		    {
11467 			/*
11468 			* SPEC src-redefine:
11469 			* (6.1) "If it has a <group> among its contents at
11470 			* some level the `actual value` of whose ref
11471 			* [attribute] is the same as the `actual value` of
11472 			* its own name attribute plus target namespace, then
11473 			* all of the following must be true:"
11474 			* (6.1.1) "It must have exactly one such group."
11475 			*/
11476 			if (ctxt->redefCounter != 0) {
11477 			    xmlChar *str = NULL;
11478 
11479 			    xmlSchemaCustomErr(ACTXT_CAST ctxt,
11480 				XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11481 				"The redefining model group definition "
11482 				"'%s' must not contain more than one "
11483 				"reference to the redefined definition",
11484 				xmlSchemaFormatQName(&str,
11485 				    ctxt->redef->refTargetNs,
11486 				    ctxt->redef->refName),
11487 				NULL);
11488 			    FREE_AND_NULL(str)
11489 			    part = NULL;
11490 			} else if (((WXS_PARTICLE(part))->minOccurs != 1) ||
11491 			    ((WXS_PARTICLE(part))->maxOccurs != 1))
11492 			{
11493 			    xmlChar *str = NULL;
11494 			    /*
11495 			    * SPEC src-redefine:
11496 			    * (6.1.2) "The `actual value` of both that
11497 			    * group's minOccurs and maxOccurs [attribute]
11498 			    * must be 1 (or `absent`).
11499 			    */
11500 			    xmlSchemaCustomErr(ACTXT_CAST ctxt,
11501 				XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11502 				"The redefining model group definition "
11503 				"'%s' must not contain a reference to the "
11504 				"redefined definition with a "
11505 				"maxOccurs/minOccurs other than 1",
11506 				xmlSchemaFormatQName(&str,
11507 				    ctxt->redef->refTargetNs,
11508 				    ctxt->redef->refName),
11509 				NULL);
11510 			    FREE_AND_NULL(str)
11511 			    part = NULL;
11512 			}
11513 			ctxt->redef->reference = WXS_BASIC_CAST part;
11514 			ctxt->redefCounter++;
11515 		    }
11516 		}
11517 	    } else if (IS_SCHEMA(child, "any")) {
11518 		part = (xmlSchemaTreeItemPtr)
11519 		    xmlSchemaParseAny(ctxt, schema, child);
11520 	    } else if (IS_SCHEMA(child, "choice")) {
11521 		part = xmlSchemaParseModelGroup(ctxt, schema, child,
11522 		    XML_SCHEMA_TYPE_CHOICE, 1);
11523 	    } else if (IS_SCHEMA(child, "sequence")) {
11524 		part = xmlSchemaParseModelGroup(ctxt, schema, child,
11525 		    XML_SCHEMA_TYPE_SEQUENCE, 1);
11526 	    }
11527 	    if (part != NULL) {
11528 		if (last == NULL)
11529 		    item->children = part;
11530 		else
11531 		    last->next = part;
11532 		last = part;
11533 	    }
11534 	    child = child->next;
11535 	}
11536 	if (child != NULL) {
11537 	    xmlSchemaPContentErr(ctxt,
11538 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11539 		NULL, node, child, NULL,
11540 		"(annotation?, (element | group | choice | sequence | any)*)");
11541 	}
11542     }
11543     if ((max == 0) && (min == 0))
11544 	return (NULL);
11545     if (hasRefs) {
11546 	/*
11547 	* We need to resolve references.
11548 	*/
11549 	WXS_ADD_PENDING(ctxt, item);
11550     }
11551     if (withParticle)
11552 	return ((xmlSchemaTreeItemPtr) particle);
11553     else
11554 	return ((xmlSchemaTreeItemPtr) item);
11555 }
11556 
11557 /**
11558  * xmlSchemaParseRestriction:
11559  * @ctxt:  a schema validation context
11560  * @schema:  the schema being built
11561  * @node:  a subtree containing XML Schema information
11562  *
11563  * parse a XML schema Restriction definition
11564  * *WARNING* this interface is highly subject to change
11565  *
11566  * Returns the type definition or NULL in case of error
11567  */
11568 static xmlSchemaTypePtr
xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlSchemaTypeType parentType)11569 xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11570                           xmlNodePtr node, xmlSchemaTypeType parentType)
11571 {
11572     xmlSchemaTypePtr type;
11573     xmlNodePtr child = NULL;
11574     xmlAttrPtr attr;
11575 
11576     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11577         return (NULL);
11578     /* Not a component, don't create it. */
11579     type = ctxt->ctxtType;
11580     type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
11581 
11582     /*
11583     * Check for illegal attributes.
11584     */
11585     attr = node->properties;
11586     while (attr != NULL) {
11587 	if (attr->ns == NULL) {
11588 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11589 		(!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11590 		xmlSchemaPIllegalAttrErr(ctxt,
11591 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11592 	    }
11593 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11594 	    xmlSchemaPIllegalAttrErr(ctxt,
11595 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11596 	}
11597 	attr = attr->next;
11598     }
11599     /*
11600     * Extract and validate attributes.
11601     */
11602     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11603     /*
11604     * Attribute
11605     */
11606     /*
11607     * Extract the base type. The "base" attribute is mandatory if inside
11608     * a complex type or if redefining.
11609     *
11610     * SPEC (1.2) "...otherwise (<restriction> has no <simpleType> "
11611     * among its [children]), the simple type definition which is
11612     * the {content type} of the type definition `resolved` to by
11613     * the `actual value` of the base [attribute]"
11614     */
11615     if (xmlSchemaPValAttrQName(ctxt, schema, NULL, node, "base",
11616 	&(type->baseNs), &(type->base)) == 0)
11617     {
11618 	if ((type->base == NULL) && (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
11619 	    xmlSchemaPMissingAttrErr(ctxt,
11620 		XML_SCHEMAP_S4S_ATTR_MISSING,
11621 		NULL, node, "base", NULL);
11622 	} else if ((ctxt->isRedefine) &&
11623 	    (type->flags & XML_SCHEMAS_TYPE_GLOBAL))
11624 	{
11625 	    if (type->base == NULL) {
11626 		xmlSchemaPMissingAttrErr(ctxt,
11627 		    XML_SCHEMAP_S4S_ATTR_MISSING,
11628 		    NULL, node, "base", NULL);
11629 	    } else if ((! xmlStrEqual(type->base, type->name)) ||
11630 		(! xmlStrEqual(type->baseNs, type->targetNamespace)))
11631 	    {
11632 		xmlChar *str1 = NULL, *str2 = NULL;
11633 		/*
11634 		* REDEFINE: SPEC src-redefine (5)
11635 		* "Within the [children], each <simpleType> must have a
11636 		* <restriction> among its [children] ... the `actual value` of
11637 		* whose base [attribute] must be the same as the `actual value`
11638 		* of its own name attribute plus target namespace;"
11639 		*/
11640 		xmlSchemaPCustomErrExt(ctxt, XML_SCHEMAP_SRC_REDEFINE,
11641 		    NULL, node, "This is a redefinition, but the QName "
11642 		    "value '%s' of the 'base' attribute does not match the "
11643 		    "type's designation '%s'",
11644 		    xmlSchemaFormatQName(&str1, type->baseNs, type->base),
11645 		    xmlSchemaFormatQName(&str2, type->targetNamespace,
11646 			type->name), NULL);
11647 		FREE_AND_NULL(str1);
11648 		FREE_AND_NULL(str2);
11649 		/* Avoid confusion and erase the values. */
11650 		type->base = NULL;
11651 		type->baseNs = NULL;
11652 	    }
11653 	}
11654     }
11655     /*
11656     * And now for the children...
11657     */
11658     child = node->children;
11659     if (IS_SCHEMA(child, "annotation")) {
11660 	/*
11661 	* Add the annotation to the simple type ancestor.
11662 	*/
11663 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11664 	    xmlSchemaParseAnnotation(ctxt, child, 1));
11665         child = child->next;
11666     }
11667     if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
11668 	/*
11669 	* Corresponds to <simpleType><restriction><simpleType>.
11670 	*/
11671 	if (IS_SCHEMA(child, "simpleType")) {
11672 	    if (type->base != NULL) {
11673 		/*
11674 		* src-restriction-base-or-simpleType
11675 		* Either the base [attribute] or the simpleType [child] of the
11676 		* <restriction> element must be present, but not both.
11677 		*/
11678 		xmlSchemaPContentErr(ctxt,
11679 		    XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11680 		    NULL, node, child,
11681 		    "The attribute 'base' and the <simpleType> child are "
11682 		    "mutually exclusive", NULL);
11683 	    } else {
11684 		type->baseType = (xmlSchemaTypePtr)
11685 		    xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11686 	    }
11687 	    child = child->next;
11688 	} else if (type->base == NULL) {
11689 	    xmlSchemaPContentErr(ctxt,
11690 		XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11691 		NULL, node, child,
11692 		"Either the attribute 'base' or a <simpleType> child "
11693 		"must be present", NULL);
11694 	}
11695     } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11696 	/*
11697 	* Corresponds to <complexType><complexContent><restriction>...
11698 	* followed by:
11699 	*
11700 	* Model groups <all>, <choice> and <sequence>.
11701 	*/
11702 	if (IS_SCHEMA(child, "all")) {
11703 	    type->subtypes = (xmlSchemaTypePtr)
11704 		xmlSchemaParseModelGroup(ctxt, schema, child,
11705 		    XML_SCHEMA_TYPE_ALL, 1);
11706 	    child = child->next;
11707 	} else if (IS_SCHEMA(child, "choice")) {
11708 	    type->subtypes = (xmlSchemaTypePtr)
11709 		xmlSchemaParseModelGroup(ctxt,
11710 		    schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
11711 	    child = child->next;
11712 	} else if (IS_SCHEMA(child, "sequence")) {
11713 	    type->subtypes = (xmlSchemaTypePtr)
11714 		xmlSchemaParseModelGroup(ctxt, schema, child,
11715 		    XML_SCHEMA_TYPE_SEQUENCE, 1);
11716 	    child = child->next;
11717 	/*
11718 	* Model group reference <group>.
11719 	*/
11720 	} else if (IS_SCHEMA(child, "group")) {
11721 	    type->subtypes = (xmlSchemaTypePtr)
11722 		xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11723 	    /*
11724 	    * Note that the reference will be resolved in
11725 	    * xmlSchemaResolveTypeReferences();
11726 	    */
11727 	    child = child->next;
11728 	}
11729     } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11730 	/*
11731 	* Corresponds to <complexType><simpleContent><restriction>...
11732 	*
11733 	* "1.1 the simple type definition corresponding to the <simpleType>
11734 	* among the [children] of <restriction> if there is one;"
11735 	*/
11736 	if (IS_SCHEMA(child, "simpleType")) {
11737 	    /*
11738 	    * We will store the to-be-restricted simple type in
11739 	    * type->contentTypeDef *temporarily*.
11740 	    */
11741 	    type->contentTypeDef = (xmlSchemaTypePtr)
11742 		xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11743 	    if ( type->contentTypeDef == NULL)
11744 		return (NULL);
11745 	    child = child->next;
11746 	}
11747     }
11748 
11749     if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
11750 	(parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
11751 	xmlSchemaFacetPtr facet, lastfacet = NULL;
11752 	/*
11753 	* Corresponds to <complexType><simpleContent><restriction>...
11754 	* <simpleType><restriction>...
11755 	*/
11756 
11757 	/*
11758 	* Add the facets to the simple type ancestor.
11759 	*/
11760 	/*
11761 	* TODO: Datatypes: 4.1.3 Constraints on XML Representation of
11762 	* Simple Type Definition Schema Representation Constraint:
11763 	* *Single Facet Value*
11764 	*/
11765 	while ((IS_SCHEMA(child, "minInclusive")) ||
11766 	    (IS_SCHEMA(child, "minExclusive")) ||
11767 	    (IS_SCHEMA(child, "maxInclusive")) ||
11768 	    (IS_SCHEMA(child, "maxExclusive")) ||
11769 	    (IS_SCHEMA(child, "totalDigits")) ||
11770 	    (IS_SCHEMA(child, "fractionDigits")) ||
11771 	    (IS_SCHEMA(child, "pattern")) ||
11772 	    (IS_SCHEMA(child, "enumeration")) ||
11773 	    (IS_SCHEMA(child, "whiteSpace")) ||
11774 	    (IS_SCHEMA(child, "length")) ||
11775 	    (IS_SCHEMA(child, "maxLength")) ||
11776 	    (IS_SCHEMA(child, "minLength"))) {
11777 	    facet = xmlSchemaParseFacet(ctxt, schema, child);
11778 	    if (facet != NULL) {
11779 		if (lastfacet == NULL)
11780 		    type->facets = facet;
11781 		else
11782 		    lastfacet->next = facet;
11783 		lastfacet = facet;
11784 		lastfacet->next = NULL;
11785 	    }
11786 	    child = child->next;
11787 	}
11788 	/*
11789 	* Create links for derivation and validation.
11790 	*/
11791 	if (type->facets != NULL) {
11792 	    xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
11793 
11794 	    facet = type->facets;
11795 	    do {
11796 		facetLink = (xmlSchemaFacetLinkPtr)
11797 		    xmlMalloc(sizeof(xmlSchemaFacetLink));
11798 		if (facetLink == NULL) {
11799 		    xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
11800 		    xmlFree(facetLink);
11801 		    return (NULL);
11802 		}
11803 		facetLink->facet = facet;
11804 		facetLink->next = NULL;
11805 		if (lastFacetLink == NULL)
11806 		    type->facetSet = facetLink;
11807 		else
11808 		    lastFacetLink->next = facetLink;
11809 		lastFacetLink = facetLink;
11810 		facet = facet->next;
11811 	    } while (facet != NULL);
11812 	}
11813     }
11814     if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
11815 	/*
11816 	* Attribute uses/declarations.
11817 	*/
11818 	if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11819 	    (xmlSchemaItemListPtr *) &(type->attrUses),
11820 	    XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
11821 	    return(NULL);
11822 	/*
11823 	* Attribute wildcard.
11824 	*/
11825 	if (IS_SCHEMA(child, "anyAttribute")) {
11826 	    type->attributeWildcard =
11827 		xmlSchemaParseAnyAttribute(ctxt, schema, child);
11828 	    child = child->next;
11829 	}
11830     }
11831     if (child != NULL) {
11832 	if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11833 	    xmlSchemaPContentErr(ctxt,
11834 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11835 		NULL, node, child, NULL,
11836 		"annotation?, (group | all | choice | sequence)?, "
11837 		"((attribute | attributeGroup)*, anyAttribute?))");
11838 	} else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11839 	     xmlSchemaPContentErr(ctxt,
11840 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11841 		NULL, node, child, NULL,
11842 		"(annotation?, (simpleType?, (minExclusive | minInclusive | "
11843 		"maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11844 		"length | minLength | maxLength | enumeration | whiteSpace | "
11845 		"pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
11846 	} else {
11847 	    /* Simple type */
11848 	    xmlSchemaPContentErr(ctxt,
11849 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11850 		NULL, node, child, NULL,
11851 		"(annotation?, (simpleType?, (minExclusive | minInclusive | "
11852 		"maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11853 		"length | minLength | maxLength | enumeration | whiteSpace | "
11854 		"pattern)*))");
11855 	}
11856     }
11857     return (NULL);
11858 }
11859 
11860 /**
11861  * xmlSchemaParseExtension:
11862  * @ctxt:  a schema validation context
11863  * @schema:  the schema being built
11864  * @node:  a subtree containing XML Schema information
11865  *
11866  * Parses an <extension>, which is found inside a
11867  * <simpleContent> or <complexContent>.
11868  * *WARNING* this interface is highly subject to change.
11869  *
11870  * TODO: Returns the type definition or NULL in case of error
11871  */
11872 static xmlSchemaTypePtr
xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlSchemaTypeType parentType)11873 xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11874                         xmlNodePtr node, xmlSchemaTypeType parentType)
11875 {
11876     xmlSchemaTypePtr type;
11877     xmlNodePtr child = NULL;
11878     xmlAttrPtr attr;
11879 
11880     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11881         return (NULL);
11882     /* Not a component, don't create it. */
11883     type = ctxt->ctxtType;
11884     type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
11885 
11886     /*
11887     * Check for illegal attributes.
11888     */
11889     attr = node->properties;
11890     while (attr != NULL) {
11891 	if (attr->ns == NULL) {
11892 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11893 		(!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11894 		xmlSchemaPIllegalAttrErr(ctxt,
11895 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11896 	    }
11897 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11898 	    xmlSchemaPIllegalAttrErr(ctxt,
11899 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11900 	}
11901 	attr = attr->next;
11902     }
11903 
11904     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11905 
11906     /*
11907     * Attribute "base" - mandatory.
11908     */
11909     if ((xmlSchemaPValAttrQName(ctxt, schema, NULL, node,
11910 	"base", &(type->baseNs), &(type->base)) == 0) &&
11911 	(type->base == NULL)) {
11912 	xmlSchemaPMissingAttrErr(ctxt,
11913 	    XML_SCHEMAP_S4S_ATTR_MISSING,
11914 	    NULL, node, "base", NULL);
11915     }
11916     /*
11917     * And now for the children...
11918     */
11919     child = node->children;
11920     if (IS_SCHEMA(child, "annotation")) {
11921 	/*
11922 	* Add the annotation to the type ancestor.
11923 	*/
11924 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11925 	    xmlSchemaParseAnnotation(ctxt, child, 1));
11926         child = child->next;
11927     }
11928     if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11929 	/*
11930 	* Corresponds to <complexType><complexContent><extension>... and:
11931 	*
11932 	* Model groups <all>, <choice>, <sequence> and <group>.
11933 	*/
11934 	if (IS_SCHEMA(child, "all")) {
11935 	    type->subtypes = (xmlSchemaTypePtr)
11936 		xmlSchemaParseModelGroup(ctxt, schema,
11937 		    child, XML_SCHEMA_TYPE_ALL, 1);
11938 	    child = child->next;
11939 	} else if (IS_SCHEMA(child, "choice")) {
11940 	    type->subtypes = (xmlSchemaTypePtr)
11941 		xmlSchemaParseModelGroup(ctxt, schema,
11942 		    child, XML_SCHEMA_TYPE_CHOICE, 1);
11943 	    child = child->next;
11944 	} else if (IS_SCHEMA(child, "sequence")) {
11945 	    type->subtypes = (xmlSchemaTypePtr)
11946 		xmlSchemaParseModelGroup(ctxt, schema,
11947 		child, XML_SCHEMA_TYPE_SEQUENCE, 1);
11948 	    child = child->next;
11949 	} else if (IS_SCHEMA(child, "group")) {
11950 	    type->subtypes = (xmlSchemaTypePtr)
11951 		xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11952 	    /*
11953 	    * Note that the reference will be resolved in
11954 	    * xmlSchemaResolveTypeReferences();
11955 	    */
11956 	    child = child->next;
11957 	}
11958     }
11959     if (child != NULL) {
11960 	/*
11961 	* Attribute uses/declarations.
11962 	*/
11963 	if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11964 	    (xmlSchemaItemListPtr *) &(type->attrUses),
11965 	    XML_SCHEMA_TYPE_EXTENSION, NULL) == -1)
11966 	    return(NULL);
11967 	/*
11968 	* Attribute wildcard.
11969 	*/
11970 	if (IS_SCHEMA(child, "anyAttribute")) {
11971 	    ctxt->ctxtType->attributeWildcard =
11972 		xmlSchemaParseAnyAttribute(ctxt, schema, child);
11973 	    child = child->next;
11974 	}
11975     }
11976     if (child != NULL) {
11977 	if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11978 	    /* Complex content extension. */
11979 	    xmlSchemaPContentErr(ctxt,
11980 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11981 		NULL, node, child, NULL,
11982 		"(annotation?, ((group | all | choice | sequence)?, "
11983 		"((attribute | attributeGroup)*, anyAttribute?)))");
11984 	} else {
11985 	    /* Simple content extension. */
11986 	    xmlSchemaPContentErr(ctxt,
11987 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11988 		NULL, node, child, NULL,
11989 		"(annotation?, ((attribute | attributeGroup)*, "
11990 		"anyAttribute?))");
11991 	}
11992     }
11993     return (NULL);
11994 }
11995 
11996 /**
11997  * xmlSchemaParseSimpleContent:
11998  * @ctxt:  a schema validation context
11999  * @schema:  the schema being built
12000  * @node:  a subtree containing XML Schema information
12001  *
12002  * parse a XML schema SimpleContent definition
12003  * *WARNING* this interface is highly subject to change
12004  *
12005  * Returns the type definition or NULL in case of error
12006  */
12007 static int
xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int * hasRestrictionOrExtension)12008 xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
12009                             xmlSchemaPtr schema, xmlNodePtr node,
12010 			    int *hasRestrictionOrExtension)
12011 {
12012     xmlSchemaTypePtr type;
12013     xmlNodePtr child = NULL;
12014     xmlAttrPtr attr;
12015 
12016     if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
12017 	(hasRestrictionOrExtension == NULL))
12018         return (-1);
12019     *hasRestrictionOrExtension = 0;
12020     /* Not a component, don't create it. */
12021     type = ctxt->ctxtType;
12022     type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
12023     /*
12024     * Check for illegal attributes.
12025     */
12026     attr = node->properties;
12027     while (attr != NULL) {
12028 	if (attr->ns == NULL) {
12029 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
12030 		xmlSchemaPIllegalAttrErr(ctxt,
12031 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12032 	    }
12033 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12034 	    xmlSchemaPIllegalAttrErr(ctxt,
12035 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12036 	}
12037 	attr = attr->next;
12038     }
12039 
12040     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12041 
12042     /*
12043     * And now for the children...
12044     */
12045     child = node->children;
12046     if (IS_SCHEMA(child, "annotation")) {
12047 	/*
12048 	* Add the annotation to the complex type ancestor.
12049 	*/
12050 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
12051 	    xmlSchemaParseAnnotation(ctxt, child, 1));
12052         child = child->next;
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 (child == NULL) {
12061 	xmlSchemaPContentErr(ctxt,
12062 	    XML_SCHEMAP_S4S_ELEM_MISSING,
12063 	    NULL, node, NULL, NULL,
12064 	    "(annotation?, (restriction | extension))");
12065     }
12066     if (IS_SCHEMA(child, "restriction")) {
12067         xmlSchemaParseRestriction(ctxt, schema, child,
12068 	    XML_SCHEMA_TYPE_SIMPLE_CONTENT);
12069 	(*hasRestrictionOrExtension) = 1;
12070         child = child->next;
12071     } else if (IS_SCHEMA(child, "extension")) {
12072         xmlSchemaParseExtension(ctxt, schema, child,
12073 	    XML_SCHEMA_TYPE_SIMPLE_CONTENT);
12074 	(*hasRestrictionOrExtension) = 1;
12075         child = child->next;
12076     }
12077     if (child != NULL) {
12078 	xmlSchemaPContentErr(ctxt,
12079 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12080 	    NULL, node, child, NULL,
12081 	    "(annotation?, (restriction | extension))");
12082     }
12083     return (0);
12084 }
12085 
12086 /**
12087  * xmlSchemaParseComplexContent:
12088  * @ctxt:  a schema validation context
12089  * @schema:  the schema being built
12090  * @node:  a subtree containing XML Schema information
12091  *
12092  * parse a XML schema ComplexContent definition
12093  * *WARNING* this interface is highly subject to change
12094  *
12095  * Returns the type definition or NULL in case of error
12096  */
12097 static int
xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int * hasRestrictionOrExtension)12098 xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
12099                              xmlSchemaPtr schema, xmlNodePtr node,
12100 			     int *hasRestrictionOrExtension)
12101 {
12102     xmlSchemaTypePtr type;
12103     xmlNodePtr child = NULL;
12104     xmlAttrPtr attr;
12105 
12106     if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
12107 	(hasRestrictionOrExtension == NULL))
12108         return (-1);
12109     *hasRestrictionOrExtension = 0;
12110     /* Not a component, don't create it. */
12111     type = ctxt->ctxtType;
12112     /*
12113     * Check for illegal attributes.
12114     */
12115     attr = node->properties;
12116     while (attr != NULL) {
12117 	if (attr->ns == NULL) {
12118 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
12119 		(!xmlStrEqual(attr->name, BAD_CAST "mixed")))
12120 	    {
12121 		xmlSchemaPIllegalAttrErr(ctxt,
12122 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12123 	    }
12124 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12125 	    xmlSchemaPIllegalAttrErr(ctxt,
12126 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12127 	}
12128 	attr = attr->next;
12129     }
12130 
12131     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12132 
12133     /*
12134     * Set the 'mixed' on the complex type ancestor.
12135     */
12136     if (xmlGetBooleanProp(ctxt, node, "mixed", 0))  {
12137 	if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
12138 	    type->flags |= XML_SCHEMAS_TYPE_MIXED;
12139     }
12140     child = node->children;
12141     if (IS_SCHEMA(child, "annotation")) {
12142 	/*
12143 	* Add the annotation to the complex type ancestor.
12144 	*/
12145 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
12146 	    xmlSchemaParseAnnotation(ctxt, child, 1));
12147         child = child->next;
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 (child == NULL) {
12156 	xmlSchemaPContentErr(ctxt,
12157 	    XML_SCHEMAP_S4S_ELEM_MISSING,
12158 	    NULL, node, NULL,
12159 	    NULL, "(annotation?, (restriction | extension))");
12160     }
12161     if (IS_SCHEMA(child, "restriction")) {
12162         xmlSchemaParseRestriction(ctxt, schema, child,
12163 	    XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12164 	(*hasRestrictionOrExtension) = 1;
12165         child = child->next;
12166     } else if (IS_SCHEMA(child, "extension")) {
12167         xmlSchemaParseExtension(ctxt, schema, child,
12168 	    XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12169 	(*hasRestrictionOrExtension) = 1;
12170         child = child->next;
12171     }
12172     if (child != NULL) {
12173 	xmlSchemaPContentErr(ctxt,
12174 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12175 	    NULL, node, child,
12176 	    NULL, "(annotation?, (restriction | extension))");
12177     }
12178     return (0);
12179 }
12180 
12181 /**
12182  * xmlSchemaParseComplexType:
12183  * @ctxt:  a schema validation context
12184  * @schema:  the schema being built
12185  * @node:  a subtree containing XML Schema information
12186  *
12187  * parse a XML schema Complex Type definition
12188  * *WARNING* this interface is highly subject to change
12189  *
12190  * Returns the type definition or NULL in case of error
12191  */
12192 static xmlSchemaTypePtr
xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int topLevel)12193 xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
12194                           xmlNodePtr node, int topLevel)
12195 {
12196     xmlSchemaTypePtr type, ctxtType;
12197     xmlNodePtr child = NULL;
12198     const xmlChar *name = NULL;
12199     xmlAttrPtr attr;
12200     const xmlChar *attrValue;
12201 #ifdef ENABLE_NAMED_LOCALS
12202     char buf[40];
12203 #endif
12204     int final = 0, block = 0, hasRestrictionOrExtension = 0;
12205 
12206 
12207     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
12208         return (NULL);
12209 
12210     ctxtType = ctxt->ctxtType;
12211 
12212     if (topLevel) {
12213 	attr = xmlSchemaGetPropNode(node, "name");
12214 	if (attr == NULL) {
12215 	    xmlSchemaPMissingAttrErr(ctxt,
12216 		XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
12217 	    return (NULL);
12218 	} else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
12219 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
12220 	    return (NULL);
12221 	}
12222     }
12223 
12224     if (topLevel == 0) {
12225 	/*
12226 	* Parse as local complex type definition.
12227 	*/
12228 #ifdef ENABLE_NAMED_LOCALS
12229         snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
12230 	type = xmlSchemaAddType(ctxt, schema,
12231 	    XML_SCHEMA_TYPE_COMPLEX,
12232 	    xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
12233 	    ctxt->targetNamespace, node, 0);
12234 #else
12235 	type = xmlSchemaAddType(ctxt, schema,
12236 	    XML_SCHEMA_TYPE_COMPLEX,
12237 	    NULL, ctxt->targetNamespace, node, 0);
12238 #endif
12239 	if (type == NULL)
12240 	    return (NULL);
12241 	name = type->name;
12242 	type->node = node;
12243 	type->type = XML_SCHEMA_TYPE_COMPLEX;
12244 	/*
12245 	* TODO: We need the target namespace.
12246 	*/
12247     } else {
12248 	/*
12249 	* Parse as global complex type definition.
12250 	*/
12251 	type = xmlSchemaAddType(ctxt, schema,
12252 	    XML_SCHEMA_TYPE_COMPLEX,
12253 	    name, ctxt->targetNamespace, node, 1);
12254 	if (type == NULL)
12255 	    return (NULL);
12256 	type->node = node;
12257 	type->type = XML_SCHEMA_TYPE_COMPLEX;
12258 	type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
12259     }
12260     type->targetNamespace = ctxt->targetNamespace;
12261     /*
12262     * Handle attributes.
12263     */
12264     attr = node->properties;
12265     while (attr != NULL) {
12266 	if (attr->ns == NULL) {
12267 	    if (xmlStrEqual(attr->name, BAD_CAST "id")) {
12268 		/*
12269 		* Attribute "id".
12270 		*/
12271 		xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12272 	    } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
12273 		/*
12274 		* Attribute "mixed".
12275 		*/
12276 		if (xmlSchemaPGetBoolNodeValue(ctxt,
12277 			NULL, (xmlNodePtr) attr))
12278 		    type->flags |= XML_SCHEMAS_TYPE_MIXED;
12279 	    } else if (topLevel) {
12280 		/*
12281 		* Attributes of global complex type definitions.
12282 		*/
12283 		if (xmlStrEqual(attr->name, BAD_CAST "name")) {
12284 		    /* Pass. */
12285 		} else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
12286 		    /*
12287 		    * Attribute "abstract".
12288 		    */
12289 		    if (xmlSchemaPGetBoolNodeValue(ctxt,
12290 			    NULL, (xmlNodePtr) attr))
12291 			type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
12292 		} else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
12293 		    /*
12294 		    * Attribute "final".
12295 		    */
12296 		    attrValue = xmlSchemaGetNodeContent(ctxt,
12297 			(xmlNodePtr) attr);
12298 		    if (xmlSchemaPValAttrBlockFinal(attrValue,
12299 			&(type->flags),
12300 			-1,
12301 			XML_SCHEMAS_TYPE_FINAL_EXTENSION,
12302 			XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
12303 			-1, -1, -1) != 0)
12304 		    {
12305 			xmlSchemaPSimpleTypeErr(ctxt,
12306 			    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12307 			    NULL, (xmlNodePtr) attr, NULL,
12308 			    "(#all | List of (extension | restriction))",
12309 			    attrValue, NULL, NULL, NULL);
12310 		    } else
12311 			final = 1;
12312 		} else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
12313 		    /*
12314 		    * Attribute "block".
12315 		    */
12316 		    attrValue = xmlSchemaGetNodeContent(ctxt,
12317 			(xmlNodePtr) attr);
12318 		    if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
12319 			-1,
12320 			XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
12321 			XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
12322 			-1, -1, -1) != 0) {
12323 			xmlSchemaPSimpleTypeErr(ctxt,
12324 			    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12325 			    NULL, (xmlNodePtr) attr, NULL,
12326 			    "(#all | List of (extension | restriction)) ",
12327 			    attrValue, NULL, NULL, NULL);
12328 		    } else
12329 			block = 1;
12330 		} else {
12331 			xmlSchemaPIllegalAttrErr(ctxt,
12332 			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12333 		}
12334 	    } else {
12335 		xmlSchemaPIllegalAttrErr(ctxt,
12336 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12337 	    }
12338 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12339 	    xmlSchemaPIllegalAttrErr(ctxt,
12340 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12341 	}
12342 	attr = attr->next;
12343     }
12344     if (! block) {
12345 	/*
12346 	* Apply default "block" values.
12347 	*/
12348 	if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
12349 	    type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
12350 	if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
12351 	    type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
12352     }
12353     if (! final) {
12354 	/*
12355 	* Apply default "block" values.
12356 	*/
12357 	if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
12358 	    type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
12359 	if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
12360 	    type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
12361     }
12362     /*
12363     * And now for the children...
12364     */
12365     child = node->children;
12366     if (IS_SCHEMA(child, "annotation")) {
12367         type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
12368         child = child->next;
12369     }
12370     ctxt->ctxtType = type;
12371     if (IS_SCHEMA(child, "simpleContent")) {
12372 	/*
12373 	* <complexType><simpleContent>...
12374 	* 3.4.3 : 2.2
12375 	* Specifying mixed='true' when the <simpleContent>
12376 	* alternative is chosen has no effect
12377 	*/
12378 	if (type->flags & XML_SCHEMAS_TYPE_MIXED)
12379 	    type->flags ^= XML_SCHEMAS_TYPE_MIXED;
12380         xmlSchemaParseSimpleContent(ctxt, schema, child,
12381 	    &hasRestrictionOrExtension);
12382         child = child->next;
12383     } else if (IS_SCHEMA(child, "complexContent")) {
12384 	/*
12385 	* <complexType><complexContent>...
12386 	*/
12387 	type->contentType = XML_SCHEMA_CONTENT_EMPTY;
12388         xmlSchemaParseComplexContent(ctxt, schema, child,
12389 	    &hasRestrictionOrExtension);
12390         child = child->next;
12391     } else {
12392 	/*
12393 	* E.g <complexType><sequence>... or <complexType><attribute>... etc.
12394 	*
12395 	* SPEC
12396 	* "...the third alternative (neither <simpleContent> nor
12397 	* <complexContent>) is chosen. This case is understood as shorthand
12398 	* for complex content restricting the `ur-type definition`, and the
12399 	* details of the mappings should be modified as necessary.
12400 	*/
12401 	type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12402 	type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
12403 	/*
12404 	* Parse model groups.
12405 	*/
12406         if (IS_SCHEMA(child, "all")) {
12407             type->subtypes = (xmlSchemaTypePtr)
12408 		xmlSchemaParseModelGroup(ctxt, schema, child,
12409 		    XML_SCHEMA_TYPE_ALL, 1);
12410             child = child->next;
12411         } else if (IS_SCHEMA(child, "choice")) {
12412             type->subtypes = (xmlSchemaTypePtr)
12413 		xmlSchemaParseModelGroup(ctxt, schema, child,
12414 		    XML_SCHEMA_TYPE_CHOICE, 1);
12415             child = child->next;
12416         } else if (IS_SCHEMA(child, "sequence")) {
12417             type->subtypes = (xmlSchemaTypePtr)
12418 		xmlSchemaParseModelGroup(ctxt, schema, child,
12419 		    XML_SCHEMA_TYPE_SEQUENCE, 1);
12420             child = child->next;
12421         } else if (IS_SCHEMA(child, "group")) {
12422             type->subtypes = (xmlSchemaTypePtr)
12423 		xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
12424 	    /*
12425 	    * Note that the reference will be resolved in
12426 	    * xmlSchemaResolveTypeReferences();
12427 	    */
12428             child = child->next;
12429         }
12430 	/*
12431 	* Parse attribute decls/refs.
12432 	*/
12433         if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
12434 	    (xmlSchemaItemListPtr *) &(type->attrUses),
12435 	    XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
12436 	    return(NULL);
12437 	/*
12438 	* Parse attribute wildcard.
12439 	*/
12440 	if (IS_SCHEMA(child, "anyAttribute")) {
12441 	    type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
12442 	    child = child->next;
12443 	}
12444     }
12445     if (child != NULL) {
12446 	xmlSchemaPContentErr(ctxt,
12447 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12448 	    NULL, node, child,
12449 	    NULL, "(annotation?, (simpleContent | complexContent | "
12450 	    "((group | all | choice | sequence)?, ((attribute | "
12451 	    "attributeGroup)*, anyAttribute?))))");
12452     }
12453     /*
12454     * REDEFINE: SPEC src-redefine (5)
12455     */
12456     if (topLevel && ctxt->isRedefine && (! hasRestrictionOrExtension)) {
12457 	xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
12458 	    NULL, node, "This is a redefinition, thus the "
12459 	    "<complexType> must have a <restriction> or <extension> "
12460 	    "grand-child", NULL);
12461     }
12462     ctxt->ctxtType = ctxtType;
12463     return (type);
12464 }
12465 
12466 /************************************************************************
12467  *									*
12468  *			Validating using Schemas			*
12469  *									*
12470  ************************************************************************/
12471 
12472 /************************************************************************
12473  *									*
12474  *			Reading/Writing Schemas				*
12475  *									*
12476  ************************************************************************/
12477 
12478 #if 0 /* Will be enabled if it is clear what options are needed. */
12479 /**
12480  * xmlSchemaParserCtxtSetOptions:
12481  * @ctxt:	a schema parser context
12482  * @options: a combination of xmlSchemaParserOption
12483  *
12484  * Sets the options to be used during the parse.
12485  *
12486  * Returns 0 in case of success, -1 in case of an
12487  * API error.
12488  */
12489 static int
12490 xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
12491 			      int options)
12492 
12493 {
12494     int i;
12495 
12496     if (ctxt == NULL)
12497 	return (-1);
12498     /*
12499     * WARNING: Change the start value if adding to the
12500     * xmlSchemaParseOption.
12501     */
12502     for (i = 1; i < (int) sizeof(int) * 8; i++) {
12503         if (options & 1<<i) {
12504 	    return (-1);
12505         }
12506     }
12507     ctxt->options = options;
12508     return (0);
12509 }
12510 
12511 /**
12512  * xmlSchemaValidCtxtGetOptions:
12513  * @ctxt: a schema parser context
12514  *
12515  * Returns the option combination of the parser context.
12516  */
12517 static int
12518 xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
12519 
12520 {
12521     if (ctxt == NULL)
12522 	return (-1);
12523     else
12524 	return (ctxt->options);
12525 }
12526 #endif
12527 
12528 /**
12529  * xmlSchemaNewParserCtxt:
12530  * @URL:  the location of the schema
12531  *
12532  * Create an XML Schemas parse context for that file/resource expected
12533  * to contain an XML Schemas file.
12534  *
12535  * Returns the parser context or NULL in case of error
12536  */
12537 xmlSchemaParserCtxtPtr
xmlSchemaNewParserCtxt(const char * URL)12538 xmlSchemaNewParserCtxt(const char *URL)
12539 {
12540     xmlSchemaParserCtxtPtr ret;
12541 
12542     if (URL == NULL)
12543         return (NULL);
12544 
12545     ret = xmlSchemaParserCtxtCreate();
12546     if (ret == NULL)
12547 	return(NULL);
12548     ret->dict = xmlDictCreate();
12549     ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
12550     return (ret);
12551 }
12552 
12553 /**
12554  * xmlSchemaNewMemParserCtxt:
12555  * @buffer:  a pointer to a char array containing the schemas
12556  * @size:  the size of the array
12557  *
12558  * Create an XML Schemas parse context for that memory buffer expected
12559  * to contain an XML Schemas file.
12560  *
12561  * Returns the parser context or NULL in case of error
12562  */
12563 xmlSchemaParserCtxtPtr
xmlSchemaNewMemParserCtxt(const char * buffer,int size)12564 xmlSchemaNewMemParserCtxt(const char *buffer, int size)
12565 {
12566     xmlSchemaParserCtxtPtr ret;
12567 
12568     if ((buffer == NULL) || (size <= 0))
12569         return (NULL);
12570     ret = xmlSchemaParserCtxtCreate();
12571     if (ret == NULL)
12572 	return(NULL);
12573     ret->buffer = buffer;
12574     ret->size = size;
12575     ret->dict = xmlDictCreate();
12576     return (ret);
12577 }
12578 
12579 /**
12580  * xmlSchemaNewDocParserCtxt:
12581  * @doc:  a preparsed document tree
12582  *
12583  * Create an XML Schemas parse context for that document.
12584  * NB. The document may be modified during the parsing process.
12585  *
12586  * Returns the parser context or NULL in case of error
12587  */
12588 xmlSchemaParserCtxtPtr
xmlSchemaNewDocParserCtxt(xmlDocPtr doc)12589 xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
12590 {
12591     xmlSchemaParserCtxtPtr ret;
12592 
12593     if (doc == NULL)
12594       return (NULL);
12595     ret = xmlSchemaParserCtxtCreate();
12596     if (ret == NULL)
12597 	return(NULL);
12598     ret->doc = doc;
12599     ret->dict = xmlDictCreate();
12600     /* The application has responsibility for the document */
12601     ret->preserve = 1;
12602 
12603     return (ret);
12604 }
12605 
12606 /**
12607  * xmlSchemaFreeParserCtxt:
12608  * @ctxt:  the schema parser context
12609  *
12610  * Free the resources associated to the schema parser context
12611  */
12612 void
xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)12613 xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
12614 {
12615     if (ctxt == NULL)
12616         return;
12617     if (ctxt->doc != NULL && !ctxt->preserve)
12618         xmlFreeDoc(ctxt->doc);
12619     if (ctxt->vctxt != NULL) {
12620 	xmlSchemaFreeValidCtxt(ctxt->vctxt);
12621     }
12622     if (ctxt->ownsConstructor && (ctxt->constructor != NULL)) {
12623 	xmlSchemaConstructionCtxtFree(ctxt->constructor);
12624 	ctxt->constructor = NULL;
12625 	ctxt->ownsConstructor = 0;
12626     }
12627     if (ctxt->attrProhibs != NULL)
12628 	xmlSchemaItemListFree(ctxt->attrProhibs);
12629     xmlDictFree(ctxt->dict);
12630     xmlFree(ctxt);
12631 }
12632 
12633 /************************************************************************
12634  *									*
12635  *			Building the content models			*
12636  *									*
12637  ************************************************************************/
12638 
12639 /**
12640  * xmlSchemaBuildContentModelForSubstGroup:
12641  *
12642  * Returns 1 if nillable, 0 otherwise
12643  */
12644 static int
xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,xmlSchemaParticlePtr particle,int counter,xmlAutomataStatePtr end)12645 xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
12646 	xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end)
12647 {
12648     xmlAutomataStatePtr start, tmp;
12649     xmlSchemaElementPtr elemDecl, member;
12650     xmlSchemaSubstGroupPtr substGroup;
12651     int i;
12652     int ret = 0;
12653 
12654     elemDecl = (xmlSchemaElementPtr) particle->children;
12655     /*
12656     * Wrap the substitution group with a CHOICE.
12657     */
12658     start = pctxt->state;
12659     if (end == NULL)
12660 	end = xmlAutomataNewState(pctxt->am);
12661     substGroup = xmlSchemaSubstGroupGet(pctxt, elemDecl);
12662     if (substGroup == NULL) {
12663 	xmlSchemaPErr(pctxt, WXS_ITEM_NODE(particle),
12664 	    XML_SCHEMAP_INTERNAL,
12665 	    "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
12666 	    "declaration is marked having a subst. group but none "
12667 	    "available.\n", elemDecl->name, NULL);
12668 	return(0);
12669     }
12670     if (counter >= 0) {
12671 	/*
12672 	* NOTE that we put the declaration in, even if it's abstract.
12673 	* However, an error will be raised during *validation* if an element
12674 	* information item shall be validated against an abstract element
12675 	* declaration.
12676 	*/
12677 	tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter);
12678         xmlAutomataNewTransition2(pctxt->am, tmp, end,
12679 	            elemDecl->name, elemDecl->targetNamespace, elemDecl);
12680 	/*
12681 	* Add subst. group members.
12682 	*/
12683 	for (i = 0; i < substGroup->members->nbItems; i++) {
12684 	    member = (xmlSchemaElementPtr) substGroup->members->items[i];
12685             xmlAutomataNewTransition2(pctxt->am, tmp, end,
12686 		               member->name, member->targetNamespace, member);
12687 	}
12688     } else if (particle->maxOccurs == 1) {
12689 	/*
12690 	* NOTE that we put the declaration in, even if it's abstract,
12691 	*/
12692 	xmlAutomataNewEpsilon(pctxt->am,
12693 	    xmlAutomataNewTransition2(pctxt->am,
12694 	    start, NULL,
12695 	    elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
12696 	/*
12697 	* Add subst. group members.
12698 	*/
12699 	for (i = 0; i < substGroup->members->nbItems; i++) {
12700 	    member = (xmlSchemaElementPtr) substGroup->members->items[i];
12701 	    /*
12702 	    * NOTE: This fixes bug #341150. xmlAutomataNewOnceTrans2()
12703 	    *  was incorrectly used instead of xmlAutomataNewTransition2()
12704 	    *  (seems like a copy&paste bug from the XML_SCHEMA_TYPE_ALL
12705 	    *  section in xmlSchemaBuildAContentModel() ).
12706 	    * TODO: Check if xmlAutomataNewOnceTrans2() was instead
12707 	    *  intended for the above "counter" section originally. I.e.,
12708 	    *  check xs:all with subst-groups.
12709 	    *
12710 	    * tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL,
12711 	    *	               member->name, member->targetNamespace,
12712 	    *		       1, 1, member);
12713 	    */
12714 	    tmp = xmlAutomataNewTransition2(pctxt->am, start, NULL,
12715 		member->name, member->targetNamespace, member);
12716 	    xmlAutomataNewEpsilon(pctxt->am, tmp, end);
12717 	}
12718     } else {
12719 	xmlAutomataStatePtr hop;
12720 	int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12721 	    UNBOUNDED : particle->maxOccurs - 1;
12722 	int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12723 
12724 	counter =
12725 	    xmlAutomataNewCounter(pctxt->am, minOccurs,
12726 	    maxOccurs);
12727 	hop = xmlAutomataNewState(pctxt->am);
12728 
12729 	xmlAutomataNewEpsilon(pctxt->am,
12730 	    xmlAutomataNewTransition2(pctxt->am,
12731 	    start, NULL,
12732 	    elemDecl->name, elemDecl->targetNamespace, elemDecl),
12733 	    hop);
12734 	/*
12735 	 * Add subst. group members.
12736 	 */
12737 	for (i = 0; i < substGroup->members->nbItems; i++) {
12738 	    member = (xmlSchemaElementPtr) substGroup->members->items[i];
12739 	    xmlAutomataNewEpsilon(pctxt->am,
12740 		xmlAutomataNewTransition2(pctxt->am,
12741 		start, NULL,
12742 		member->name, member->targetNamespace, member),
12743 		hop);
12744 	}
12745 	xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12746 	xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12747     }
12748     if (particle->minOccurs == 0) {
12749 	xmlAutomataNewEpsilon(pctxt->am, start, end);
12750         ret = 1;
12751     }
12752     pctxt->state = end;
12753     return(ret);
12754 }
12755 
12756 /**
12757  * xmlSchemaBuildContentModelForElement:
12758  *
12759  * Returns 1 if nillable, 0 otherwise
12760  */
12761 static int
xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr particle)12762 xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
12763 				     xmlSchemaParticlePtr particle)
12764 {
12765     int ret = 0;
12766 
12767     if (((xmlSchemaElementPtr) particle->children)->flags &
12768 	XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
12769 	/*
12770 	* Substitution groups.
12771 	*/
12772 	ret = xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
12773     } else {
12774 	xmlSchemaElementPtr elemDecl;
12775 	xmlAutomataStatePtr start;
12776 
12777 	elemDecl = (xmlSchemaElementPtr) particle->children;
12778 
12779 	if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
12780 	    return(0);
12781 	if (particle->maxOccurs == 1) {
12782 	    start = ctxt->state;
12783 	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12784 		    elemDecl->name, elemDecl->targetNamespace, elemDecl);
12785 	} else if ((particle->maxOccurs >= UNBOUNDED) &&
12786 	           (particle->minOccurs < 2)) {
12787 	    /* Special case. */
12788 	    start = ctxt->state;
12789 	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12790 		elemDecl->name, elemDecl->targetNamespace, elemDecl);
12791 	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, ctxt->state, ctxt->state,
12792 		elemDecl->name, elemDecl->targetNamespace, elemDecl);
12793 	} else {
12794 	    int counter;
12795 	    int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12796 			    UNBOUNDED : particle->maxOccurs - 1;
12797 	    int minOccurs = particle->minOccurs < 1 ?
12798 			    0 : particle->minOccurs - 1;
12799 
12800 	    start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
12801 	    counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
12802 	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12803 		elemDecl->name, elemDecl->targetNamespace, elemDecl);
12804 	    xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
12805 	    ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
12806 		NULL, counter);
12807 	}
12808 	if (particle->minOccurs == 0) {
12809 	    xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
12810             ret = 1;
12811         }
12812     }
12813     return(ret);
12814 }
12815 
12816 /**
12817  * xmlSchemaBuildAContentModel:
12818  * @ctxt:  the schema parser context
12819  * @particle:  the particle component
12820  * @name:  the complex type's name whose content is being built
12821  *
12822  * Create the automaton for the {content type} of a complex type.
12823  *
12824  * Returns 1 if the content is nillable, 0 otherwise
12825  */
12826 static int
xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,xmlSchemaParticlePtr particle)12827 xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
12828 			    xmlSchemaParticlePtr particle)
12829 {
12830     int ret = 0, tmp2;
12831 
12832     if (particle == NULL) {
12833 	PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL");
12834 	return(1);
12835     }
12836     if (particle->children == NULL) {
12837 	/*
12838 	* Just return in this case. A missing "term" of the particle
12839 	* might arise due to an invalid "term" component.
12840 	*/
12841 	return(1);
12842     }
12843 
12844     switch (particle->children->type) {
12845 	case XML_SCHEMA_TYPE_ANY: {
12846 	    xmlAutomataStatePtr start, end;
12847 	    xmlSchemaWildcardPtr wild;
12848 	    xmlSchemaWildcardNsPtr ns;
12849 
12850 	    wild = (xmlSchemaWildcardPtr) particle->children;
12851 
12852 	    start = pctxt->state;
12853 	    end = xmlAutomataNewState(pctxt->am);
12854 
12855 	    if (particle->maxOccurs == 1) {
12856 		if (wild->any == 1) {
12857 		    /*
12858 		    * We need to add both transitions:
12859 		    *
12860 		    * 1. the {"*", "*"} for elements in a namespace.
12861 		    */
12862 		    pctxt->state =
12863 			xmlAutomataNewTransition2(pctxt->am,
12864 			start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12865 		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12866 		    /*
12867 		    * 2. the {"*"} for elements in no namespace.
12868 		    */
12869 		    pctxt->state =
12870 			xmlAutomataNewTransition2(pctxt->am,
12871 			start, NULL, BAD_CAST "*", NULL, wild);
12872 		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12873 
12874 		} else if (wild->nsSet != NULL) {
12875 		    ns = wild->nsSet;
12876 		    do {
12877 			pctxt->state = start;
12878 			pctxt->state = xmlAutomataNewTransition2(pctxt->am,
12879 			    pctxt->state, NULL, BAD_CAST "*", ns->value, wild);
12880 			xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12881 			ns = ns->next;
12882 		    } while (ns != NULL);
12883 
12884 		} else if (wild->negNsSet != NULL) {
12885 		    pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12886 			start, end, BAD_CAST "*", wild->negNsSet->value,
12887 			wild);
12888 		}
12889 	    } else {
12890 		int counter;
12891 		xmlAutomataStatePtr hop;
12892 		int maxOccurs =
12893 		    particle->maxOccurs == UNBOUNDED ? UNBOUNDED :
12894                                            particle->maxOccurs - 1;
12895 		int minOccurs =
12896 		    particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12897 
12898 		counter = xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12899 		hop = xmlAutomataNewState(pctxt->am);
12900 		if (wild->any == 1) {
12901 		    pctxt->state =
12902 			xmlAutomataNewTransition2(pctxt->am,
12903 			start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12904 		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12905 		    pctxt->state =
12906 			xmlAutomataNewTransition2(pctxt->am,
12907 			start, NULL, BAD_CAST "*", NULL, wild);
12908 		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12909 		} else if (wild->nsSet != NULL) {
12910 		    ns = wild->nsSet;
12911 		    do {
12912 			pctxt->state =
12913 			    xmlAutomataNewTransition2(pctxt->am,
12914 				start, NULL, BAD_CAST "*", ns->value, wild);
12915 			xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12916 			ns = ns->next;
12917 		    } while (ns != NULL);
12918 
12919 		} else if (wild->negNsSet != NULL) {
12920 		    pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12921 			start, hop, BAD_CAST "*", wild->negNsSet->value,
12922 			wild);
12923 		}
12924 		xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12925 		xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12926 	    }
12927 	    if (particle->minOccurs == 0) {
12928 		xmlAutomataNewEpsilon(pctxt->am, start, end);
12929                 ret = 1;
12930 	    }
12931 	    pctxt->state = end;
12932             break;
12933 	}
12934         case XML_SCHEMA_TYPE_ELEMENT:
12935 	    ret = xmlSchemaBuildContentModelForElement(pctxt, particle);
12936 	    break;
12937         case XML_SCHEMA_TYPE_SEQUENCE:{
12938             xmlSchemaTreeItemPtr sub;
12939 
12940             ret = 1;
12941             /*
12942              * If max and min occurrences are default (1) then
12943              * simply iterate over the particles of the <sequence>.
12944              */
12945             if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
12946                 sub = particle->children->children;
12947 
12948                 while (sub != NULL) {
12949                     tmp2 = xmlSchemaBuildAContentModel(pctxt,
12950                                         (xmlSchemaParticlePtr) sub);
12951                     if (tmp2 != 1) ret = 0;
12952                     sub = sub->next;
12953                 }
12954             } else {
12955                 xmlAutomataStatePtr oldstate = pctxt->state;
12956 
12957                 if (particle->maxOccurs >= UNBOUNDED) {
12958                     if (particle->minOccurs > 1) {
12959                         xmlAutomataStatePtr tmp;
12960                         int counter;
12961 
12962                         pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12963                             oldstate, NULL);
12964                         oldstate = pctxt->state;
12965 
12966                         counter = xmlAutomataNewCounter(pctxt->am,
12967                             particle->minOccurs - 1, UNBOUNDED);
12968 
12969                         sub = particle->children->children;
12970                         while (sub != NULL) {
12971                             tmp2 = xmlSchemaBuildAContentModel(pctxt,
12972                                             (xmlSchemaParticlePtr) sub);
12973                             if (tmp2 != 1) ret = 0;
12974                             sub = sub->next;
12975                         }
12976                         tmp = pctxt->state;
12977                         xmlAutomataNewCountedTrans(pctxt->am, tmp,
12978                                                    oldstate, counter);
12979                         pctxt->state =
12980                             xmlAutomataNewCounterTrans(pctxt->am, tmp,
12981                                                        NULL, counter);
12982                         if (ret == 1)
12983                             xmlAutomataNewEpsilon(pctxt->am,
12984                                                 oldstate, pctxt->state);
12985 
12986                     } else {
12987                         pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12988                             oldstate, NULL);
12989                         oldstate = pctxt->state;
12990 
12991                         sub = particle->children->children;
12992                         while (sub != NULL) {
12993                             tmp2 = xmlSchemaBuildAContentModel(pctxt,
12994                                         (xmlSchemaParticlePtr) sub);
12995                             if (tmp2 != 1) ret = 0;
12996                             sub = sub->next;
12997                         }
12998                         xmlAutomataNewEpsilon(pctxt->am, pctxt->state,
12999                                               oldstate);
13000                         /*
13001                          * epsilon needed to block previous trans from
13002                          * being allowed to enter back from another
13003                          * construct
13004                          */
13005                         pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
13006                                             pctxt->state, NULL);
13007                         if (particle->minOccurs == 0) {
13008                             xmlAutomataNewEpsilon(pctxt->am,
13009                                 oldstate, pctxt->state);
13010                             ret = 1;
13011                         }
13012                     }
13013                 } else if ((particle->maxOccurs > 1)
13014                            || (particle->minOccurs > 1)) {
13015                     xmlAutomataStatePtr tmp;
13016                     int counter;
13017 
13018                     pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
13019                         oldstate, NULL);
13020                     oldstate = pctxt->state;
13021 
13022                     counter = xmlAutomataNewCounter(pctxt->am,
13023                         particle->minOccurs - 1,
13024                         particle->maxOccurs - 1);
13025 
13026                     sub = particle->children->children;
13027                     while (sub != NULL) {
13028                         tmp2 = xmlSchemaBuildAContentModel(pctxt,
13029                                         (xmlSchemaParticlePtr) sub);
13030                         if (tmp2 != 1) ret = 0;
13031                         sub = sub->next;
13032                     }
13033                     tmp = pctxt->state;
13034                     xmlAutomataNewCountedTrans(pctxt->am,
13035                         tmp, oldstate, counter);
13036                     pctxt->state =
13037                         xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL,
13038                                                    counter);
13039                     if ((particle->minOccurs == 0) || (ret == 1)) {
13040                         xmlAutomataNewEpsilon(pctxt->am,
13041                                             oldstate, pctxt->state);
13042                         ret = 1;
13043                     }
13044                 } else {
13045                     sub = particle->children->children;
13046                     while (sub != NULL) {
13047                         tmp2 = xmlSchemaBuildAContentModel(pctxt,
13048                                         (xmlSchemaParticlePtr) sub);
13049                         if (tmp2 != 1) ret = 0;
13050                         sub = sub->next;
13051                     }
13052 
13053 		    /*
13054 		     * epsilon needed to block previous trans from
13055 		     * being allowed to enter back from another
13056 		     * construct
13057 		     */
13058 		    pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
13059 					pctxt->state, NULL);
13060 
13061                     if (particle->minOccurs == 0) {
13062                         xmlAutomataNewEpsilon(pctxt->am, oldstate,
13063                                               pctxt->state);
13064                         ret = 1;
13065                     }
13066                 }
13067             }
13068             break;
13069         }
13070         case XML_SCHEMA_TYPE_CHOICE:{
13071             xmlSchemaTreeItemPtr sub;
13072             xmlAutomataStatePtr start, end;
13073 
13074             ret = 0;
13075             start = pctxt->state;
13076             end = xmlAutomataNewState(pctxt->am);
13077 
13078             /*
13079              * iterate over the subtypes and remerge the end with an
13080              * epsilon transition
13081              */
13082             if (particle->maxOccurs == 1) {
13083                 sub = particle->children->children;
13084                 while (sub != NULL) {
13085                     pctxt->state = start;
13086                     tmp2 = xmlSchemaBuildAContentModel(pctxt,
13087                                         (xmlSchemaParticlePtr) sub);
13088                     if (tmp2 == 1) ret = 1;
13089                     xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
13090                     sub = sub->next;
13091                 }
13092             } else {
13093                 int counter;
13094                 xmlAutomataStatePtr hop, base;
13095                 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
13096                     UNBOUNDED : particle->maxOccurs - 1;
13097                 int minOccurs =
13098                     particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
13099 
13100                 /*
13101                  * use a counter to keep track of the number of transitions
13102                  * which went through the choice.
13103                  */
13104                 counter =
13105                     xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
13106                 hop = xmlAutomataNewState(pctxt->am);
13107                 base = xmlAutomataNewState(pctxt->am);
13108 
13109                 sub = particle->children->children;
13110                 while (sub != NULL) {
13111                     pctxt->state = base;
13112                     tmp2 = xmlSchemaBuildAContentModel(pctxt,
13113                                         (xmlSchemaParticlePtr) sub);
13114                     if (tmp2 == 1) ret = 1;
13115                     xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
13116                     sub = sub->next;
13117                 }
13118                 xmlAutomataNewEpsilon(pctxt->am, start, base);
13119                 xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter);
13120                 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
13121                 if (ret == 1)
13122                     xmlAutomataNewEpsilon(pctxt->am, base, end);
13123             }
13124             if (particle->minOccurs == 0) {
13125                 xmlAutomataNewEpsilon(pctxt->am, start, end);
13126                 ret = 1;
13127             }
13128             pctxt->state = end;
13129             break;
13130         }
13131         case XML_SCHEMA_TYPE_ALL:{
13132             xmlAutomataStatePtr start, tmp;
13133             xmlSchemaParticlePtr sub;
13134             xmlSchemaElementPtr elemDecl;
13135 
13136             ret = 1;
13137 
13138             sub = (xmlSchemaParticlePtr) particle->children->children;
13139             if (sub == NULL)
13140                 break;
13141 
13142             ret = 0;
13143 
13144             start = pctxt->state;
13145             tmp = xmlAutomataNewState(pctxt->am);
13146             xmlAutomataNewEpsilon(pctxt->am, pctxt->state, tmp);
13147             pctxt->state = tmp;
13148             while (sub != NULL) {
13149                 pctxt->state = tmp;
13150 
13151                 elemDecl = (xmlSchemaElementPtr) sub->children;
13152                 if (elemDecl == NULL) {
13153                     PERROR_INT("xmlSchemaBuildAContentModel",
13154                         "<element> particle has no term");
13155                     return(ret);
13156                 };
13157                 /*
13158                 * NOTE: The {max occurs} of all the particles in the
13159                 * {particles} of the group must be 0 or 1; this is
13160                 * already ensured during the parse of the content of
13161                 * <all>.
13162                 */
13163                 if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
13164                     int counter;
13165 
13166                     /*
13167                      * This is an abstract group, we need to share
13168                      * the same counter for all the element transitions
13169                      * derived from the group
13170                      */
13171                     counter = xmlAutomataNewCounter(pctxt->am,
13172                                        sub->minOccurs, sub->maxOccurs);
13173                     xmlSchemaBuildContentModelForSubstGroup(pctxt,
13174                                        sub, counter, pctxt->state);
13175                 } else {
13176                     if ((sub->minOccurs == 1) &&
13177                         (sub->maxOccurs == 1)) {
13178                         xmlAutomataNewOnceTrans2(pctxt->am, pctxt->state,
13179                                                 pctxt->state,
13180                                                 elemDecl->name,
13181                                                 elemDecl->targetNamespace,
13182                                                 1, 1, elemDecl);
13183                     } else if ((sub->minOccurs == 0) &&
13184                         (sub->maxOccurs == 1)) {
13185 
13186                         xmlAutomataNewCountTrans2(pctxt->am, pctxt->state,
13187                                                  pctxt->state,
13188                                                  elemDecl->name,
13189                                                  elemDecl->targetNamespace,
13190                                                  0,
13191                                                  1,
13192                                                  elemDecl);
13193                     }
13194                 }
13195                 sub = (xmlSchemaParticlePtr) sub->next;
13196             }
13197             pctxt->state =
13198                 xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, 0);
13199             if (particle->minOccurs == 0) {
13200                 xmlAutomataNewEpsilon(pctxt->am, start, pctxt->state);
13201                 ret = 1;
13202             }
13203             break;
13204         }
13205 	case XML_SCHEMA_TYPE_GROUP:
13206 	    /*
13207 	    * If we hit a model group definition, then this means that
13208 	    * it was empty, thus was not substituted for the containing
13209 	    * model group. Just do nothing in this case.
13210 	    * TODO: But the group should be substituted and not occur at
13211 	    * all in the content model at this point. Fix this.
13212 	    */
13213             ret = 1;
13214 	    break;
13215         default:
13216 	    xmlSchemaInternalErr2(ACTXT_CAST pctxt,
13217 		"xmlSchemaBuildAContentModel",
13218 		"found unexpected term of type '%s' in content model",
13219 		WXS_ITEM_TYPE_NAME(particle->children), NULL);
13220             return(ret);
13221     }
13222     return(ret);
13223 }
13224 
13225 /**
13226  * xmlSchemaBuildContentModel:
13227  * @ctxt:  the schema parser context
13228  * @type:  the complex type definition
13229  * @name:  the element name
13230  *
13231  * Builds the content model of the complex type.
13232  */
13233 static void
xmlSchemaBuildContentModel(xmlSchemaTypePtr type,xmlSchemaParserCtxtPtr ctxt)13234 xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
13235 			   xmlSchemaParserCtxtPtr ctxt)
13236 {
13237     if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
13238 	(type->contModel != NULL) ||
13239 	((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
13240 	(type->contentType != XML_SCHEMA_CONTENT_MIXED)))
13241 	return;
13242 
13243 #ifdef DEBUG_CONTENT
13244     xmlGenericError(xmlGenericErrorContext,
13245                     "Building content model for %s\n", name);
13246 #endif
13247     ctxt->am = NULL;
13248     ctxt->am = xmlNewAutomata();
13249     if (ctxt->am == NULL) {
13250         xmlGenericError(xmlGenericErrorContext,
13251 	    "Cannot create automata for complex type %s\n", type->name);
13252         return;
13253     }
13254     ctxt->state = xmlAutomataGetInitState(ctxt->am);
13255     /*
13256     * Build the automaton.
13257     */
13258     xmlSchemaBuildAContentModel(ctxt, WXS_TYPE_PARTICLE(type));
13259     xmlAutomataSetFinalState(ctxt->am, ctxt->state);
13260     type->contModel = xmlAutomataCompile(ctxt->am);
13261     if (type->contModel == NULL) {
13262         xmlSchemaPCustomErr(ctxt,
13263 	    XML_SCHEMAP_INTERNAL,
13264 	    WXS_BASIC_CAST type, type->node,
13265 	    "Failed to compile the content model", NULL);
13266     } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
13267         xmlSchemaPCustomErr(ctxt,
13268 	    XML_SCHEMAP_NOT_DETERMINISTIC,
13269 	    /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
13270 	    WXS_BASIC_CAST type, type->node,
13271 	    "The content model is not determinist", NULL);
13272     } else {
13273 #ifdef DEBUG_CONTENT_REGEXP
13274         xmlGenericError(xmlGenericErrorContext,
13275                         "Content model of %s:\n", type->name);
13276         xmlRegexpPrint(stderr, type->contModel);
13277 #endif
13278     }
13279     ctxt->state = NULL;
13280     xmlFreeAutomata(ctxt->am);
13281     ctxt->am = NULL;
13282 }
13283 
13284 /**
13285  * xmlSchemaResolveElementReferences:
13286  * @elem:  the schema element context
13287  * @ctxt:  the schema parser context
13288  *
13289  * Resolves the references of an element declaration
13290  * or particle, which has an element declaration as it's
13291  * term.
13292  */
13293 static void
xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,xmlSchemaParserCtxtPtr ctxt)13294 xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,
13295 				  xmlSchemaParserCtxtPtr ctxt)
13296 {
13297     if ((ctxt == NULL) || (elemDecl == NULL) ||
13298 	((elemDecl != NULL) &&
13299 	(elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
13300         return;
13301     elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
13302 
13303     if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
13304 	xmlSchemaTypePtr type;
13305 
13306 	/* (type definition) ... otherwise the type definition `resolved`
13307 	* to by the `actual value` of the type [attribute] ...
13308 	*/
13309 	type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
13310 	    elemDecl->namedTypeNs);
13311 	if (type == NULL) {
13312 	    xmlSchemaPResCompAttrErr(ctxt,
13313 		XML_SCHEMAP_SRC_RESOLVE,
13314 		WXS_BASIC_CAST elemDecl, elemDecl->node,
13315 		"type", elemDecl->namedType, elemDecl->namedTypeNs,
13316 		XML_SCHEMA_TYPE_BASIC, "type definition");
13317 	} else
13318 	    elemDecl->subtypes = type;
13319     }
13320     if (elemDecl->substGroup != NULL) {
13321 	xmlSchemaElementPtr substHead;
13322 
13323 	/*
13324 	* FIXME TODO: Do we need a new field in _xmlSchemaElement for
13325 	* substitutionGroup?
13326 	*/
13327 	substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
13328 	    elemDecl->substGroupNs);
13329 	if (substHead == NULL) {
13330 	    xmlSchemaPResCompAttrErr(ctxt,
13331 		XML_SCHEMAP_SRC_RESOLVE,
13332 		WXS_BASIC_CAST elemDecl, NULL,
13333 		"substitutionGroup", elemDecl->substGroup,
13334 		elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
13335 	} else {
13336 	    xmlSchemaResolveElementReferences(substHead, ctxt);
13337 	    /*
13338 	    * Set the "substitution group affiliation".
13339 	    * NOTE that now we use the "refDecl" field for this.
13340 	    */
13341 	    WXS_SUBST_HEAD(elemDecl) = substHead;
13342 	    /*
13343 	    * The type definitions is set to:
13344 	    * SPEC "...the {type definition} of the element
13345 	    * declaration `resolved` to by the `actual value`
13346 	    * of the substitutionGroup [attribute], if present"
13347 	    */
13348 	    if (elemDecl->subtypes == NULL) {
13349                 if (substHead->subtypes == NULL) {
13350                     /*
13351                      * This can happen with self-referencing substitution
13352                      * groups. The cycle will be detected later, but we have
13353                      * to set subtypes to avoid null-pointer dereferences.
13354                      */
13355 	            elemDecl->subtypes = xmlSchemaGetBuiltInType(
13356                             XML_SCHEMAS_ANYTYPE);
13357                 } else {
13358 		    elemDecl->subtypes = substHead->subtypes;
13359                 }
13360             }
13361 	}
13362     }
13363     /*
13364     * SPEC "The definition of anyType serves as the default type definition
13365     * for element declarations whose XML representation does not specify one."
13366     */
13367     if ((elemDecl->subtypes == NULL) &&
13368 	(elemDecl->namedType == NULL) &&
13369 	(elemDecl->substGroup == NULL))
13370 	elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
13371 }
13372 
13373 /**
13374  * xmlSchemaResolveUnionMemberTypes:
13375  * @ctxt:  the schema parser context
13376  * @type:  the schema simple type definition
13377  *
13378  * Checks and builds the "member type definitions" property of the union
13379  * simple type. This handles part (1), part (2) is done in
13380  * xmlSchemaFinishMemberTypeDefinitionsProperty()
13381  *
13382  * Returns -1 in case of an internal error, 0 otherwise.
13383  */
13384 static int
xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)13385 xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
13386 				 xmlSchemaTypePtr type)
13387 {
13388 
13389     xmlSchemaTypeLinkPtr link, lastLink, newLink;
13390     xmlSchemaTypePtr memberType;
13391 
13392     /*
13393     * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
13394     * define the explicit members as the type definitions `resolved`
13395     * to by the items in the `actual value` of the memberTypes [attribute],
13396     * if any, followed by the type definitions corresponding to the
13397     * <simpleType>s among the [children] of <union>, if any."
13398     */
13399     /*
13400     * Resolve references.
13401     */
13402     link = type->memberTypes;
13403     lastLink = NULL;
13404     while (link != NULL) {
13405 	const xmlChar *name, *nsName;
13406 
13407 	name = ((xmlSchemaQNameRefPtr) link->type)->name;
13408 	nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
13409 
13410 	memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
13411 	if ((memberType == NULL) || (! WXS_IS_SIMPLE(memberType))) {
13412 	    xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
13413 		WXS_BASIC_CAST type, type->node, "memberTypes",
13414 		name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
13415 	    /*
13416 	    * Remove the member type link.
13417 	    */
13418 	    if (lastLink == NULL)
13419 		type->memberTypes = link->next;
13420 	    else
13421 		lastLink->next = link->next;
13422 	    newLink = link;
13423 	    link = link->next;
13424 	    xmlFree(newLink);
13425 	} else {
13426 	    link->type = memberType;
13427 	    lastLink = link;
13428 	    link = link->next;
13429 	}
13430     }
13431     /*
13432     * Add local simple types,
13433     */
13434     memberType = type->subtypes;
13435     while (memberType != NULL) {
13436 	link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
13437 	if (link == NULL) {
13438 	    xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
13439 	    return (-1);
13440 	}
13441 	link->type = memberType;
13442 	link->next = NULL;
13443 	if (lastLink == NULL)
13444 	    type->memberTypes = link;
13445 	else
13446 	    lastLink->next = link;
13447 	lastLink = link;
13448 	memberType = memberType->next;
13449     }
13450     return (0);
13451 }
13452 
13453 /**
13454  * xmlSchemaIsDerivedFromBuiltInType:
13455  * @ctxt:  the schema parser context
13456  * @type:  the type definition
13457  * @valType: the value type
13458  *
13459  *
13460  * Returns 1 if the type has the given value type, or
13461  * is derived from such a type.
13462  */
13463 static int
xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type,int valType)13464 xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13465 {
13466     if (type == NULL)
13467 	return (0);
13468     if (WXS_IS_COMPLEX(type))
13469 	return (0);
13470     if (type->type == XML_SCHEMA_TYPE_BASIC) {
13471 	if (type->builtInType == valType)
13472 	    return(1);
13473 	if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13474 	    (type->builtInType == XML_SCHEMAS_ANYTYPE))
13475 	    return (0);
13476 	return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13477     }
13478     return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13479 }
13480 
13481 #if 0
13482 /**
13483  * xmlSchemaIsDerivedFromBuiltInType:
13484  * @ctxt:  the schema parser context
13485  * @type:  the type definition
13486  * @valType: the value type
13487  *
13488  *
13489  * Returns 1 if the type has the given value type, or
13490  * is derived from such a type.
13491  */
13492 static int
13493 xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13494 {
13495     if (type == NULL)
13496 	return (0);
13497     if (WXS_IS_COMPLEX(type))
13498 	return (0);
13499     if (type->type == XML_SCHEMA_TYPE_BASIC) {
13500 	if (type->builtInType == valType)
13501 	    return(1);
13502 	return (0);
13503     } else
13504 	return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13505 
13506     return (0);
13507 }
13508 
13509 static xmlSchemaTypePtr
13510 xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
13511 {
13512     if (type == NULL)
13513 	return (NULL);
13514     if (WXS_IS_COMPLEX(type))
13515 	return (NULL);
13516     if (type->type == XML_SCHEMA_TYPE_BASIC)
13517 	return(type);
13518     return(xmlSchemaQueryBuiltInType(type->subtypes));
13519 }
13520 #endif
13521 
13522 /**
13523  * xmlSchemaGetPrimitiveType:
13524  * @type:  the simpleType definition
13525  *
13526  * Returns the primitive type of the given type or
13527  * NULL in case of error.
13528  */
13529 static xmlSchemaTypePtr
xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)13530 xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
13531 {
13532 
13533     while (type != NULL) {
13534 	/*
13535 	* Note that anySimpleType is actually not a primitive type
13536 	* but we need that here.
13537 	*/
13538 	if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13539 	   (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
13540 	    return (type);
13541 	type = type->baseType;
13542     }
13543 
13544     return (NULL);
13545 }
13546 
13547 #if 0
13548 /**
13549  * xmlSchemaGetBuiltInTypeAncestor:
13550  * @type:  the simpleType definition
13551  *
13552  * Returns the primitive type of the given type or
13553  * NULL in case of error.
13554  */
13555 static xmlSchemaTypePtr
13556 xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
13557 {
13558     if (WXS_IS_LIST(type) || WXS_IS_UNION(type))
13559 	return (0);
13560     while (type != NULL) {
13561 	if (type->type == XML_SCHEMA_TYPE_BASIC)
13562 	    return (type);
13563 	type = type->baseType;
13564     }
13565 
13566     return (NULL);
13567 }
13568 #endif
13569 
13570 /**
13571  * xmlSchemaCloneWildcardNsConstraints:
13572  * @ctxt:  the schema parser context
13573  * @dest:  the destination wildcard
13574  * @source: the source wildcard
13575  *
13576  * Clones the namespace constraints of source
13577  * and assigns them to dest.
13578  * Returns -1 on internal error, 0 otherwise.
13579  */
13580 static int
xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,xmlSchemaWildcardPtr dest,xmlSchemaWildcardPtr source)13581 xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
13582 				    xmlSchemaWildcardPtr dest,
13583 				    xmlSchemaWildcardPtr source)
13584 {
13585     xmlSchemaWildcardNsPtr cur, tmp, last;
13586 
13587     if ((source == NULL) || (dest == NULL))
13588 	return(-1);
13589     dest->any = source->any;
13590     cur = source->nsSet;
13591     last = NULL;
13592     while (cur != NULL) {
13593 	tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13594 	if (tmp == NULL)
13595 	    return(-1);
13596 	tmp->value = cur->value;
13597 	if (last == NULL)
13598 	    dest->nsSet = tmp;
13599 	else
13600 	    last->next = tmp;
13601 	last = tmp;
13602 	cur = cur->next;
13603     }
13604     if (dest->negNsSet != NULL)
13605 	xmlSchemaFreeWildcardNsSet(dest->negNsSet);
13606     if (source->negNsSet != NULL) {
13607 	dest->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13608 	if (dest->negNsSet == NULL)
13609 	    return(-1);
13610 	dest->negNsSet->value = source->negNsSet->value;
13611     } else
13612 	dest->negNsSet = NULL;
13613     return(0);
13614 }
13615 
13616 /**
13617  * xmlSchemaUnionWildcards:
13618  * @ctxt:  the schema parser context
13619  * @completeWild:  the first wildcard
13620  * @curWild: the second wildcard
13621  *
13622  * Unions the namespace constraints of the given wildcards.
13623  * @completeWild will hold the resulting union.
13624  * Returns a positive error code on failure, -1 in case of an
13625  * internal error, 0 otherwise.
13626  */
13627 static int
xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,xmlSchemaWildcardPtr completeWild,xmlSchemaWildcardPtr curWild)13628 xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
13629 			    xmlSchemaWildcardPtr completeWild,
13630 			    xmlSchemaWildcardPtr curWild)
13631 {
13632     xmlSchemaWildcardNsPtr cur, curB, tmp;
13633 
13634     /*
13635     * 1 If O1 and O2 are the same value, then that value must be the
13636     * value.
13637     */
13638     if ((completeWild->any == curWild->any) &&
13639 	((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13640 	((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13641 
13642 	if ((completeWild->negNsSet == NULL) ||
13643 	    (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13644 
13645 	    if (completeWild->nsSet != NULL) {
13646 		int found = 0;
13647 
13648 		/*
13649 		* Check equality of sets.
13650 		*/
13651 		cur = completeWild->nsSet;
13652 		while (cur != NULL) {
13653 		    found = 0;
13654 		    curB = curWild->nsSet;
13655 		    while (curB != NULL) {
13656 			if (cur->value == curB->value) {
13657 			    found = 1;
13658 			    break;
13659 			}
13660 			curB = curB->next;
13661 		    }
13662 		    if (!found)
13663 			break;
13664 		    cur = cur->next;
13665 		}
13666 		if (found)
13667 		    return(0);
13668 	    } else
13669 		return(0);
13670 	}
13671     }
13672     /*
13673     * 2 If either O1 or O2 is any, then any must be the value
13674     */
13675     if (completeWild->any != curWild->any) {
13676 	if (completeWild->any == 0) {
13677 	    completeWild->any = 1;
13678 	    if (completeWild->nsSet != NULL) {
13679 		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13680 		completeWild->nsSet = NULL;
13681 	    }
13682 	    if (completeWild->negNsSet != NULL) {
13683 		xmlFree(completeWild->negNsSet);
13684 		completeWild->negNsSet = NULL;
13685 	    }
13686 	}
13687 	return (0);
13688     }
13689     /*
13690     * 3 If both O1 and O2 are sets of (namespace names or `absent`),
13691     * then the union of those sets must be the value.
13692     */
13693     if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13694 	int found;
13695 	xmlSchemaWildcardNsPtr start;
13696 
13697 	cur = curWild->nsSet;
13698 	start = completeWild->nsSet;
13699 	while (cur != NULL) {
13700 	    found = 0;
13701 	    curB = start;
13702 	    while (curB != NULL) {
13703 		if (cur->value == curB->value) {
13704 		    found = 1;
13705 		    break;
13706 		}
13707 		curB = curB->next;
13708 	    }
13709 	    if (!found) {
13710 		tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13711 		if (tmp == NULL)
13712 		    return (-1);
13713 		tmp->value = cur->value;
13714 		tmp->next = completeWild->nsSet;
13715 		completeWild->nsSet = tmp;
13716 	    }
13717 	    cur = cur->next;
13718 	}
13719 
13720 	return(0);
13721     }
13722     /*
13723     * 4 If the two are negations of different values (namespace names
13724     * or `absent`), then a pair of not and `absent` must be the value.
13725     */
13726     if ((completeWild->negNsSet != NULL) &&
13727 	(curWild->negNsSet != NULL) &&
13728 	(completeWild->negNsSet->value != curWild->negNsSet->value)) {
13729 	completeWild->negNsSet->value = NULL;
13730 
13731 	return(0);
13732     }
13733     /*
13734      * 5.
13735      */
13736     if (((completeWild->negNsSet != NULL) &&
13737 	(completeWild->negNsSet->value != NULL) &&
13738 	(curWild->nsSet != NULL)) ||
13739 	((curWild->negNsSet != NULL) &&
13740 	(curWild->negNsSet->value != NULL) &&
13741 	(completeWild->nsSet != NULL))) {
13742 
13743 	int nsFound, absentFound = 0;
13744 
13745 	if (completeWild->nsSet != NULL) {
13746 	    cur = completeWild->nsSet;
13747 	    curB = curWild->negNsSet;
13748 	} else {
13749 	    cur = curWild->nsSet;
13750 	    curB = completeWild->negNsSet;
13751 	}
13752 	nsFound = 0;
13753 	while (cur != NULL) {
13754 	    if (cur->value == NULL)
13755 		absentFound = 1;
13756 	    else if (cur->value == curB->value)
13757 		nsFound = 1;
13758 	    if (nsFound && absentFound)
13759 		break;
13760 	    cur = cur->next;
13761 	}
13762 
13763 	if (nsFound && absentFound) {
13764 	    /*
13765 	    * 5.1 If the set S includes both the negated namespace
13766 	    * name and `absent`, then any must be the value.
13767 	    */
13768 	    completeWild->any = 1;
13769 	    if (completeWild->nsSet != NULL) {
13770 		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13771 		completeWild->nsSet = NULL;
13772 	    }
13773 	    if (completeWild->negNsSet != NULL) {
13774 		xmlFree(completeWild->negNsSet);
13775 		completeWild->negNsSet = NULL;
13776 	    }
13777 	} else if (nsFound && (!absentFound)) {
13778 	    /*
13779 	    * 5.2 If the set S includes the negated namespace name
13780 	    * but not `absent`, then a pair of not and `absent` must
13781 	    * be the value.
13782 	    */
13783 	    if (completeWild->nsSet != NULL) {
13784 		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13785 		completeWild->nsSet = NULL;
13786 	    }
13787 	    if (completeWild->negNsSet == NULL) {
13788 		completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13789 		if (completeWild->negNsSet == NULL)
13790 		    return (-1);
13791 	    }
13792 	    completeWild->negNsSet->value = NULL;
13793 	} else if ((!nsFound) && absentFound) {
13794 	    /*
13795 	    * 5.3 If the set S includes `absent` but not the negated
13796 	    * namespace name, then the union is not expressible.
13797 	    */
13798 	    xmlSchemaPErr(ctxt, completeWild->node,
13799 		XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
13800 		"The union of the wildcard is not expressible.\n",
13801 		NULL, NULL);
13802 	    return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
13803 	} else if ((!nsFound) && (!absentFound)) {
13804 	    /*
13805 	    * 5.4 If the set S does not include either the negated namespace
13806 	    * name or `absent`, then whichever of O1 or O2 is a pair of not
13807 	    * and a namespace name must be the value.
13808 	    */
13809 	    if (completeWild->negNsSet == NULL) {
13810 		if (completeWild->nsSet != NULL) {
13811 		    xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13812 		    completeWild->nsSet = NULL;
13813 		}
13814 		completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13815 		if (completeWild->negNsSet == NULL)
13816 		    return (-1);
13817 		completeWild->negNsSet->value = curWild->negNsSet->value;
13818 	    }
13819 	}
13820 	return (0);
13821     }
13822     /*
13823      * 6.
13824      */
13825     if (((completeWild->negNsSet != NULL) &&
13826 	(completeWild->negNsSet->value == NULL) &&
13827 	(curWild->nsSet != NULL)) ||
13828 	((curWild->negNsSet != NULL) &&
13829 	(curWild->negNsSet->value == NULL) &&
13830 	(completeWild->nsSet != NULL))) {
13831 
13832 	if (completeWild->nsSet != NULL) {
13833 	    cur = completeWild->nsSet;
13834 	} else {
13835 	    cur = curWild->nsSet;
13836 	}
13837 	while (cur != NULL) {
13838 	    if (cur->value == NULL) {
13839 		/*
13840 		* 6.1 If the set S includes `absent`, then any must be the
13841 		* value.
13842 		*/
13843 		completeWild->any = 1;
13844 		if (completeWild->nsSet != NULL) {
13845 		    xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13846 		    completeWild->nsSet = NULL;
13847 		}
13848 		if (completeWild->negNsSet != NULL) {
13849 		    xmlFree(completeWild->negNsSet);
13850 		    completeWild->negNsSet = NULL;
13851 		}
13852 		return (0);
13853 	    }
13854 	    cur = cur->next;
13855 	}
13856 	if (completeWild->negNsSet == NULL) {
13857 	    /*
13858 	    * 6.2 If the set S does not include `absent`, then a pair of not
13859 	    * and `absent` must be the value.
13860 	    */
13861 	    if (completeWild->nsSet != NULL) {
13862 		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13863 		completeWild->nsSet = NULL;
13864 	    }
13865 	    completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13866 	    if (completeWild->negNsSet == NULL)
13867 		return (-1);
13868 	    completeWild->negNsSet->value = NULL;
13869 	}
13870 	return (0);
13871     }
13872     return (0);
13873 
13874 }
13875 
13876 /**
13877  * xmlSchemaIntersectWildcards:
13878  * @ctxt:  the schema parser context
13879  * @completeWild:  the first wildcard
13880  * @curWild: the second wildcard
13881  *
13882  * Intersects the namespace constraints of the given wildcards.
13883  * @completeWild will hold the resulting intersection.
13884  * Returns a positive error code on failure, -1 in case of an
13885  * internal error, 0 otherwise.
13886  */
13887 static int
xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,xmlSchemaWildcardPtr completeWild,xmlSchemaWildcardPtr curWild)13888 xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
13889 			    xmlSchemaWildcardPtr completeWild,
13890 			    xmlSchemaWildcardPtr curWild)
13891 {
13892     xmlSchemaWildcardNsPtr cur, curB, prev,  tmp;
13893 
13894     /*
13895     * 1 If O1 and O2 are the same value, then that value must be the
13896     * value.
13897     */
13898     if ((completeWild->any == curWild->any) &&
13899 	((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13900 	((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13901 
13902 	if ((completeWild->negNsSet == NULL) ||
13903 	    (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13904 
13905 	    if (completeWild->nsSet != NULL) {
13906 		int found = 0;
13907 
13908 		/*
13909 		* Check equality of sets.
13910 		*/
13911 		cur = completeWild->nsSet;
13912 		while (cur != NULL) {
13913 		    found = 0;
13914 		    curB = curWild->nsSet;
13915 		    while (curB != NULL) {
13916 			if (cur->value == curB->value) {
13917 			    found = 1;
13918 			    break;
13919 			}
13920 			curB = curB->next;
13921 		    }
13922 		    if (!found)
13923 			break;
13924 		    cur = cur->next;
13925 		}
13926 		if (found)
13927 		    return(0);
13928 	    } else
13929 		return(0);
13930 	}
13931     }
13932     /*
13933     * 2 If either O1 or O2 is any, then the other must be the value.
13934     */
13935     if ((completeWild->any != curWild->any) && (completeWild->any)) {
13936 	if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13937 	    return(-1);
13938 	return(0);
13939     }
13940     /*
13941     * 3 If either O1 or O2 is a pair of not and a value (a namespace
13942     * name or `absent`) and the other is a set of (namespace names or
13943     * `absent`), then that set, minus the negated value if it was in
13944     * the set, minus `absent` if it was in the set, must be the value.
13945     */
13946     if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
13947 	((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
13948 	const xmlChar *neg;
13949 
13950 	if (completeWild->nsSet == NULL) {
13951 	    neg = completeWild->negNsSet->value;
13952 	    if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13953 		return(-1);
13954 	} else
13955 	    neg = curWild->negNsSet->value;
13956 	/*
13957 	* Remove absent and negated.
13958 	*/
13959 	prev = NULL;
13960 	cur = completeWild->nsSet;
13961 	while (cur != NULL) {
13962 	    if (cur->value == NULL) {
13963 		if (prev == NULL)
13964 		    completeWild->nsSet = cur->next;
13965 		else
13966 		    prev->next = cur->next;
13967 		xmlFree(cur);
13968 		break;
13969 	    }
13970 	    prev = cur;
13971 	    cur = cur->next;
13972 	}
13973 	if (neg != NULL) {
13974 	    prev = NULL;
13975 	    cur = completeWild->nsSet;
13976 	    while (cur != NULL) {
13977 		if (cur->value == neg) {
13978 		    if (prev == NULL)
13979 			completeWild->nsSet = cur->next;
13980 		    else
13981 			prev->next = cur->next;
13982 		    xmlFree(cur);
13983 		    break;
13984 		}
13985 		prev = cur;
13986 		cur = cur->next;
13987 	    }
13988 	}
13989 
13990 	return(0);
13991     }
13992     /*
13993     * 4 If both O1 and O2 are sets of (namespace names or `absent`),
13994     * then the intersection of those sets must be the value.
13995     */
13996     if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13997 	int found;
13998 
13999 	cur = completeWild->nsSet;
14000 	prev = NULL;
14001 	while (cur != NULL) {
14002 	    found = 0;
14003 	    curB = curWild->nsSet;
14004 	    while (curB != NULL) {
14005 		if (cur->value == curB->value) {
14006 		    found = 1;
14007 		    break;
14008 		}
14009 		curB = curB->next;
14010 	    }
14011 	    if (!found) {
14012 		if (prev == NULL)
14013 		    completeWild->nsSet = cur->next;
14014 		else
14015 		    prev->next = cur->next;
14016 		tmp = cur->next;
14017 		xmlFree(cur);
14018 		cur = tmp;
14019 		continue;
14020 	    }
14021 	    prev = cur;
14022 	    cur = cur->next;
14023 	}
14024 
14025 	return(0);
14026     }
14027     /* 5 If the two are negations of different namespace names,
14028     * then the intersection is not expressible
14029     */
14030     if ((completeWild->negNsSet != NULL) &&
14031 	(curWild->negNsSet != NULL) &&
14032 	(completeWild->negNsSet->value != curWild->negNsSet->value) &&
14033 	(completeWild->negNsSet->value != NULL) &&
14034 	(curWild->negNsSet->value != NULL)) {
14035 
14036 	xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
14037 	    "The intersection of the wildcard is not expressible.\n",
14038 	    NULL, NULL);
14039 	return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
14040     }
14041     /*
14042     * 6 If the one is a negation of a namespace name and the other
14043     * is a negation of `absent`, then the one which is the negation
14044     * of a namespace name must be the value.
14045     */
14046     if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
14047 	(completeWild->negNsSet->value != curWild->negNsSet->value) &&
14048 	(completeWild->negNsSet->value == NULL)) {
14049 	completeWild->negNsSet->value =  curWild->negNsSet->value;
14050     }
14051     return(0);
14052 }
14053 
14054 /**
14055  * xmlSchemaIsWildcardNsConstraintSubset:
14056  * @ctxt:  the schema parser context
14057  * @sub:  the first wildcard
14058  * @super: the second wildcard
14059  *
14060  * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
14061  *
14062  * Returns 0 if the namespace constraint of @sub is an intensional
14063  * subset of @super, 1 otherwise.
14064  */
14065 static int
xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,xmlSchemaWildcardPtr super)14066 xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
14067 			  xmlSchemaWildcardPtr super)
14068 {
14069     /*
14070     * 1 super must be any.
14071     */
14072     if (super->any)
14073 	return (0);
14074     /*
14075     * 2.1 sub must be a pair of not and a namespace name or `absent`.
14076     * 2.2 super must be a pair of not and the same value.
14077     */
14078     if ((sub->negNsSet != NULL) &&
14079 	(super->negNsSet != NULL) &&
14080 	(sub->negNsSet->value == super->negNsSet->value))
14081 	return (0);
14082     /*
14083     * 3.1 sub must be a set whose members are either namespace names or `absent`.
14084     */
14085     if (sub->nsSet != NULL) {
14086 	/*
14087 	* 3.2.1 super must be the same set or a superset thereof.
14088 	*/
14089 	if (super->nsSet != NULL) {
14090 	    xmlSchemaWildcardNsPtr cur, curB;
14091 	    int found = 0;
14092 
14093 	    cur = sub->nsSet;
14094 	    while (cur != NULL) {
14095 		found = 0;
14096 		curB = super->nsSet;
14097 		while (curB != NULL) {
14098 		    if (cur->value == curB->value) {
14099 			found = 1;
14100 			break;
14101 		    }
14102 		    curB = curB->next;
14103 		}
14104 		if (!found)
14105 		    return (1);
14106 		cur = cur->next;
14107 	    }
14108 	    if (found)
14109 		return (0);
14110 	} else if (super->negNsSet != NULL) {
14111 	    xmlSchemaWildcardNsPtr cur;
14112 	    /*
14113 	    * 3.2.2 super must be a pair of not and a namespace name or
14114 	    * `absent` and that value must not be in sub's set.
14115 	    */
14116 	    cur = sub->nsSet;
14117 	    while (cur != NULL) {
14118 		if (cur->value == super->negNsSet->value)
14119 		    return (1);
14120 		cur = cur->next;
14121 	    }
14122 	    return (0);
14123 	}
14124     }
14125     return (1);
14126 }
14127 
14128 static int
xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse,int * fixed,const xmlChar ** value,xmlSchemaValPtr * val)14129 xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse,
14130 				     int *fixed,
14131 				     const xmlChar **value,
14132 				     xmlSchemaValPtr *val)
14133 {
14134     *fixed = 0;
14135     *value = NULL;
14136     if (val != 0)
14137 	*val = NULL;
14138 
14139     if (attruse->defValue != NULL) {
14140 	*value = attruse->defValue;
14141 	if (val != NULL)
14142 	    *val = attruse->defVal;
14143 	if (attruse->flags & XML_SCHEMA_ATTR_USE_FIXED)
14144 	    *fixed = 1;
14145 	return(1);
14146     } else if ((attruse->attrDecl != NULL) &&
14147 	(attruse->attrDecl->defValue != NULL)) {
14148 	*value = attruse->attrDecl->defValue;
14149 	if (val != NULL)
14150 	    *val = attruse->attrDecl->defVal;
14151 	if (attruse->attrDecl->flags & XML_SCHEMAS_ATTR_FIXED)
14152 	    *fixed = 1;
14153 	return(1);
14154     }
14155     return(0);
14156 }
14157 /**
14158  * xmlSchemaCheckCVCWildcardNamespace:
14159  * @wild:  the wildcard
14160  * @ns:  the namespace
14161  *
14162  * Validation Rule: Wildcard allows Namespace Name
14163  * (cvc-wildcard-namespace)
14164  *
14165  * Returns 0 if the given namespace matches the wildcard,
14166  * 1 otherwise and -1 on API errors.
14167  */
14168 static int
xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,const xmlChar * ns)14169 xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
14170 				   const xmlChar* ns)
14171 {
14172     if (wild == NULL)
14173 	return(-1);
14174 
14175     if (wild->any)
14176 	return(0);
14177     else if (wild->nsSet != NULL) {
14178 	xmlSchemaWildcardNsPtr cur;
14179 
14180 	cur = wild->nsSet;
14181 	while (cur != NULL) {
14182 	    if (xmlStrEqual(cur->value, ns))
14183 		return(0);
14184 	    cur = cur->next;
14185 	}
14186     } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
14187 	(!xmlStrEqual(wild->negNsSet->value, ns)))
14188 	return(0);
14189 
14190     return(1);
14191 }
14192 
14193 #define XML_SCHEMA_ACTION_DERIVE 0
14194 #define XML_SCHEMA_ACTION_REDEFINE 1
14195 
14196 #define WXS_ACTION_STR(a) \
14197 ((a) == XML_SCHEMA_ACTION_DERIVE) ? (const xmlChar *) "base" : (const xmlChar *) "redefined"
14198 
14199 /*
14200 * Schema Component Constraint:
14201 *   Derivation Valid (Restriction, Complex)
14202 *   derivation-ok-restriction (2) - (4)
14203 *
14204 * ATTENTION:
14205 * In XML Schema 1.1 this will be:
14206 * Validation Rule:
14207 *     Checking complex type subsumption (practicalSubsumption) (1, 2 and 3)
14208 *
14209 */
14210 static int
xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt,int action,xmlSchemaBasicItemPtr item,xmlSchemaBasicItemPtr baseItem,xmlSchemaItemListPtr uses,xmlSchemaItemListPtr baseUses,xmlSchemaWildcardPtr wild,xmlSchemaWildcardPtr baseWild)14211 xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt,
14212 				       int action,
14213 				       xmlSchemaBasicItemPtr item,
14214 				       xmlSchemaBasicItemPtr baseItem,
14215 				       xmlSchemaItemListPtr uses,
14216 				       xmlSchemaItemListPtr baseUses,
14217 				       xmlSchemaWildcardPtr wild,
14218 				       xmlSchemaWildcardPtr baseWild)
14219 {
14220     xmlSchemaAttributeUsePtr cur = NULL, bcur;
14221     int i, j, found; /* err = 0; */
14222     const xmlChar *bEffValue;
14223     int effFixed;
14224 
14225     if (uses != NULL) {
14226 	for (i = 0; i < uses->nbItems; i++) {
14227 	    cur = uses->items[i];
14228 	    found = 0;
14229 	    if (baseUses == NULL)
14230 		goto not_found;
14231 	    for (j = 0; j < baseUses->nbItems; j++) {
14232 		bcur = baseUses->items[j];
14233 		if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14234 			WXS_ATTRUSE_DECL_NAME(bcur)) &&
14235 		    (WXS_ATTRUSE_DECL_TNS(cur) ==
14236 			WXS_ATTRUSE_DECL_TNS(bcur)))
14237 		{
14238 		    /*
14239 		    * (2.1) "If there is an attribute use in the {attribute
14240 		    * uses} of the {base type definition} (call this B) whose
14241 		    * {attribute declaration} has the same {name} and {target
14242 		    * namespace}, then  all of the following must be true:"
14243 		    */
14244 		    found = 1;
14245 
14246 		    if ((cur->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
14247 			(bcur->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED))
14248 		    {
14249 			xmlChar *str = NULL;
14250 			/*
14251 			* (2.1.1) "one of the following must be true:"
14252 			* (2.1.1.1) "B's {required} is false."
14253 			* (2.1.1.2) "R's {required} is true."
14254 			*/
14255 			xmlSchemaPAttrUseErr4(pctxt,
14256 			    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
14257 			    WXS_ITEM_NODE(item), item, cur,
14258 			    "The 'optional' attribute use is inconsistent "
14259 			    "with the corresponding 'required' attribute use of "
14260 			    "the %s %s",
14261 			    WXS_ACTION_STR(action),
14262 			    xmlSchemaGetComponentDesignation(&str, baseItem),
14263 			    NULL, NULL);
14264 			FREE_AND_NULL(str);
14265 			/* err = pctxt->err; */
14266 		    } else if (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
14267 			WXS_ATTRUSE_TYPEDEF(cur),
14268 			WXS_ATTRUSE_TYPEDEF(bcur), 0) != 0)
14269 		    {
14270 			xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
14271 
14272 			/*
14273 			* SPEC (2.1.2) "R's {attribute declaration}'s
14274 			* {type definition} must be validly derived from
14275 			* B's {type definition} given the empty set as
14276 			* defined in Type Derivation OK (Simple) ($3.14.6)."
14277 			*/
14278 			xmlSchemaPAttrUseErr4(pctxt,
14279 			    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
14280 			    WXS_ITEM_NODE(item), item, cur,
14281 			    "The attribute declaration's %s "
14282 			    "is not validly derived from "
14283 			    "the corresponding %s of the "
14284 			    "attribute declaration in the %s %s",
14285 			    xmlSchemaGetComponentDesignation(&strA,
14286 				WXS_ATTRUSE_TYPEDEF(cur)),
14287 			    xmlSchemaGetComponentDesignation(&strB,
14288 				WXS_ATTRUSE_TYPEDEF(bcur)),
14289 			    WXS_ACTION_STR(action),
14290 			    xmlSchemaGetComponentDesignation(&strC, baseItem));
14291 			    /* xmlSchemaGetComponentDesignation(&str, baseItem), */
14292 			FREE_AND_NULL(strA);
14293 			FREE_AND_NULL(strB);
14294 			FREE_AND_NULL(strC);
14295 			/* err = pctxt->err; */
14296 		    } else {
14297 			/*
14298 			* 2.1.3 [Definition:]  Let the effective value
14299 			* constraint of an attribute use be its {value
14300 			* constraint}, if present, otherwise its {attribute
14301 			* declaration}'s {value constraint} .
14302 			*/
14303 			xmlSchemaGetEffectiveValueConstraint(bcur,
14304 			    &effFixed, &bEffValue, NULL);
14305 			/*
14306 			* 2.1.3 ... one of the following must be true
14307 			*
14308 			* 2.1.3.1 B's `effective value constraint` is
14309 			* `absent` or default.
14310 			*/
14311 			if ((bEffValue != NULL) &&
14312 			    (effFixed == 1)) {
14313 			    const xmlChar *rEffValue = NULL;
14314 
14315 			    xmlSchemaGetEffectiveValueConstraint(bcur,
14316 				&effFixed, &rEffValue, NULL);
14317 			    /*
14318 			    * 2.1.3.2 R's `effective value constraint` is
14319 			    * fixed with the same string as B's.
14320 			    * MAYBE TODO: Compare the computed values.
14321 			    *       Hmm, it says "same string" so
14322 			    *       string-equality might really be sufficient.
14323 			    */
14324 			    if ((effFixed == 0) ||
14325 				(! WXS_ARE_DEFAULT_STR_EQUAL(rEffValue, bEffValue)))
14326 			    {
14327 				xmlChar *str = NULL;
14328 
14329 				xmlSchemaPAttrUseErr4(pctxt,
14330 				    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
14331 				    WXS_ITEM_NODE(item), item, cur,
14332 				    "The effective value constraint of the "
14333 				    "attribute use is inconsistent with "
14334 				    "its correspondent in the %s %s",
14335 				    WXS_ACTION_STR(action),
14336 				    xmlSchemaGetComponentDesignation(&str,
14337 					baseItem),
14338 				    NULL, NULL);
14339 				FREE_AND_NULL(str);
14340 				/* err = pctxt->err; */
14341 			    }
14342 			}
14343 		    }
14344 		    break;
14345 		}
14346 	    }
14347 not_found:
14348 	    if (!found) {
14349 		/*
14350 		* (2.2) "otherwise the {base type definition} must have an
14351 		* {attribute wildcard} and the {target namespace} of the
14352 		* R's {attribute declaration} must be `valid` with respect
14353 		* to that wildcard, as defined in Wildcard allows Namespace
14354 		* Name ($3.10.4)."
14355 		*/
14356 		if ((baseWild == NULL) ||
14357 		    (xmlSchemaCheckCVCWildcardNamespace(baseWild,
14358 		    (WXS_ATTRUSE_DECL(cur))->targetNamespace) != 0))
14359 		{
14360 		    xmlChar *str = NULL;
14361 
14362 		    xmlSchemaPAttrUseErr4(pctxt,
14363 			XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
14364 			WXS_ITEM_NODE(item), item, cur,
14365 			"Neither a matching attribute use, "
14366 			"nor a matching wildcard exists in the %s %s",
14367 			WXS_ACTION_STR(action),
14368 			xmlSchemaGetComponentDesignation(&str, baseItem),
14369 			NULL, NULL);
14370 		    FREE_AND_NULL(str);
14371 		    /* err = pctxt->err; */
14372 		}
14373 	    }
14374 	}
14375     }
14376     /*
14377     * SPEC derivation-ok-restriction (3):
14378     * (3) "For each attribute use in the {attribute uses} of the {base type
14379     * definition} whose {required} is true, there must be an attribute
14380     * use with an {attribute declaration} with the same {name} and
14381     * {target namespace} as its {attribute declaration} in the {attribute
14382     * uses} of the complex type definition itself whose {required} is true.
14383     */
14384     if (baseUses != NULL) {
14385 	for (j = 0; j < baseUses->nbItems; j++) {
14386 	    bcur = baseUses->items[j];
14387 	    if (bcur->occurs != XML_SCHEMAS_ATTR_USE_REQUIRED)
14388 		continue;
14389 	    found = 0;
14390 	    if (uses != NULL) {
14391 		for (i = 0; i < uses->nbItems; i++) {
14392 		    cur = uses->items[i];
14393 		    if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14394 			WXS_ATTRUSE_DECL_NAME(bcur)) &&
14395 			(WXS_ATTRUSE_DECL_TNS(cur) ==
14396 			WXS_ATTRUSE_DECL_TNS(bcur))) {
14397 			found = 1;
14398 			break;
14399 		    }
14400 		}
14401 	    }
14402 	    if (!found) {
14403 		xmlChar *strA = NULL, *strB = NULL;
14404 
14405 		xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14406 		    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
14407 		    NULL, item,
14408 		    "A matching attribute use for the "
14409 		    "'required' %s of the %s %s is missing",
14410 		    xmlSchemaGetComponentDesignation(&strA, bcur),
14411 		    WXS_ACTION_STR(action),
14412 		    xmlSchemaGetComponentDesignation(&strB, baseItem),
14413 		    NULL);
14414 		FREE_AND_NULL(strA);
14415 		FREE_AND_NULL(strB);
14416 	    }
14417 	}
14418     }
14419     /*
14420     * derivation-ok-restriction (4)
14421     */
14422     if (wild != NULL) {
14423 	/*
14424 	* (4) "If there is an {attribute wildcard}, all of the
14425 	* following must be true:"
14426 	*/
14427 	if (baseWild == NULL) {
14428 	    xmlChar *str = NULL;
14429 
14430 	    /*
14431 	    * (4.1) "The {base type definition} must also have one."
14432 	    */
14433 	    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14434 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
14435 		NULL, item,
14436 		"The %s has an attribute wildcard, "
14437 		"but the %s %s '%s' does not have one",
14438 		WXS_ITEM_TYPE_NAME(item),
14439 		WXS_ACTION_STR(action),
14440 		WXS_ITEM_TYPE_NAME(baseItem),
14441 		xmlSchemaGetComponentQName(&str, baseItem));
14442 	    FREE_AND_NULL(str);
14443 	    return(pctxt->err);
14444 	} else if ((baseWild->any == 0) &&
14445 		xmlSchemaCheckCOSNSSubset(wild, baseWild))
14446 	{
14447 	    xmlChar *str = NULL;
14448 	    /*
14449 	    * (4.2) "The complex type definition's {attribute wildcard}'s
14450 	    * {namespace constraint} must be a subset of the {base type
14451 	    * definition}'s {attribute wildcard}'s {namespace constraint},
14452 	    * as defined by Wildcard Subset ($3.10.6)."
14453 	    */
14454 	    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14455 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
14456 		NULL, item,
14457 		"The attribute wildcard is not a valid "
14458 		"subset of the wildcard in the %s %s '%s'",
14459 		WXS_ACTION_STR(action),
14460 		WXS_ITEM_TYPE_NAME(baseItem),
14461 		xmlSchemaGetComponentQName(&str, baseItem),
14462 		NULL);
14463 	    FREE_AND_NULL(str);
14464 	    return(pctxt->err);
14465 	}
14466 	/* 4.3 Unless the {base type definition} is the `ur-type
14467 	* definition`, the complex type definition's {attribute
14468 	* wildcard}'s {process contents} must be identical to or
14469 	* stronger than the {base type definition}'s {attribute
14470 	* wildcard}'s {process contents}, where strict is stronger
14471 	* than lax is stronger than skip.
14472 	*/
14473 	if ((! WXS_IS_ANYTYPE(baseItem)) &&
14474 	    (wild->processContents < baseWild->processContents)) {
14475 	    xmlChar *str = NULL;
14476 	    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14477 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
14478 		NULL, baseItem,
14479 		"The {process contents} of the attribute wildcard is "
14480 		"weaker than the one in the %s %s '%s'",
14481 		WXS_ACTION_STR(action),
14482 		WXS_ITEM_TYPE_NAME(baseItem),
14483 		xmlSchemaGetComponentQName(&str, baseItem),
14484 		NULL);
14485 	    FREE_AND_NULL(str)
14486 		return(pctxt->err);
14487 	}
14488     }
14489     return(0);
14490 }
14491 
14492 
14493 static int
14494 xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
14495 				  xmlSchemaBasicItemPtr item,
14496 				  xmlSchemaWildcardPtr *completeWild,
14497 				  xmlSchemaItemListPtr list,
14498 				  xmlSchemaItemListPtr prohibs);
14499 /**
14500  * xmlSchemaFixupTypeAttributeUses:
14501  * @ctxt:  the schema parser context
14502  * @type:  the complex type definition
14503  *
14504  *
14505  * Builds the wildcard and the attribute uses on the given complex type.
14506  * Returns -1 if an internal error occurs, 0 otherwise.
14507  *
14508  * ATTENTION TODO: Experimentally this uses pointer comparisons for
14509  * strings, so recheck this if we start to hardcode some schemata, since
14510  * they might not be in the same dict.
14511  * NOTE: It is allowed to "extend" the xs:anyType type.
14512  */
14513 static int
xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)14514 xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt,
14515 				  xmlSchemaTypePtr type)
14516 {
14517     xmlSchemaTypePtr baseType = NULL;
14518     xmlSchemaAttributeUsePtr use;
14519     xmlSchemaItemListPtr uses, baseUses, prohibs = NULL;
14520 
14521     if (type->baseType == NULL) {
14522 	PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14523 	    "no base type");
14524         return (-1);
14525     }
14526     baseType = type->baseType;
14527     if (WXS_IS_TYPE_NOT_FIXED(baseType))
14528 	if (xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt) == -1)
14529 	    return(-1);
14530 
14531     uses = type->attrUses;
14532     baseUses = baseType->attrUses;
14533     /*
14534     * Expand attribute group references. And build the 'complete'
14535     * wildcard, i.e. intersect multiple wildcards.
14536     * Move attribute prohibitions into a separate list.
14537     */
14538     if (uses != NULL) {
14539 	if (WXS_IS_RESTRICTION(type)) {
14540 	    /*
14541 	    * This one will transfer all attr. prohibitions
14542 	    * into pctxt->attrProhibs.
14543 	    */
14544 	    if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14545 		WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14546 		pctxt->attrProhibs) == -1)
14547 	    {
14548 		PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14549 		"failed to expand attributes");
14550 	    }
14551 	    if (pctxt->attrProhibs->nbItems != 0)
14552 		prohibs = pctxt->attrProhibs;
14553 	} else {
14554 	    if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14555 		WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14556 		NULL) == -1)
14557 	    {
14558 		PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14559 		"failed to expand attributes");
14560 	    }
14561 	}
14562     }
14563     /*
14564     * Inherit the attribute uses of the base type.
14565     */
14566     if (baseUses != NULL) {
14567 	int i, j;
14568 	xmlSchemaAttributeUseProhibPtr pro;
14569 
14570 	if (WXS_IS_RESTRICTION(type)) {
14571 	    int usesCount;
14572 	    xmlSchemaAttributeUsePtr tmp;
14573 
14574 	    if (uses != NULL)
14575 		usesCount = uses->nbItems;
14576 	    else
14577 		usesCount = 0;
14578 
14579 	    /* Restriction. */
14580 	    for (i = 0; i < baseUses->nbItems; i++) {
14581 		use = baseUses->items[i];
14582 		if (prohibs) {
14583 		    /*
14584 		    * Filter out prohibited uses.
14585 		    */
14586 		    for (j = 0; j < prohibs->nbItems; j++) {
14587 			pro = prohibs->items[j];
14588 			if ((WXS_ATTRUSE_DECL_NAME(use) == pro->name) &&
14589 			    (WXS_ATTRUSE_DECL_TNS(use) ==
14590 				pro->targetNamespace))
14591 			{
14592 			    goto inherit_next;
14593 			}
14594 		    }
14595 		}
14596 		if (usesCount) {
14597 		    /*
14598 		    * Filter out existing uses.
14599 		    */
14600 		    for (j = 0; j < usesCount; j++) {
14601 			tmp = uses->items[j];
14602 			if ((WXS_ATTRUSE_DECL_NAME(use) ==
14603 				WXS_ATTRUSE_DECL_NAME(tmp)) &&
14604 			    (WXS_ATTRUSE_DECL_TNS(use) ==
14605 				WXS_ATTRUSE_DECL_TNS(tmp)))
14606 			{
14607 			    goto inherit_next;
14608 			}
14609 		    }
14610 		}
14611 		if (uses == NULL) {
14612 		    type->attrUses = xmlSchemaItemListCreate();
14613 		    if (type->attrUses == NULL)
14614 			goto exit_failure;
14615 		    uses = type->attrUses;
14616 		}
14617 		xmlSchemaItemListAddSize(uses, 2, use);
14618 inherit_next: {}
14619 	    }
14620 	} else {
14621 	    /* Extension. */
14622 	    for (i = 0; i < baseUses->nbItems; i++) {
14623 		use = baseUses->items[i];
14624 		if (uses == NULL) {
14625 		    type->attrUses = xmlSchemaItemListCreate();
14626 		    if (type->attrUses == NULL)
14627 			goto exit_failure;
14628 		    uses = type->attrUses;
14629 		}
14630 		xmlSchemaItemListAddSize(uses, baseUses->nbItems, use);
14631 	    }
14632 	}
14633     }
14634     /*
14635     * Shrink attr. uses.
14636     */
14637     if (uses) {
14638 	if (uses->nbItems == 0) {
14639 	    xmlSchemaItemListFree(uses);
14640 	    type->attrUses = NULL;
14641 	}
14642 	/*
14643 	* TODO: We could shrink the size of the array
14644 	* to fit the actual number of items.
14645 	*/
14646     }
14647     /*
14648     * Compute the complete wildcard.
14649     */
14650     if (WXS_IS_EXTENSION(type)) {
14651 	if (baseType->attributeWildcard != NULL) {
14652 	    /*
14653 	    * (3.2.2.1) "If the `base wildcard` is non-`absent`, then
14654 	    * the appropriate case among the following:"
14655 	    */
14656 	    if (type->attributeWildcard != NULL) {
14657 		/*
14658 		* Union the complete wildcard with the base wildcard.
14659 		* SPEC {attribute wildcard}
14660 		* (3.2.2.1.2) "otherwise a wildcard whose {process contents}
14661 		* and {annotation} are those of the `complete wildcard`,
14662 		* and whose {namespace constraint} is the intensional union
14663 		* of the {namespace constraint} of the `complete wildcard`
14664 		* and of the `base wildcard`, as defined in Attribute
14665 		* Wildcard Union ($3.10.6)."
14666 		*/
14667 		if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
14668 		    baseType->attributeWildcard) == -1)
14669 		    goto exit_failure;
14670 	    } else {
14671 		/*
14672 		* (3.2.2.1.1) "If the `complete wildcard` is `absent`,
14673 		* then the `base wildcard`."
14674 		*/
14675 		type->attributeWildcard = baseType->attributeWildcard;
14676 	    }
14677 	} else {
14678 	    /*
14679 	    * (3.2.2.2) "otherwise (the `base wildcard` is `absent`) the
14680 	    * `complete wildcard`"
14681 	    * NOOP
14682 	    */
14683 	}
14684     } else {
14685 	/*
14686 	* SPEC {attribute wildcard}
14687 	* (3.1) "If the <restriction> alternative is chosen, then the
14688 	* `complete wildcard`;"
14689 	* NOOP
14690 	*/
14691     }
14692 
14693     return (0);
14694 
14695 exit_failure:
14696     return(-1);
14697 }
14698 
14699 /**
14700  * xmlSchemaTypeFinalContains:
14701  * @schema:  the schema
14702  * @type:  the type definition
14703  * @final: the final
14704  *
14705  * Evaluates if a type definition contains the given "final".
14706  * This does take "finalDefault" into account as well.
14707  *
14708  * Returns 1 if the type does contain the given "final",
14709  * 0 otherwise.
14710  */
14711 static int
xmlSchemaTypeFinalContains(xmlSchemaTypePtr type,int final)14712 xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
14713 {
14714     if (type == NULL)
14715 	return (0);
14716     if (type->flags & final)
14717 	return (1);
14718     else
14719 	return (0);
14720 }
14721 
14722 /**
14723  * xmlSchemaGetUnionSimpleTypeMemberTypes:
14724  * @type:  the Union Simple Type
14725  *
14726  * Returns a list of member types of @type if existing,
14727  * returns NULL otherwise.
14728  */
14729 static xmlSchemaTypeLinkPtr
xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)14730 xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
14731 {
14732     while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
14733 	if (type->memberTypes != NULL)
14734 	    return (type->memberTypes);
14735 	else
14736 	    type = type->baseType;
14737     }
14738     return (NULL);
14739 }
14740 
14741 #if 0
14742 /**
14743  * xmlSchemaGetParticleTotalRangeMin:
14744  * @particle: the particle
14745  *
14746  * Schema Component Constraint: Effective Total Range
14747  * (all and sequence) + (choice)
14748  *
14749  * Returns the minimum Effective Total Range.
14750  */
14751 static int
14752 xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
14753 {
14754     if ((particle->children == NULL) ||
14755 	(particle->minOccurs == 0))
14756 	return (0);
14757     if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14758 	int min = -1, cur;
14759 	xmlSchemaParticlePtr part =
14760 	    (xmlSchemaParticlePtr) particle->children->children;
14761 
14762 	if (part == NULL)
14763 	    return (0);
14764 	while (part != NULL) {
14765 	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14766 		(part->children->type == XML_SCHEMA_TYPE_ANY))
14767 		cur = part->minOccurs;
14768 	    else
14769 		cur = xmlSchemaGetParticleTotalRangeMin(part);
14770 	    if (cur == 0)
14771 		return (0);
14772 	    if ((min > cur) || (min == -1))
14773 		min = cur;
14774 	    part = (xmlSchemaParticlePtr) part->next;
14775 	}
14776 	return (particle->minOccurs * min);
14777     } else {
14778 	/* <all> and <sequence> */
14779 	int sum = 0;
14780 	xmlSchemaParticlePtr part =
14781 	    (xmlSchemaParticlePtr) particle->children->children;
14782 
14783 	if (part == NULL)
14784 	    return (0);
14785 	do {
14786 	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14787 		(part->children->type == XML_SCHEMA_TYPE_ANY))
14788 		sum += part->minOccurs;
14789 	    else
14790 		sum += xmlSchemaGetParticleTotalRangeMin(part);
14791 	    part = (xmlSchemaParticlePtr) part->next;
14792 	} while (part != NULL);
14793 	return (particle->minOccurs * sum);
14794     }
14795 }
14796 
14797 /**
14798  * xmlSchemaGetParticleTotalRangeMax:
14799  * @particle: the particle
14800  *
14801  * Schema Component Constraint: Effective Total Range
14802  * (all and sequence) + (choice)
14803  *
14804  * Returns the maximum Effective Total Range.
14805  */
14806 static int
14807 xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
14808 {
14809     if ((particle->children == NULL) ||
14810 	(particle->children->children == NULL))
14811 	return (0);
14812     if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14813 	int max = -1, cur;
14814 	xmlSchemaParticlePtr part =
14815 	    (xmlSchemaParticlePtr) particle->children->children;
14816 
14817 	for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14818 	    if (part->children == NULL)
14819 		continue;
14820 	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14821 		(part->children->type == XML_SCHEMA_TYPE_ANY))
14822 		cur = part->maxOccurs;
14823 	    else
14824 		cur = xmlSchemaGetParticleTotalRangeMax(part);
14825 	    if (cur == UNBOUNDED)
14826 		return (UNBOUNDED);
14827 	    if ((max < cur) || (max == -1))
14828 		max = cur;
14829 	}
14830 	/* TODO: Handle overflows? */
14831 	return (particle->maxOccurs * max);
14832     } else {
14833 	/* <all> and <sequence> */
14834 	int sum = 0, cur;
14835 	xmlSchemaParticlePtr part =
14836 	    (xmlSchemaParticlePtr) particle->children->children;
14837 
14838 	for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14839 	    if (part->children == NULL)
14840 		continue;
14841 	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14842 		(part->children->type == XML_SCHEMA_TYPE_ANY))
14843 		cur = part->maxOccurs;
14844 	    else
14845 		cur = xmlSchemaGetParticleTotalRangeMax(part);
14846 	    if (cur == UNBOUNDED)
14847 		return (UNBOUNDED);
14848 	    if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
14849 		return (UNBOUNDED);
14850 	    sum += cur;
14851 	}
14852 	/* TODO: Handle overflows? */
14853 	return (particle->maxOccurs * sum);
14854     }
14855 }
14856 #endif
14857 
14858 /**
14859  * xmlSchemaGetParticleEmptiable:
14860  * @particle: the particle
14861  *
14862  * Returns 1 if emptiable, 0 otherwise.
14863  */
14864 static int
xmlSchemaGetParticleEmptiable(xmlSchemaParticlePtr particle)14865 xmlSchemaGetParticleEmptiable(xmlSchemaParticlePtr particle)
14866 {
14867     xmlSchemaParticlePtr part;
14868     int emptiable;
14869 
14870     if ((particle->children == NULL) || (particle->minOccurs == 0))
14871 	return (1);
14872 
14873     part = (xmlSchemaParticlePtr) particle->children->children;
14874     if (part == NULL)
14875         return (1);
14876 
14877     while (part != NULL) {
14878         if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14879             (part->children->type == XML_SCHEMA_TYPE_ANY))
14880             emptiable = (part->minOccurs == 0);
14881         else
14882             emptiable = xmlSchemaGetParticleEmptiable(part);
14883         if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14884             if (emptiable)
14885                 return (1);
14886         } else {
14887 	    /* <all> and <sequence> */
14888             if (!emptiable)
14889                 return (0);
14890         }
14891         part = (xmlSchemaParticlePtr) part->next;
14892     }
14893 
14894     if (particle->children->type == XML_SCHEMA_TYPE_CHOICE)
14895         return (0);
14896     else
14897         return (1);
14898 }
14899 
14900 /**
14901  * xmlSchemaIsParticleEmptiable:
14902  * @particle: the particle
14903  *
14904  * Schema Component Constraint: Particle Emptiable
14905  * Checks whether the given particle is emptiable.
14906  *
14907  * Returns 1 if emptiable, 0 otherwise.
14908  */
14909 static int
xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)14910 xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
14911 {
14912     /*
14913     * SPEC (1) "Its {min occurs} is 0."
14914     */
14915     if ((particle == NULL) || (particle->minOccurs == 0) ||
14916 	(particle->children == NULL))
14917 	return (1);
14918     /*
14919     * SPEC (2) "Its {term} is a group and the minimum part of the
14920     * effective total range of that group, [...] is 0."
14921     */
14922     if (WXS_IS_MODEL_GROUP(particle->children))
14923 	return (xmlSchemaGetParticleEmptiable(particle));
14924     return (0);
14925 }
14926 
14927 /**
14928  * xmlSchemaCheckCOSSTDerivedOK:
14929  * @actxt: a context
14930  * @type:  the derived simple type definition
14931  * @baseType:  the base type definition
14932  * @subset: the subset of ('restriction', etc.)
14933  *
14934  * Schema Component Constraint:
14935  * Type Derivation OK (Simple) (cos-st-derived-OK)
14936  *
14937  * Checks whether @type can be validly
14938  * derived from @baseType.
14939  *
14940  * Returns 0 on success, an positive error code otherwise.
14941  */
14942 static int
xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,xmlSchemaTypePtr type,xmlSchemaTypePtr baseType,int subset)14943 xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
14944 			     xmlSchemaTypePtr type,
14945 			     xmlSchemaTypePtr baseType,
14946 			     int subset)
14947 {
14948     /*
14949     * 1 They are the same type definition.
14950     * TODO: The identity check might have to be more complex than this.
14951     */
14952     if (type == baseType)
14953 	return (0);
14954     /*
14955     * 2.1 restriction is not in the subset, or in the {final}
14956     * of its own {base type definition};
14957     *
14958     * NOTE that this will be used also via "xsi:type".
14959     *
14960     * TODO: Revise this, it looks strange. How can the "type"
14961     * not be fixed or *in* fixing?
14962     */
14963     if (WXS_IS_TYPE_NOT_FIXED(type))
14964 	if (xmlSchemaTypeFixup(type, actxt) == -1)
14965 	    return(-1);
14966     if (WXS_IS_TYPE_NOT_FIXED(baseType))
14967 	if (xmlSchemaTypeFixup(baseType, actxt) == -1)
14968 	    return(-1);
14969     if ((subset & SUBSET_RESTRICTION) ||
14970 	(xmlSchemaTypeFinalContains(type->baseType,
14971 	    XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
14972 	return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
14973     }
14974     /* 2.2 */
14975     if (type->baseType == baseType) {
14976 	/*
14977 	* 2.2.1 D's `base type definition` is B.
14978 	*/
14979 	return (0);
14980     }
14981     /*
14982     * 2.2.2 D's `base type definition` is not the `ur-type definition`
14983     * and is validly derived from B given the subset, as defined by this
14984     * constraint.
14985     */
14986     if ((! WXS_IS_ANYTYPE(type->baseType)) &&
14987 	(xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
14988 	    baseType, subset) == 0)) {
14989 	return (0);
14990     }
14991     /*
14992     * 2.2.3 D's {variety} is list or union and B is the `simple ur-type
14993     * definition`.
14994     */
14995     if (WXS_IS_ANY_SIMPLE_TYPE(baseType) &&
14996 	(WXS_IS_LIST(type) || WXS_IS_UNION(type))) {
14997 	return (0);
14998     }
14999     /*
15000     * 2.2.4 B's {variety} is union and D is validly derived from a type
15001     * definition in B's {member type definitions} given the subset, as
15002     * defined by this constraint.
15003     *
15004     * NOTE: This seems not to involve built-in types, since there is no
15005     * built-in Union Simple Type.
15006     */
15007     if (WXS_IS_UNION(baseType)) {
15008 	xmlSchemaTypeLinkPtr cur;
15009 
15010 	cur = baseType->memberTypes;
15011 	while (cur != NULL) {
15012 	    if (WXS_IS_TYPE_NOT_FIXED(cur->type))
15013 		if (xmlSchemaTypeFixup(cur->type, actxt) == -1)
15014 		    return(-1);
15015 	    if (xmlSchemaCheckCOSSTDerivedOK(actxt,
15016 		    type, cur->type, subset) == 0)
15017 	    {
15018 		/*
15019 		* It just has to be validly derived from at least one
15020 		* member-type.
15021 		*/
15022 		return (0);
15023 	    }
15024 	    cur = cur->next;
15025 	}
15026     }
15027     return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
15028 }
15029 
15030 /**
15031  * xmlSchemaCheckTypeDefCircularInternal:
15032  * @pctxt:  the schema parser context
15033  * @ctxtType:  the type definition
15034  * @ancestor: an ancestor of @ctxtType
15035  *
15036  * Checks st-props-correct (2) + ct-props-correct (3).
15037  * Circular type definitions are not allowed.
15038  *
15039  * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
15040  * circular, 0 otherwise.
15041  */
15042 static int
xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr ctxtType,xmlSchemaTypePtr ancestor)15043 xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
15044 			   xmlSchemaTypePtr ctxtType,
15045 			   xmlSchemaTypePtr ancestor)
15046 {
15047     int ret;
15048 
15049     if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
15050 	return (0);
15051 
15052     if (ctxtType == ancestor) {
15053 	xmlSchemaPCustomErr(pctxt,
15054 	    XML_SCHEMAP_ST_PROPS_CORRECT_2,
15055 	    WXS_BASIC_CAST ctxtType, WXS_ITEM_NODE(ctxtType),
15056 	    "The definition is circular", NULL);
15057 	return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
15058     }
15059     if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
15060 	/*
15061 	* Avoid infinite recursion on circular types not yet checked.
15062 	*/
15063 	return (0);
15064     }
15065     ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
15066     ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
15067 	ancestor->baseType);
15068     ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
15069     return (ret);
15070 }
15071 
15072 /**
15073  * xmlSchemaCheckTypeDefCircular:
15074  * @item:  the complex/simple type definition
15075  * @ctxt:  the parser context
15076  * @name:  the name
15077  *
15078  * Checks for circular type definitions.
15079  */
15080 static void
xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,xmlSchemaParserCtxtPtr ctxt)15081 xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
15082 			      xmlSchemaParserCtxtPtr ctxt)
15083 {
15084     if ((item == NULL) ||
15085 	(item->type == XML_SCHEMA_TYPE_BASIC) ||
15086 	(item->baseType == NULL))
15087 	return;
15088     xmlSchemaCheckTypeDefCircularInternal(ctxt, item,
15089 	item->baseType);
15090 }
15091 
15092 /*
15093 * Simple Type Definition Representation OK (src-simple-type) 4
15094 *
15095 * "4 Circular union type definition is disallowed. That is, if the
15096 * <union> alternative is chosen, there must not be any entries in the
15097 * memberTypes [attribute] at any depth which resolve to the component
15098 * corresponding to the <simpleType>."
15099 *
15100 * Note that this should work on the *representation* of a component,
15101 * thus assumes any union types in the member types not being yet
15102 * substituted. At this stage we need the variety of the types
15103 * to be already computed.
15104 */
15105 static int
xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr ctxType,xmlSchemaTypeLinkPtr members)15106 xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,
15107 					xmlSchemaTypePtr ctxType,
15108 					xmlSchemaTypeLinkPtr members)
15109 {
15110     xmlSchemaTypeLinkPtr member;
15111     xmlSchemaTypePtr memberType;
15112 
15113     member = members;
15114     while (member != NULL) {
15115 	memberType = member->type;
15116 	while ((memberType != NULL) &&
15117 	    (memberType->type != XML_SCHEMA_TYPE_BASIC)) {
15118 	    if (memberType == ctxType) {
15119 		xmlSchemaPCustomErr(pctxt,
15120 		    XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
15121 		    WXS_BASIC_CAST ctxType, NULL,
15122 		    "The union type definition is circular", NULL);
15123 		return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
15124 	    }
15125 	    if ((WXS_IS_UNION(memberType)) &&
15126 		((memberType->flags & XML_SCHEMAS_TYPE_MARKED) == 0))
15127 	    {
15128 		int res;
15129 		memberType->flags |= XML_SCHEMAS_TYPE_MARKED;
15130 		res = xmlSchemaCheckUnionTypeDefCircularRecur(pctxt,
15131 		    ctxType,
15132 		    xmlSchemaGetUnionSimpleTypeMemberTypes(memberType));
15133 		memberType->flags ^= XML_SCHEMAS_TYPE_MARKED;
15134 		if (res != 0)
15135 		    return(res);
15136 	    }
15137 	    memberType = memberType->baseType;
15138 	}
15139 	member = member->next;
15140     }
15141     return(0);
15142 }
15143 
15144 static int
xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)15145 xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,
15146 				   xmlSchemaTypePtr type)
15147 {
15148     if (! WXS_IS_UNION(type))
15149 	return(0);
15150     return(xmlSchemaCheckUnionTypeDefCircularRecur(pctxt, type,
15151 	type->memberTypes));
15152 }
15153 
15154 /**
15155  * xmlSchemaResolveTypeReferences:
15156  * @item:  the complex/simple type definition
15157  * @ctxt:  the parser context
15158  * @name:  the name
15159  *
15160  * Resolves type definition references
15161  */
15162 static void
xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,xmlSchemaParserCtxtPtr ctxt)15163 xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,
15164 			 xmlSchemaParserCtxtPtr ctxt)
15165 {
15166     if (typeDef == NULL)
15167 	return;
15168 
15169     /*
15170     * Resolve the base type.
15171     */
15172     if (typeDef->baseType == NULL) {
15173 	typeDef->baseType = xmlSchemaGetType(ctxt->schema,
15174 	    typeDef->base, typeDef->baseNs);
15175 	if (typeDef->baseType == NULL) {
15176 	    xmlSchemaPResCompAttrErr(ctxt,
15177 		XML_SCHEMAP_SRC_RESOLVE,
15178 		WXS_BASIC_CAST typeDef, typeDef->node,
15179 		"base", typeDef->base, typeDef->baseNs,
15180 		XML_SCHEMA_TYPE_SIMPLE, NULL);
15181 	    return;
15182 	}
15183     }
15184     if (WXS_IS_SIMPLE(typeDef)) {
15185 	if (WXS_IS_UNION(typeDef)) {
15186 	    /*
15187 	    * Resolve the memberTypes.
15188 	    */
15189 	    xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
15190 	    return;
15191 	} else if (WXS_IS_LIST(typeDef)) {
15192 	    /*
15193 	    * Resolve the itemType.
15194 	    */
15195 	    if ((typeDef->subtypes == NULL) && (typeDef->base != NULL)) {
15196 
15197 		typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
15198 		    typeDef->base, typeDef->baseNs);
15199 
15200 		if ((typeDef->subtypes == NULL) ||
15201 		    (! WXS_IS_SIMPLE(typeDef->subtypes)))
15202 		{
15203 		    typeDef->subtypes = NULL;
15204 		    xmlSchemaPResCompAttrErr(ctxt,
15205 			XML_SCHEMAP_SRC_RESOLVE,
15206 			WXS_BASIC_CAST typeDef, typeDef->node,
15207 			"itemType", typeDef->base, typeDef->baseNs,
15208 			XML_SCHEMA_TYPE_SIMPLE, NULL);
15209 		}
15210 	    }
15211 	    return;
15212 	}
15213     }
15214     /*
15215     * The ball of letters below means, that if we have a particle
15216     * which has a QName-helper component as its {term}, we want
15217     * to resolve it...
15218     */
15219     else if ((WXS_TYPE_CONTENTTYPE(typeDef) != NULL) &&
15220 	((WXS_TYPE_CONTENTTYPE(typeDef))->type ==
15221 	    XML_SCHEMA_TYPE_PARTICLE) &&
15222 	(WXS_TYPE_PARTICLE_TERM(typeDef) != NULL) &&
15223 	((WXS_TYPE_PARTICLE_TERM(typeDef))->type ==
15224 	    XML_SCHEMA_EXTRA_QNAMEREF))
15225     {
15226 	xmlSchemaQNameRefPtr ref =
15227 	    WXS_QNAME_CAST WXS_TYPE_PARTICLE_TERM(typeDef);
15228 	xmlSchemaModelGroupDefPtr groupDef;
15229 
15230 	/*
15231 	* URGENT TODO: Test this.
15232 	*/
15233 	WXS_TYPE_PARTICLE_TERM(typeDef) = NULL;
15234 	/*
15235 	* Resolve the MG definition reference.
15236 	*/
15237 	groupDef =
15238 	    WXS_MODEL_GROUPDEF_CAST xmlSchemaGetNamedComponent(ctxt->schema,
15239 		ref->itemType, ref->name, ref->targetNamespace);
15240 	if (groupDef == NULL) {
15241 	    xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
15242 		NULL, WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)),
15243 		"ref", ref->name, ref->targetNamespace, ref->itemType,
15244 		NULL);
15245 	    /* Remove the particle. */
15246 	    WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15247 	} else if (WXS_MODELGROUPDEF_MODEL(groupDef) == NULL)
15248 	    /* Remove the particle. */
15249 	    WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15250 	else {
15251 	    /*
15252 	    * Assign the MG definition's {model group} to the
15253 	    * particle's {term}.
15254 	    */
15255 	    WXS_TYPE_PARTICLE_TERM(typeDef) = WXS_MODELGROUPDEF_MODEL(groupDef);
15256 
15257 	    if (WXS_MODELGROUPDEF_MODEL(groupDef)->type == XML_SCHEMA_TYPE_ALL) {
15258 		/*
15259 		* SPEC cos-all-limited (1.2)
15260 		* "1.2 the {term} property of a particle with
15261 		* {max occurs}=1 which is part of a pair which constitutes
15262 		* the {content type} of a complex type definition."
15263 		*/
15264 		if ((WXS_TYPE_PARTICLE(typeDef))->maxOccurs != 1) {
15265 		    xmlSchemaCustomErr(ACTXT_CAST ctxt,
15266 			/* TODO: error code */
15267 			XML_SCHEMAP_COS_ALL_LIMITED,
15268 			WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)), NULL,
15269 			"The particle's {max occurs} must be 1, since the "
15270 			"reference resolves to an 'all' model group",
15271 			NULL, NULL);
15272 		}
15273 	    }
15274 	}
15275     }
15276 }
15277 
15278 
15279 
15280 /**
15281  * xmlSchemaCheckSTPropsCorrect:
15282  * @ctxt:  the schema parser context
15283  * @type:  the simple type definition
15284  *
15285  * Checks st-props-correct.
15286  *
15287  * Returns 0 if the properties are correct,
15288  * if not, a positive error code and -1 on internal
15289  * errors.
15290  */
15291 static int
xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)15292 xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
15293 			     xmlSchemaTypePtr type)
15294 {
15295     xmlSchemaTypePtr baseType = type->baseType;
15296     xmlChar *str = NULL;
15297 
15298     /* STATE: error funcs converted. */
15299     /*
15300     * Schema Component Constraint: Simple Type Definition Properties Correct
15301     *
15302     * NOTE: This is somehow redundant, since we actually built a simple type
15303     * to have all the needed information; this acts as an self test.
15304     */
15305     /* Base type: If the datatype has been `derived` by `restriction`
15306     * then the Simple Type Definition component from which it is `derived`,
15307     * otherwise the Simple Type Definition for anySimpleType ($4.1.6).
15308     */
15309     if (baseType == NULL) {
15310 	/*
15311 	* TODO: Think about: "modulo the impact of Missing
15312 	* Sub-components ($5.3)."
15313 	*/
15314 	xmlSchemaPCustomErr(ctxt,
15315 	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15316 	    WXS_BASIC_CAST type, NULL,
15317 	    "No base type existent", NULL);
15318 	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15319 
15320     }
15321     if (! WXS_IS_SIMPLE(baseType)) {
15322 	xmlSchemaPCustomErr(ctxt,
15323 	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15324 	    WXS_BASIC_CAST type, NULL,
15325 	    "The base type '%s' is not a simple type",
15326 	    xmlSchemaGetComponentQName(&str, baseType));
15327 	FREE_AND_NULL(str)
15328 	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15329     }
15330     if ((WXS_IS_LIST(type) || WXS_IS_UNION(type)) &&
15331 	(WXS_IS_RESTRICTION(type) == 0) &&
15332 	((! WXS_IS_ANY_SIMPLE_TYPE(baseType)) &&
15333          (baseType->type != XML_SCHEMA_TYPE_SIMPLE))) {
15334 	xmlSchemaPCustomErr(ctxt,
15335 	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15336 	    WXS_BASIC_CAST type, NULL,
15337 	    "A type, derived by list or union, must have "
15338 	    "the simple ur-type definition as base type, not '%s'",
15339 	    xmlSchemaGetComponentQName(&str, baseType));
15340 	FREE_AND_NULL(str)
15341 	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15342     }
15343     /*
15344     * Variety: One of {atomic, list, union}.
15345     */
15346     if ((! WXS_IS_ATOMIC(type)) && (! WXS_IS_UNION(type)) &&
15347 	(! WXS_IS_LIST(type))) {
15348 	xmlSchemaPCustomErr(ctxt,
15349 	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15350 	    WXS_BASIC_CAST type, NULL,
15351 	    "The variety is absent", NULL);
15352 	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15353     }
15354     /* TODO: Finish this. Hmm, is this finished? */
15355 
15356     /*
15357     * 3 The {final} of the {base type definition} must not contain restriction.
15358     */
15359     if (xmlSchemaTypeFinalContains(baseType,
15360 	XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15361 	xmlSchemaPCustomErr(ctxt,
15362 	    XML_SCHEMAP_ST_PROPS_CORRECT_3,
15363 	    WXS_BASIC_CAST type, NULL,
15364 	    "The 'final' of its base type '%s' must not contain "
15365 	    "'restriction'",
15366 	    xmlSchemaGetComponentQName(&str, baseType));
15367 	FREE_AND_NULL(str)
15368 	return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
15369     }
15370 
15371     /*
15372     * 2 All simple type definitions must be derived ultimately from the `simple
15373     * ur-type definition` (so circular definitions are disallowed). That is, it
15374     * must be possible to reach a built-in primitive datatype or the `simple
15375     * ur-type definition` by repeatedly following the {base type definition}.
15376     *
15377     * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
15378     */
15379     return (0);
15380 }
15381 
15382 /**
15383  * xmlSchemaCheckCOSSTRestricts:
15384  * @ctxt:  the schema parser context
15385  * @type:  the simple type definition
15386  *
15387  * Schema Component Constraint:
15388  * Derivation Valid (Restriction, Simple) (cos-st-restricts)
15389 
15390  * Checks if the given @type (simpleType) is derived validly by restriction.
15391  * STATUS:
15392  *
15393  * Returns -1 on internal errors, 0 if the type is validly derived,
15394  * a positive error code otherwise.
15395  */
15396 static int
xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)15397 xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
15398 			     xmlSchemaTypePtr type)
15399 {
15400     xmlChar *str = NULL;
15401 
15402     if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
15403 	PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15404 	    "given type is not a user-derived simpleType");
15405 	return (-1);
15406     }
15407 
15408     if (WXS_IS_ATOMIC(type)) {
15409 	xmlSchemaTypePtr primitive;
15410 	/*
15411 	* 1.1 The {base type definition} must be an atomic simple
15412 	* type definition or a built-in primitive datatype.
15413 	*/
15414 	if (! WXS_IS_ATOMIC(type->baseType)) {
15415 	    xmlSchemaPCustomErr(pctxt,
15416 		XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
15417 		WXS_BASIC_CAST type, NULL,
15418 		"The base type '%s' is not an atomic simple type",
15419 		xmlSchemaGetComponentQName(&str, type->baseType));
15420 	    FREE_AND_NULL(str)
15421 	    return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
15422 	}
15423 	/* 1.2 The {final} of the {base type definition} must not contain
15424 	* restriction.
15425 	*/
15426 	/* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
15427 	if (xmlSchemaTypeFinalContains(type->baseType,
15428 	    XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15429 	    xmlSchemaPCustomErr(pctxt,
15430 		XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
15431 		WXS_BASIC_CAST type, NULL,
15432 		"The final of its base type '%s' must not contain 'restriction'",
15433 		xmlSchemaGetComponentQName(&str, type->baseType));
15434 	    FREE_AND_NULL(str)
15435 	    return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
15436 	}
15437 
15438 	/*
15439 	* 1.3.1 DF must be an allowed constraining facet for the {primitive
15440 	* type definition}, as specified in the appropriate subsection of 3.2
15441 	* Primitive datatypes.
15442 	*/
15443 	if (type->facets != NULL) {
15444 	    xmlSchemaFacetPtr facet;
15445 	    int ok = 1;
15446 
15447 	    primitive = xmlSchemaGetPrimitiveType(type);
15448 	    if (primitive == NULL) {
15449 		PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15450 		    "failed to get primitive type");
15451 		return (-1);
15452 	    }
15453 	    facet = type->facets;
15454 	    do {
15455 		if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
15456 		    ok = 0;
15457 		    xmlSchemaPIllegalFacetAtomicErr(pctxt,
15458 			XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
15459 			type, primitive, facet);
15460 		}
15461 		facet = facet->next;
15462 	    } while (facet != NULL);
15463 	    if (ok == 0)
15464 		return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
15465 	}
15466 	/*
15467 	* SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
15468 	* of the {base type definition} (call this BF),then the DF's {value}
15469 	* must be a valid restriction of BF's {value} as defined in
15470 	* [XML Schemas: Datatypes]."
15471 	*
15472 	* NOTE (1.3.2) Facet derivation constraints are currently handled in
15473 	* xmlSchemaDeriveAndValidateFacets()
15474 	*/
15475     } else if (WXS_IS_LIST(type)) {
15476 	xmlSchemaTypePtr itemType = NULL;
15477 
15478 	itemType = type->subtypes;
15479 	if ((itemType == NULL) || (! WXS_IS_SIMPLE(itemType))) {
15480 	    PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15481 		"failed to evaluate the item type");
15482 	    return (-1);
15483 	}
15484 	if (WXS_IS_TYPE_NOT_FIXED(itemType))
15485 	    xmlSchemaTypeFixup(itemType, ACTXT_CAST pctxt);
15486 	/*
15487 	* 2.1 The {item type definition} must have a {variety} of atomic or
15488 	* union (in which case all the {member type definitions}
15489 	* must be atomic).
15490 	*/
15491 	if ((! WXS_IS_ATOMIC(itemType)) &&
15492 	    (! WXS_IS_UNION(itemType))) {
15493 	    xmlSchemaPCustomErr(pctxt,
15494 		XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15495 		WXS_BASIC_CAST type, NULL,
15496 		"The item type '%s' does not have a variety of atomic or union",
15497 		xmlSchemaGetComponentQName(&str, itemType));
15498 	    FREE_AND_NULL(str)
15499 	    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15500 	} else if (WXS_IS_UNION(itemType)) {
15501 	    xmlSchemaTypeLinkPtr member;
15502 
15503 	    member = itemType->memberTypes;
15504 	    while (member != NULL) {
15505 		if (! WXS_IS_ATOMIC(member->type)) {
15506 		    xmlSchemaPCustomErr(pctxt,
15507 			XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15508 			WXS_BASIC_CAST type, NULL,
15509 			"The item type is a union type, but the "
15510 			"member type '%s' of this item type is not atomic",
15511 			xmlSchemaGetComponentQName(&str, member->type));
15512 		    FREE_AND_NULL(str)
15513 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15514 		}
15515 		member = member->next;
15516 	    }
15517 	}
15518 
15519 	if (WXS_IS_ANY_SIMPLE_TYPE(type->baseType)) {
15520 	    xmlSchemaFacetPtr facet;
15521 	    /*
15522 	    * This is the case if we have: <simpleType><list ..
15523 	    */
15524 	    /*
15525 	    * 2.3.1
15526 	    * 2.3.1.1 The {final} of the {item type definition} must not
15527 	    * contain list.
15528 	    */
15529 	    if (xmlSchemaTypeFinalContains(itemType,
15530 		XML_SCHEMAS_TYPE_FINAL_LIST)) {
15531 		xmlSchemaPCustomErr(pctxt,
15532 		    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
15533 		    WXS_BASIC_CAST type, NULL,
15534 		    "The final of its item type '%s' must not contain 'list'",
15535 		    xmlSchemaGetComponentQName(&str, itemType));
15536 		FREE_AND_NULL(str)
15537 		return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
15538 	    }
15539 	    /*
15540 	    * 2.3.1.2 The {facets} must only contain the whiteSpace
15541 	    * facet component.
15542 	    * OPTIMIZE TODO: the S4S already disallows any facet
15543 	    * to be specified.
15544 	    */
15545 	    if (type->facets != NULL) {
15546 		facet = type->facets;
15547 		do {
15548 		    if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
15549 			xmlSchemaPIllegalFacetListUnionErr(pctxt,
15550 			    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
15551 			    type, facet);
15552 			return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
15553 		    }
15554 		    facet = facet->next;
15555 		} while (facet != NULL);
15556 	    }
15557 	    /*
15558 	    * MAYBE TODO: (Hmm, not really) Datatypes states:
15559 	    * A `list` datatype can be `derived` from an `atomic` datatype
15560 	    * whose `lexical space` allows space (such as string or anyURI)or
15561 	    * a `union` datatype any of whose {member type definitions}'s
15562 	    * `lexical space` allows space.
15563 	    */
15564 	} else {
15565 	    /*
15566 	    * This is the case if we have: <simpleType><restriction ...
15567 	    * I.e. the variety of "list" is inherited.
15568 	    */
15569 	    /*
15570 	    * 2.3.2
15571 	    * 2.3.2.1 The {base type definition} must have a {variety} of list.
15572 	    */
15573 	    if (! WXS_IS_LIST(type->baseType)) {
15574 		xmlSchemaPCustomErr(pctxt,
15575 		    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
15576 		    WXS_BASIC_CAST type, NULL,
15577 		    "The base type '%s' must be a list type",
15578 		    xmlSchemaGetComponentQName(&str, type->baseType));
15579 		FREE_AND_NULL(str)
15580 		return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
15581 	    }
15582 	    /*
15583 	    * 2.3.2.2 The {final} of the {base type definition} must not
15584 	    * contain restriction.
15585 	    */
15586 	    if (xmlSchemaTypeFinalContains(type->baseType,
15587 		XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15588 		xmlSchemaPCustomErr(pctxt,
15589 		    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
15590 		    WXS_BASIC_CAST type, NULL,
15591 		    "The 'final' of the base type '%s' must not contain 'restriction'",
15592 		    xmlSchemaGetComponentQName(&str, type->baseType));
15593 		FREE_AND_NULL(str)
15594 		return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
15595 	    }
15596 	    /*
15597 	    * 2.3.2.3 The {item type definition} must be validly derived
15598 	    * from the {base type definition}'s {item type definition} given
15599 	    * the empty set, as defined in Type Derivation OK (Simple) ($3.14.6).
15600 	    */
15601 	    {
15602 		xmlSchemaTypePtr baseItemType;
15603 
15604 		baseItemType = type->baseType->subtypes;
15605 		if ((baseItemType == NULL) || (! WXS_IS_SIMPLE(baseItemType))) {
15606 		    PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15607 			"failed to eval the item type of a base type");
15608 		    return (-1);
15609 		}
15610 		if ((itemType != baseItemType) &&
15611 		    (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt, itemType,
15612 			baseItemType, 0) != 0)) {
15613 		    xmlChar *strBIT = NULL, *strBT = NULL;
15614 		    xmlSchemaPCustomErrExt(pctxt,
15615 			XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
15616 			WXS_BASIC_CAST type, NULL,
15617 			"The item type '%s' is not validly derived from "
15618 			"the item type '%s' of the base type '%s'",
15619 			xmlSchemaGetComponentQName(&str, itemType),
15620 			xmlSchemaGetComponentQName(&strBIT, baseItemType),
15621 			xmlSchemaGetComponentQName(&strBT, type->baseType));
15622 
15623 		    FREE_AND_NULL(str)
15624 		    FREE_AND_NULL(strBIT)
15625 		    FREE_AND_NULL(strBT)
15626 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
15627 		}
15628 	    }
15629 
15630 	    if (type->facets != NULL) {
15631 		xmlSchemaFacetPtr facet;
15632 		int ok = 1;
15633 		/*
15634 		* 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
15635 		* and enumeration facet components are allowed among the {facets}.
15636 		*/
15637 		facet = type->facets;
15638 		do {
15639 		    switch (facet->type) {
15640 			case XML_SCHEMA_FACET_LENGTH:
15641 			case XML_SCHEMA_FACET_MINLENGTH:
15642 			case XML_SCHEMA_FACET_MAXLENGTH:
15643 			case XML_SCHEMA_FACET_WHITESPACE:
15644 			    /*
15645 			    * TODO: 2.5.1.2 List datatypes
15646 			    * The value of `whiteSpace` is fixed to the value collapse.
15647 			    */
15648 			case XML_SCHEMA_FACET_PATTERN:
15649 			case XML_SCHEMA_FACET_ENUMERATION:
15650 			    break;
15651 			default: {
15652 			    xmlSchemaPIllegalFacetListUnionErr(pctxt,
15653 				XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
15654 				type, facet);
15655 			    /*
15656 			    * We could return, but it's nicer to report all
15657 			    * invalid facets.
15658 			    */
15659 			    ok = 0;
15660 			}
15661 		    }
15662 		    facet = facet->next;
15663 		} while (facet != NULL);
15664 		if (ok == 0)
15665 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
15666 		/*
15667 		* SPEC (2.3.2.5) (same as 1.3.2)
15668 		*
15669 		* NOTE (2.3.2.5) This is currently done in
15670 		* xmlSchemaDeriveAndValidateFacets()
15671 		*/
15672 	    }
15673 	}
15674     } else if (WXS_IS_UNION(type)) {
15675 	/*
15676 	* 3.1 The {member type definitions} must all have {variety} of
15677 	* atomic or list.
15678 	*/
15679 	xmlSchemaTypeLinkPtr member;
15680 
15681 	member = type->memberTypes;
15682 	while (member != NULL) {
15683 	    if (WXS_IS_TYPE_NOT_FIXED(member->type))
15684 		xmlSchemaTypeFixup(member->type, ACTXT_CAST pctxt);
15685 
15686 	    if ((! WXS_IS_ATOMIC(member->type)) &&
15687 		(! WXS_IS_LIST(member->type))) {
15688 		xmlSchemaPCustomErr(pctxt,
15689 		    XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
15690 		    WXS_BASIC_CAST type, NULL,
15691 		    "The member type '%s' is neither an atomic, nor a list type",
15692 		    xmlSchemaGetComponentQName(&str, member->type));
15693 		FREE_AND_NULL(str)
15694 		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
15695 	    }
15696 	    member = member->next;
15697 	}
15698 	/*
15699 	* 3.3.1 If the {base type definition} is the `simple ur-type
15700 	* definition`
15701 	*/
15702 	if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
15703 	    /*
15704 	    * 3.3.1.1 All of the {member type definitions} must have a
15705 	    * {final} which does not contain union.
15706 	    */
15707 	    member = type->memberTypes;
15708 	    while (member != NULL) {
15709 		if (xmlSchemaTypeFinalContains(member->type,
15710 		    XML_SCHEMAS_TYPE_FINAL_UNION)) {
15711 		    xmlSchemaPCustomErr(pctxt,
15712 			XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
15713 			WXS_BASIC_CAST type, NULL,
15714 			"The 'final' of member type '%s' contains 'union'",
15715 			xmlSchemaGetComponentQName(&str, member->type));
15716 		    FREE_AND_NULL(str)
15717 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
15718 		}
15719 		member = member->next;
15720 	    }
15721 	    /*
15722 	    * 3.3.1.2 The {facets} must be empty.
15723 	    */
15724 	    if (type->facetSet != NULL) {
15725 		xmlSchemaPCustomErr(pctxt,
15726 		    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
15727 		    WXS_BASIC_CAST type, NULL,
15728 		    "No facets allowed", NULL);
15729 		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
15730 	    }
15731 	} else {
15732 	    /*
15733 	    * 3.3.2.1 The {base type definition} must have a {variety} of union.
15734 	    * I.e. the variety of "list" is inherited.
15735 	    */
15736 	    if (! WXS_IS_UNION(type->baseType)) {
15737 		xmlSchemaPCustomErr(pctxt,
15738 		    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
15739 		    WXS_BASIC_CAST type, NULL,
15740 		    "The base type '%s' is not a union type",
15741 		    xmlSchemaGetComponentQName(&str, type->baseType));
15742 		FREE_AND_NULL(str)
15743 		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
15744 	    }
15745 	    /*
15746 	    * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
15747 	    */
15748 	    if (xmlSchemaTypeFinalContains(type->baseType,
15749 		XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15750 		xmlSchemaPCustomErr(pctxt,
15751 		    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
15752 		    WXS_BASIC_CAST type, NULL,
15753 		    "The 'final' of its base type '%s' must not contain 'restriction'",
15754 		    xmlSchemaGetComponentQName(&str, type->baseType));
15755 		FREE_AND_NULL(str)
15756 		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
15757 	    }
15758 	    /*
15759 	    * 3.3.2.3 The {member type definitions}, in order, must be validly
15760 	    * derived from the corresponding type definitions in the {base
15761 	    * type definition}'s {member type definitions} given the empty set,
15762 	    * as defined in Type Derivation OK (Simple) ($3.14.6).
15763 	    */
15764 	    {
15765 		xmlSchemaTypeLinkPtr baseMember;
15766 
15767 		/*
15768 		* OPTIMIZE: if the type is restricting, it has no local defined
15769 		* member types and inherits the member types of the base type;
15770 		* thus a check for equality can be skipped.
15771 		*/
15772 		/*
15773 		* Even worse: I cannot see a scenario where a restricting
15774 		* union simple type can have other member types as the member
15775 		* types of it's base type. This check seems not necessary with
15776 		* respect to the derivation process in libxml2.
15777 		* But necessary if constructing types with an API.
15778 		*/
15779 		if (type->memberTypes != NULL) {
15780 		    member = type->memberTypes;
15781 		    baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
15782 		    if ((member == NULL) && (baseMember != NULL)) {
15783 			PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15784 			    "different number of member types in base");
15785 		    }
15786 		    while (member != NULL) {
15787 			if (baseMember == NULL) {
15788 			    PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15789 			    "different number of member types in base");
15790 			} else if ((member->type != baseMember->type) &&
15791 			    (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
15792 				member->type, baseMember->type, 0) != 0)) {
15793 			    xmlChar *strBMT = NULL, *strBT = NULL;
15794 
15795 			    xmlSchemaPCustomErrExt(pctxt,
15796 				XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
15797 				WXS_BASIC_CAST type, NULL,
15798 				"The member type %s is not validly "
15799 				"derived from its corresponding member "
15800 				"type %s of the base type %s",
15801 				xmlSchemaGetComponentQName(&str, member->type),
15802 				xmlSchemaGetComponentQName(&strBMT, baseMember->type),
15803 				xmlSchemaGetComponentQName(&strBT, type->baseType));
15804 			    FREE_AND_NULL(str)
15805 			    FREE_AND_NULL(strBMT)
15806 			    FREE_AND_NULL(strBT)
15807 			    return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
15808 			}
15809 			member = member->next;
15810                         if (baseMember != NULL)
15811                             baseMember = baseMember->next;
15812 		    }
15813 		}
15814 	    }
15815 	    /*
15816 	    * 3.3.2.4 Only pattern and enumeration facet components are
15817 	    * allowed among the {facets}.
15818 	    */
15819 	    if (type->facets != NULL) {
15820 		xmlSchemaFacetPtr facet;
15821 		int ok = 1;
15822 
15823 		facet = type->facets;
15824 		do {
15825 		    if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
15826 			(facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
15827 			xmlSchemaPIllegalFacetListUnionErr(pctxt,
15828 				XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
15829 				type, facet);
15830 			ok = 0;
15831 		    }
15832 		    facet = facet->next;
15833 		} while (facet != NULL);
15834 		if (ok == 0)
15835 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
15836 
15837 	    }
15838 	    /*
15839 	    * SPEC (3.3.2.5) (same as 1.3.2)
15840 	    *
15841 	    * NOTE (3.3.2.5) This is currently done in
15842 	    * xmlSchemaDeriveAndValidateFacets()
15843 	    */
15844 	}
15845     }
15846 
15847     return (0);
15848 }
15849 
15850 /**
15851  * xmlSchemaCheckSRCSimpleType:
15852  * @ctxt:  the schema parser context
15853  * @type:  the simple type definition
15854  *
15855  * Checks crc-simple-type constraints.
15856  *
15857  * Returns 0 if the constraints are satisfied,
15858  * if not a positive error code and -1 on internal
15859  * errors.
15860  */
15861 #if 0
15862 static int
15863 xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
15864 			    xmlSchemaTypePtr type)
15865 {
15866     /*
15867     * src-simple-type.1 The corresponding simple type definition, if any,
15868     * must satisfy the conditions set out in Constraints on Simple Type
15869     * Definition Schema Components ($3.14.6).
15870     */
15871     if (WXS_IS_RESTRICTION(type)) {
15872 	/*
15873 	* src-simple-type.2 "If the <restriction> alternative is chosen,
15874 	* either it must have a base [attribute] or a <simpleType> among its
15875 	* [children], but not both."
15876 	* NOTE: This is checked in the parse function of <restriction>.
15877 	*/
15878 	/*
15879 	*
15880 	*/
15881     } else if (WXS_IS_LIST(type)) {
15882 	/* src-simple-type.3 "If the <list> alternative is chosen, either it must have
15883 	* an itemType [attribute] or a <simpleType> among its [children],
15884 	* but not both."
15885 	*
15886 	* NOTE: This is checked in the parse function of <list>.
15887 	*/
15888     } else if (WXS_IS_UNION(type)) {
15889 	/*
15890 	* src-simple-type.4 is checked in xmlSchemaCheckUnionTypeDefCircular().
15891 	*/
15892     }
15893     return (0);
15894 }
15895 #endif
15896 
15897 static int
xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)15898 xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
15899 {
15900    if (ctxt->vctxt == NULL) {
15901 	ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
15902 	if (ctxt->vctxt == NULL) {
15903 	    xmlSchemaPErr(ctxt, NULL,
15904 		XML_SCHEMAP_INTERNAL,
15905 		"Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
15906 		"failed to create a temp. validation context.\n",
15907 		NULL, NULL);
15908 	    return (-1);
15909 	}
15910 	/* TODO: Pass user data. */
15911 	xmlSchemaSetValidErrors(ctxt->vctxt,
15912 	    ctxt->error, ctxt->warning, ctxt->errCtxt);
15913 	xmlSchemaSetValidStructuredErrors(ctxt->vctxt,
15914 	    ctxt->serror, ctxt->errCtxt);
15915     }
15916     return (0);
15917 }
15918 
15919 static int
15920 xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
15921 			     xmlNodePtr node,
15922 			     xmlSchemaTypePtr type,
15923 			     const xmlChar *value,
15924 			     xmlSchemaValPtr *retVal,
15925 			     int fireErrors,
15926 			     int normalize,
15927 			     int isNormalized);
15928 
15929 /**
15930  * xmlSchemaParseCheckCOSValidDefault:
15931  * @pctxt:  the schema parser context
15932  * @type:  the simple type definition
15933  * @value: the default value
15934  * @node: an optional node (the holder of the value)
15935  *
15936  * Schema Component Constraint: Element Default Valid (Immediate)
15937  * (cos-valid-default)
15938  * This will be used by the parser only. For the validator there's
15939  * an other version.
15940  *
15941  * Returns 0 if the constraints are satisfied,
15942  * if not, a positive error code and -1 on internal
15943  * errors.
15944  */
15945 static int
xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,xmlNodePtr node,xmlSchemaTypePtr type,const xmlChar * value,xmlSchemaValPtr * val)15946 xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
15947 				   xmlNodePtr node,
15948 				   xmlSchemaTypePtr type,
15949 				   const xmlChar *value,
15950 				   xmlSchemaValPtr *val)
15951 {
15952     int ret = 0;
15953 
15954     /*
15955     * cos-valid-default:
15956     * Schema Component Constraint: Element Default Valid (Immediate)
15957     * For a string to be a valid default with respect to a type
15958     * definition the appropriate case among the following must be true:
15959     */
15960     if WXS_IS_COMPLEX(type) {
15961 	/*
15962 	* Complex type.
15963 	*
15964 	* SPEC (2.1) "its {content type} must be a simple type definition
15965 	* or mixed."
15966 	* SPEC (2.2.2) "If the {content type} is mixed, then the {content
15967 	* type}'s particle must be `emptiable` as defined by
15968 	* Particle Emptiable ($3.9.6)."
15969 	*/
15970 	if ((! WXS_HAS_SIMPLE_CONTENT(type)) &&
15971 	    ((! WXS_HAS_MIXED_CONTENT(type)) || (! WXS_EMPTIABLE(type)))) {
15972 	    /* NOTE that this covers (2.2.2) as well. */
15973 	    xmlSchemaPCustomErr(pctxt,
15974 		XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
15975 		WXS_BASIC_CAST type, type->node,
15976 		"For a string to be a valid default, the type definition "
15977 		"must be a simple type or a complex type with mixed content "
15978 		"and a particle emptiable", NULL);
15979 	    return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
15980 	}
15981     }
15982     /*
15983     * 1 If the type definition is a simple type definition, then the string
15984     * must be `valid` with respect to that definition as defined by String
15985     * Valid ($3.14.4).
15986     *
15987     * AND
15988     *
15989     * 2.2.1 If the {content type} is a simple type definition, then the
15990     * string must be `valid` with respect to that simple type definition
15991     * as defined by String Valid ($3.14.4).
15992     */
15993     if (WXS_IS_SIMPLE(type))
15994 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15995 	    type, value, val, 1, 1, 0);
15996     else if (WXS_HAS_SIMPLE_CONTENT(type))
15997 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15998 	    type->contentTypeDef, value, val, 1, 1, 0);
15999     else
16000 	return (ret);
16001 
16002     if (ret < 0) {
16003 	PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
16004 	    "calling xmlSchemaVCheckCVCSimpleType()");
16005     }
16006 
16007     return (ret);
16008 }
16009 
16010 /**
16011  * xmlSchemaCheckCTPropsCorrect:
16012  * @ctxt:  the schema parser context
16013  * @type:  the complex type definition
16014  *
16015  *.(4.6) Constraints on Complex Type Definition Schema Components
16016  * Schema Component Constraint:
16017  * Complex Type Definition Properties Correct (ct-props-correct)
16018  * STATUS: (seems) complete
16019  *
16020  * Returns 0 if the constraints are satisfied, a positive
16021  * error code if not and -1 if an internal error occurred.
16022  */
16023 static int
xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)16024 xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
16025 			     xmlSchemaTypePtr type)
16026 {
16027     /*
16028     * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
16029     *
16030     * SPEC (1) "The values of the properties of a complex type definition must
16031     * be as described in the property tableau in The Complex Type Definition
16032     * Schema Component ($3.4.1), modulo the impact of Missing
16033     * Sub-components ($5.3)."
16034     */
16035     if ((type->baseType != NULL) &&
16036 	(WXS_IS_SIMPLE(type->baseType)) &&
16037 	(WXS_IS_EXTENSION(type) == 0)) {
16038 	/*
16039 	* SPEC (2) "If the {base type definition} is a simple type definition,
16040 	* the {derivation method} must be extension."
16041 	*/
16042 	xmlSchemaCustomErr(ACTXT_CAST pctxt,
16043 	    XML_SCHEMAP_SRC_CT_1,
16044 	    NULL, WXS_BASIC_CAST type,
16045 	    "If the base type is a simple type, the derivation method must be "
16046 	    "'extension'", NULL, NULL);
16047 	return (XML_SCHEMAP_SRC_CT_1);
16048     }
16049     /*
16050     * SPEC (3) "Circular definitions are disallowed, except for the `ur-type
16051     * definition`. That is, it must be possible to reach the `ur-type
16052     * definition` by repeatedly following the {base type definition}."
16053     *
16054     * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
16055     */
16056     /*
16057     * NOTE that (4) and (5) need the following:
16058     *   - attribute uses need to be already inherited (apply attr. prohibitions)
16059     *   - attribute group references need to be expanded already
16060     *   - simple types need to be typefixed already
16061     */
16062     if (type->attrUses &&
16063 	(((xmlSchemaItemListPtr) type->attrUses)->nbItems > 1))
16064     {
16065 	xmlSchemaItemListPtr uses = (xmlSchemaItemListPtr) type->attrUses;
16066 	xmlSchemaAttributeUsePtr use, tmp;
16067 	int i, j, hasId = 0;
16068 
16069 	for (i = uses->nbItems -1; i >= 0; i--) {
16070 	    use = uses->items[i];
16071 
16072 	    /*
16073 	    * SPEC ct-props-correct
16074 	    * (4) "Two distinct attribute declarations in the
16075 	    * {attribute uses} must not have identical {name}s and
16076 	    * {target namespace}s."
16077 	    */
16078 	    if (i > 0) {
16079 		for (j = i -1; j >= 0; j--) {
16080 		    tmp = uses->items[j];
16081 		    if ((WXS_ATTRUSE_DECL_NAME(use) ==
16082 			WXS_ATTRUSE_DECL_NAME(tmp)) &&
16083 			(WXS_ATTRUSE_DECL_TNS(use) ==
16084 			WXS_ATTRUSE_DECL_TNS(tmp)))
16085 		    {
16086 			xmlChar *str = NULL;
16087 
16088 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
16089 			    XML_SCHEMAP_AG_PROPS_CORRECT,
16090 			    NULL, WXS_BASIC_CAST type,
16091 			    "Duplicate %s",
16092 			    xmlSchemaGetComponentDesignation(&str, use),
16093 			    NULL);
16094 			FREE_AND_NULL(str);
16095 			/*
16096 			* Remove the duplicate.
16097 			*/
16098 			if (xmlSchemaItemListRemove(uses, i) == -1)
16099 			    goto exit_failure;
16100 			goto next_use;
16101 		    }
16102 		}
16103 	    }
16104 	    /*
16105 	    * SPEC ct-props-correct
16106 	    * (5) "Two distinct attribute declarations in the
16107 	    * {attribute uses} must not have {type definition}s which
16108 	    * are or are derived from ID."
16109 	    */
16110 	    if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
16111 		if (xmlSchemaIsDerivedFromBuiltInType(
16112 		    WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
16113 		{
16114 		    if (hasId) {
16115 			xmlChar *str = NULL;
16116 
16117 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
16118 			    XML_SCHEMAP_AG_PROPS_CORRECT,
16119 			    NULL, WXS_BASIC_CAST type,
16120 			    "There must not exist more than one attribute "
16121 			    "declaration of type 'xs:ID' "
16122 			    "(or derived from 'xs:ID'). The %s violates this "
16123 			    "constraint",
16124 			    xmlSchemaGetComponentDesignation(&str, use),
16125 			    NULL);
16126 			FREE_AND_NULL(str);
16127 			if (xmlSchemaItemListRemove(uses, i) == -1)
16128 			    goto exit_failure;
16129 		    }
16130 
16131 		    hasId = 1;
16132 		}
16133 	    }
16134 next_use: {}
16135 	}
16136     }
16137     return (0);
16138 exit_failure:
16139     return(-1);
16140 }
16141 
16142 static int
xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,xmlSchemaTypePtr typeB)16143 xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
16144 		       xmlSchemaTypePtr typeB)
16145 {
16146     /*
16147     * TODO: This should implement component-identity
16148     * in the future.
16149     */
16150     if ((typeA == NULL) || (typeB == NULL))
16151 	return (0);
16152     return (typeA == typeB);
16153 }
16154 
16155 /**
16156  * xmlSchemaCheckCOSCTDerivedOK:
16157  * @ctxt:  the schema parser context
16158  * @type:  the to-be derived complex type definition
16159  * @baseType:  the base complex type definition
16160  * @set: the given set
16161  *
16162  * Schema Component Constraint:
16163  * Type Derivation OK (Complex) (cos-ct-derived-ok)
16164  *
16165  * STATUS: completed
16166  *
16167  * Returns 0 if the constraints are satisfied, or 1
16168  * if not.
16169  */
16170 static int
xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,xmlSchemaTypePtr type,xmlSchemaTypePtr baseType,int set)16171 xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16172 			     xmlSchemaTypePtr type,
16173 			     xmlSchemaTypePtr baseType,
16174 			     int set)
16175 {
16176     int equal = xmlSchemaAreEqualTypes(type, baseType);
16177     /* TODO: Error codes. */
16178     /*
16179     * SPEC "For a complex type definition (call it D, for derived)
16180     * to be validly derived from a type definition (call this
16181     * B, for base) given a subset of {extension, restriction}
16182     * all of the following must be true:"
16183     */
16184     if (! equal) {
16185 	/*
16186 	* SPEC (1) "If B and D are not the same type definition, then the
16187 	* {derivation method} of D must not be in the subset."
16188 	*/
16189 	if (((set & SUBSET_EXTENSION) && (WXS_IS_EXTENSION(type))) ||
16190 	    ((set & SUBSET_RESTRICTION) && (WXS_IS_RESTRICTION(type))))
16191 	    return (1);
16192     } else {
16193 	/*
16194 	* SPEC (2.1) "B and D must be the same type definition."
16195 	*/
16196 	return (0);
16197     }
16198     /*
16199     * SPEC (2.2) "B must be D's {base type definition}."
16200     */
16201     if (type->baseType == baseType)
16202 	return (0);
16203     /*
16204     * SPEC (2.3.1) "D's {base type definition} must not be the `ur-type
16205     * definition`."
16206     */
16207     if (WXS_IS_ANYTYPE(type->baseType))
16208 	return (1);
16209 
16210     if (WXS_IS_COMPLEX(type->baseType)) {
16211 	/*
16212 	* SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
16213 	* must be validly derived from B given the subset as defined by this
16214 	* constraint."
16215 	*/
16216 	return (xmlSchemaCheckCOSCTDerivedOK(actxt, type->baseType,
16217 	    baseType, set));
16218     } else {
16219 	/*
16220 	* SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
16221 	* must be validly derived from B given the subset as defined in Type
16222 	* Derivation OK (Simple) ($3.14.6).
16223 	*/
16224 	return (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
16225 	    baseType, set));
16226     }
16227 }
16228 
16229 /**
16230  * xmlSchemaCheckCOSDerivedOK:
16231  * @type:  the derived simple type definition
16232  * @baseType:  the base type definition
16233  *
16234  * Calls:
16235  * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
16236  *
16237  * Checks whether @type can be validly derived from @baseType.
16238  *
16239  * Returns 0 on success, an positive error code otherwise.
16240  */
16241 static int
xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt,xmlSchemaTypePtr type,xmlSchemaTypePtr baseType,int set)16242 xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16243 			   xmlSchemaTypePtr type,
16244 			   xmlSchemaTypePtr baseType,
16245 			   int set)
16246 {
16247     if (WXS_IS_SIMPLE(type))
16248 	return (xmlSchemaCheckCOSSTDerivedOK(actxt, type, baseType, set));
16249     else
16250 	return (xmlSchemaCheckCOSCTDerivedOK(actxt, type, baseType, set));
16251 }
16252 
16253 /**
16254  * xmlSchemaCheckCOSCTExtends:
16255  * @ctxt:  the schema parser context
16256  * @type:  the complex type definition
16257  *
16258  * (3.4.6) Constraints on Complex Type Definition Schema Components
16259  * Schema Component Constraint:
16260  * Derivation Valid (Extension) (cos-ct-extends)
16261  *
16262  * STATUS:
16263  *   missing:
16264  *     (1.5)
16265  *     (1.4.3.2.2.2) "Particle Valid (Extension)"
16266  *
16267  * Returns 0 if the constraints are satisfied, a positive
16268  * error code if not and -1 if an internal error occurred.
16269  */
16270 static int
xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)16271 xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
16272 			   xmlSchemaTypePtr type)
16273 {
16274     xmlSchemaTypePtr base = type->baseType;
16275     /*
16276     * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
16277     * temporarily only.
16278     */
16279     /*
16280     * SPEC (1) "If the {base type definition} is a complex type definition,
16281     * then all of the following must be true:"
16282     */
16283     if (WXS_IS_COMPLEX(base)) {
16284 	/*
16285 	* SPEC (1.1) "The {final} of the {base type definition} must not
16286 	* contain extension."
16287 	*/
16288 	if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16289 	    xmlSchemaPCustomErr(ctxt,
16290 		XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16291 		WXS_BASIC_CAST type, NULL,
16292 		"The 'final' of the base type definition "
16293 		"contains 'extension'", NULL);
16294 	    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16295 	}
16296 
16297 	/*
16298 	* ATTENTION: The constrains (1.2) and (1.3) are not applied,
16299 	* since they are automatically satisfied through the
16300 	* inheriting mechanism.
16301 	* Note that even if redefining components, the inheriting mechanism
16302 	* is used.
16303 	*/
16304 #if 0
16305 	/*
16306 	* SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
16307 	* uses}
16308 	* of the complex type definition itself, that is, for every attribute
16309 	* use in the {attribute uses} of the {base type definition}, there
16310 	* must be an attribute use in the {attribute uses} of the complex
16311 	* type definition itself whose {attribute declaration} has the same
16312 	* {name}, {target namespace} and {type definition} as its attribute
16313 	* declaration"
16314 	*/
16315 	if (base->attrUses != NULL) {
16316 	    int i, j, found;
16317 	    xmlSchemaAttributeUsePtr use, buse;
16318 
16319 	    for (i = 0; i < (WXS_LIST_CAST base->attrUses)->nbItems; i ++) {
16320 		buse = (WXS_LIST_CAST base->attrUses)->items[i];
16321 		found = 0;
16322 		if (type->attrUses != NULL) {
16323 		    use = (WXS_LIST_CAST type->attrUses)->items[j];
16324 		    for (j = 0; j < (WXS_LIST_CAST type->attrUses)->nbItems; j ++)
16325 		    {
16326 			if ((WXS_ATTRUSE_DECL_NAME(use) ==
16327 				WXS_ATTRUSE_DECL_NAME(buse)) &&
16328 			    (WXS_ATTRUSE_DECL_TNS(use) ==
16329 				WXS_ATTRUSE_DECL_TNS(buse)) &&
16330 			    (WXS_ATTRUSE_TYPEDEF(use) ==
16331 				WXS_ATTRUSE_TYPEDEF(buse))
16332 			{
16333 			    found = 1;
16334 			    break;
16335 			}
16336 		    }
16337 		}
16338 		if (! found) {
16339 		    xmlChar *str = NULL;
16340 
16341 		    xmlSchemaCustomErr(ACTXT_CAST ctxt,
16342 			XML_SCHEMAP_COS_CT_EXTENDS_1_2,
16343 			NULL, WXS_BASIC_CAST type,
16344 			/*
16345 			* TODO: The report does not indicate that also the
16346 			* type needs to be the same.
16347 			*/
16348 			"This type is missing a matching correspondent "
16349 			"for its {base type}'s %s in its {attribute uses}",
16350 			xmlSchemaGetComponentDesignation(&str,
16351 			    buse->children),
16352 			NULL);
16353 		    FREE_AND_NULL(str)
16354 		}
16355 	    }
16356 	}
16357 	/*
16358 	* SPEC (1.3) "If it has an {attribute wildcard}, the complex type
16359 	* definition must also have one, and the base type definition's
16360 	* {attribute  wildcard}'s {namespace constraint} must be a subset
16361 	* of the complex  type definition's {attribute wildcard}'s {namespace
16362 	* constraint}, as defined by Wildcard Subset ($3.10.6)."
16363 	*/
16364 
16365 	/*
16366 	* MAYBE TODO: Enable if ever needed. But this will be needed only
16367 	* if created the type via a schema construction API.
16368 	*/
16369 	if (base->attributeWildcard != NULL) {
16370 	    if (type->attributeWildcard == NULL) {
16371 		xmlChar *str = NULL;
16372 
16373 		xmlSchemaCustomErr(ACTXT_CAST pctxt,
16374 		    XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16375 		    NULL, type,
16376 		    "The base %s has an attribute wildcard, "
16377 		    "but this type is missing an attribute wildcard",
16378 		    xmlSchemaGetComponentDesignation(&str, base));
16379 		FREE_AND_NULL(str)
16380 
16381 	    } else if (xmlSchemaCheckCOSNSSubset(
16382 		base->attributeWildcard, type->attributeWildcard))
16383 	    {
16384 		xmlChar *str = NULL;
16385 
16386 		xmlSchemaCustomErr(ACTXT_CAST pctxt,
16387 		    XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16388 		    NULL, type,
16389 		    "The attribute wildcard is not a valid "
16390 		    "superset of the one in the base %s",
16391 		    xmlSchemaGetComponentDesignation(&str, base));
16392 		FREE_AND_NULL(str)
16393 	    }
16394 	}
16395 #endif
16396 	/*
16397 	* SPEC (1.4) "One of the following must be true:"
16398 	*/
16399 	if ((type->contentTypeDef != NULL) &&
16400 	    (type->contentTypeDef == base->contentTypeDef)) {
16401 	    /*
16402 	    * SPEC (1.4.1) "The {content type} of the {base type definition}
16403 	    * and the {content type} of the complex type definition itself
16404 	    * must be the same simple type definition"
16405 	    * PASS
16406 	    */
16407 	} else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
16408 	    (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
16409 	    /*
16410 	    * SPEC (1.4.2) "The {content type} of both the {base type
16411 	    * definition} and the complex type definition itself must
16412 	    * be empty."
16413 	    * PASS
16414 	    */
16415 	} else {
16416 	    /*
16417 	    * SPEC (1.4.3) "All of the following must be true:"
16418 	    */
16419 	    if (type->subtypes == NULL) {
16420 		/*
16421 		* SPEC 1.4.3.1 The {content type} of the complex type
16422 		* definition itself must specify a particle.
16423 		*/
16424 		xmlSchemaPCustomErr(ctxt,
16425 		    XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16426 		    WXS_BASIC_CAST type, NULL,
16427 		    "The content type must specify a particle", NULL);
16428 		return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16429 	    }
16430 	    /*
16431 	    * SPEC (1.4.3.2) "One of the following must be true:"
16432 	    */
16433 	    if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16434 		/*
16435 		* SPEC (1.4.3.2.1) "The {content type} of the {base type
16436 		* definition} must be empty.
16437 		* PASS
16438 		*/
16439 	    } else {
16440 		/*
16441 		* SPEC (1.4.3.2.2) "All of the following must be true:"
16442 		*/
16443 		if ((type->contentType != base->contentType) ||
16444 		    ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
16445 		    (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
16446 		    /*
16447 		    * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
16448 		    * or both must be element-only."
16449 		    */
16450 		    xmlSchemaPCustomErr(ctxt,
16451 			XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16452 			WXS_BASIC_CAST type, NULL,
16453 			"The content type of both, the type and its base "
16454 			"type, must either 'mixed' or 'element-only'", NULL);
16455 		    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16456 		}
16457 		/*
16458 		* URGENT TODO SPEC (1.4.3.2.2.2) "The particle of the
16459 		* complex type definition must be a `valid extension`
16460 		* of the {base type definition}'s particle, as defined
16461 		* in Particle Valid (Extension) ($3.9.6)."
16462 		*
16463 		* NOTE that we won't check "Particle Valid (Extension)",
16464 		* since it is ensured by the derivation process in
16465 		* xmlSchemaTypeFixup(). We need to implement this when heading
16466 		* for a construction API
16467 		* TODO: !! This is needed to be checked if redefining a type !!
16468 		*/
16469 	    }
16470 	    /*
16471 	    * URGENT TODO (1.5)
16472 	    */
16473 	}
16474     } else {
16475 	/*
16476 	* SPEC (2) "If the {base type definition} is a simple type definition,
16477 	* then all of the following must be true:"
16478 	*/
16479 	if (type->contentTypeDef != base) {
16480 	    /*
16481 	    * SPEC (2.1) "The {content type} must be the same simple type
16482 	    * definition."
16483 	    */
16484 	    xmlSchemaPCustomErr(ctxt,
16485 		XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16486 		WXS_BASIC_CAST type, NULL,
16487 		"The content type must be the simple base type", NULL);
16488 	    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16489 	}
16490 	if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16491 	    /*
16492 	    * SPEC (2.2) "The {final} of the {base type definition} must not
16493 	    * contain extension"
16494 	    * NOTE that this is the same as (1.1).
16495 	    */
16496 	    xmlSchemaPCustomErr(ctxt,
16497 		XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16498 		WXS_BASIC_CAST type, NULL,
16499 		"The 'final' of the base type definition "
16500 		"contains 'extension'", NULL);
16501 	    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16502 	}
16503     }
16504     return (0);
16505 }
16506 
16507 /**
16508  * xmlSchemaCheckDerivationOKRestriction:
16509  * @ctxt:  the schema parser context
16510  * @type:  the complex type definition
16511  *
16512  * (3.4.6) Constraints on Complex Type Definition Schema Components
16513  * Schema Component Constraint:
16514  * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
16515  *
16516  * STATUS:
16517  *   missing:
16518  *     (5.4.2) ???
16519  *
16520  * ATTENTION:
16521  * In XML Schema 1.1 this will be:
16522  * Validation Rule: Checking complex type subsumption
16523  *
16524  * Returns 0 if the constraints are satisfied, a positive
16525  * error code if not and -1 if an internal error occurred.
16526  */
16527 static int
xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)16528 xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
16529 				      xmlSchemaTypePtr type)
16530 {
16531     xmlSchemaTypePtr base;
16532 
16533     /*
16534     * TODO: Correct the error code; XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1 is used
16535     * temporarily only.
16536     */
16537     base = type->baseType;
16538     if (! WXS_IS_COMPLEX(base)) {
16539 	xmlSchemaCustomErr(ACTXT_CAST ctxt,
16540 	    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16541 	    type->node, WXS_BASIC_CAST type,
16542 	    "The base type must be a complex type", NULL, NULL);
16543 	return(ctxt->err);
16544     }
16545     if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
16546 	/*
16547 	* SPEC (1) "The {base type definition} must be a complex type
16548 	* definition whose {final} does not contain restriction."
16549 	*/
16550 	xmlSchemaCustomErr(ACTXT_CAST ctxt,
16551 	    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16552 	    type->node, WXS_BASIC_CAST type,
16553 	    "The 'final' of the base type definition "
16554 	    "contains 'restriction'", NULL, NULL);
16555 	return (ctxt->err);
16556     }
16557     /*
16558     * SPEC (2), (3) and (4)
16559     * Those are handled in a separate function, since the
16560     * same constraints are needed for redefinition of
16561     * attribute groups as well.
16562     */
16563     if (xmlSchemaCheckDerivationOKRestriction2to4(ctxt,
16564 	XML_SCHEMA_ACTION_DERIVE,
16565 	WXS_BASIC_CAST type, WXS_BASIC_CAST base,
16566 	type->attrUses, base->attrUses,
16567 	type->attributeWildcard,
16568 	base->attributeWildcard) == -1)
16569     {
16570 	return(-1);
16571     }
16572     /*
16573     * SPEC (5) "One of the following must be true:"
16574     */
16575     if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
16576 	/*
16577 	* SPEC (5.1) "The {base type definition} must be the
16578 	* `ur-type definition`."
16579 	* PASS
16580 	*/
16581     } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16582 	    (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16583 	/*
16584 	* SPEC (5.2.1) "The {content type} of the complex type definition
16585 	* must be a simple type definition"
16586 	*
16587 	* SPEC (5.2.2) "One of the following must be true:"
16588 	*/
16589 	if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16590 	    (base->contentType == XML_SCHEMA_CONTENT_BASIC))
16591 	{
16592 	    int err;
16593 	    /*
16594 	    * SPEC (5.2.2.1) "The {content type} of the {base type
16595 	    * definition} must be a simple type definition from which
16596 	    * the {content type} is validly derived given the empty
16597 	    * set as defined in Type Derivation OK (Simple) ($3.14.6)."
16598 	    *
16599 	    * ATTENTION TODO: This seems not needed if the type implicitly
16600 	    * derived from the base type.
16601 	    *
16602 	    */
16603 	    err = xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST ctxt,
16604 		type->contentTypeDef, base->contentTypeDef, 0);
16605 	    if (err != 0) {
16606 		xmlChar *strA = NULL, *strB = NULL;
16607 
16608 		if (err == -1)
16609 		    return(-1);
16610 		xmlSchemaCustomErr(ACTXT_CAST ctxt,
16611 		    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16612 		    NULL, WXS_BASIC_CAST type,
16613 		    "The {content type} %s is not validly derived from the "
16614 		    "base type's {content type} %s",
16615 		    xmlSchemaGetComponentDesignation(&strA,
16616 			type->contentTypeDef),
16617 		    xmlSchemaGetComponentDesignation(&strB,
16618 			base->contentTypeDef));
16619 		FREE_AND_NULL(strA);
16620 		FREE_AND_NULL(strB);
16621 		return(ctxt->err);
16622 	    }
16623 	} else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16624 	    (xmlSchemaIsParticleEmptiable(
16625 		(xmlSchemaParticlePtr) base->subtypes))) {
16626 	    /*
16627 	    * SPEC (5.2.2.2) "The {base type definition} must be mixed
16628 	    * and have a particle which is `emptiable` as defined in
16629 	    * Particle Emptiable ($3.9.6)."
16630 	    * PASS
16631 	    */
16632 	} else {
16633 	    xmlSchemaPCustomErr(ctxt,
16634 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16635 		WXS_BASIC_CAST type, NULL,
16636 		"The content type of the base type must be either "
16637 		"a simple type or 'mixed' and an emptiable particle", NULL);
16638 	    return (ctxt->err);
16639 	}
16640     } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16641 	/*
16642 	* SPEC (5.3.1) "The {content type} of the complex type itself must
16643 	* be empty"
16644 	*/
16645 	if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16646 	    /*
16647 	    * SPEC (5.3.2.1) "The {content type} of the {base type
16648 	    * definition} must also be empty."
16649 	    * PASS
16650 	    */
16651 	} else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16652 	    (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
16653 	    xmlSchemaIsParticleEmptiable(
16654 		(xmlSchemaParticlePtr) base->subtypes)) {
16655 	    /*
16656 	    * SPEC (5.3.2.2) "The {content type} of the {base type
16657 	    * definition} must be elementOnly or mixed and have a particle
16658 	    * which is `emptiable` as defined in Particle Emptiable ($3.9.6)."
16659 	    * PASS
16660 	    */
16661 	} else {
16662 	    xmlSchemaPCustomErr(ctxt,
16663 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16664 		WXS_BASIC_CAST type, NULL,
16665 		"The content type of the base type must be either "
16666 		"empty or 'mixed' (or 'elements-only') and an emptiable "
16667 		"particle", NULL);
16668 	    return (ctxt->err);
16669 	}
16670     } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16671 	WXS_HAS_MIXED_CONTENT(type)) {
16672 	/*
16673 	* SPEC (5.4.1.1) "The {content type} of the complex type definition
16674 	* itself must be element-only"
16675 	*/
16676 	if (WXS_HAS_MIXED_CONTENT(type) && (! WXS_HAS_MIXED_CONTENT(base))) {
16677 	    /*
16678 	    * SPEC (5.4.1.2) "The {content type} of the complex type
16679 	    * definition itself and of the {base type definition} must be
16680 	    * mixed"
16681 	    */
16682 	    xmlSchemaPCustomErr(ctxt,
16683 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16684 		WXS_BASIC_CAST type, NULL,
16685 		"If the content type is 'mixed', then the content type of the "
16686 		"base type must also be 'mixed'", NULL);
16687 	    return (ctxt->err);
16688 	}
16689 	/*
16690 	* SPEC (5.4.2) "The particle of the complex type definition itself
16691 	* must be a `valid restriction` of the particle of the {content
16692 	* type} of the {base type definition} as defined in Particle Valid
16693 	* (Restriction) ($3.9.6).
16694 	*
16695 	* URGENT TODO: (5.4.2)
16696 	*/
16697     } else {
16698 	xmlSchemaPCustomErr(ctxt,
16699 	    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16700 	    WXS_BASIC_CAST type, NULL,
16701 	    "The type is not a valid restriction of its base type", NULL);
16702 	return (ctxt->err);
16703     }
16704     return (0);
16705 }
16706 
16707 /**
16708  * xmlSchemaCheckCTComponent:
16709  * @ctxt:  the schema parser context
16710  * @type:  the complex type definition
16711  *
16712  * (3.4.6) Constraints on Complex Type Definition Schema Components
16713  *
16714  * Returns 0 if the constraints are satisfied, a positive
16715  * error code if not and -1 if an internal error occurred.
16716  */
16717 static int
xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)16718 xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
16719 			  xmlSchemaTypePtr type)
16720 {
16721     int ret;
16722     /*
16723     * Complex Type Definition Properties Correct
16724     */
16725     ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
16726     if (ret != 0)
16727 	return (ret);
16728     if (WXS_IS_EXTENSION(type))
16729 	ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
16730     else
16731 	ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
16732     return (ret);
16733 }
16734 
16735 /**
16736  * xmlSchemaCheckSRCCT:
16737  * @ctxt:  the schema parser context
16738  * @type:  the complex type definition
16739  *
16740  * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
16741  * Schema Representation Constraint:
16742  * Complex Type Definition Representation OK (src-ct)
16743  *
16744  * Returns 0 if the constraints are satisfied, a positive
16745  * error code if not and -1 if an internal error occurred.
16746  */
16747 static int
xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)16748 xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
16749 		    xmlSchemaTypePtr type)
16750 {
16751     xmlSchemaTypePtr base;
16752     int ret = 0;
16753 
16754     /*
16755     * TODO: Adjust the error codes here, as I used
16756     * XML_SCHEMAP_SRC_CT_1 only yet.
16757     */
16758     base = type->baseType;
16759     if (! WXS_HAS_SIMPLE_CONTENT(type)) {
16760 	/*
16761 	* 1 If the <complexContent> alternative is chosen, the type definition
16762 	* `resolved` to by the `actual value` of the base [attribute]
16763 	* must be a complex type definition;
16764 	*/
16765 	if (! WXS_IS_COMPLEX(base)) {
16766 	    xmlChar *str = NULL;
16767 	    xmlSchemaPCustomErr(ctxt,
16768 		XML_SCHEMAP_SRC_CT_1,
16769 		WXS_BASIC_CAST type, type->node,
16770 		"If using <complexContent>, the base type is expected to be "
16771 		"a complex type. The base type '%s' is a simple type",
16772 		xmlSchemaFormatQName(&str, base->targetNamespace,
16773 		base->name));
16774 	    FREE_AND_NULL(str)
16775 	    return (XML_SCHEMAP_SRC_CT_1);
16776 	}
16777     } else {
16778 	/*
16779 	* SPEC
16780 	* 2 If the <simpleContent> alternative is chosen, all of the
16781 	* following must be true:
16782 	* 2.1 The type definition `resolved` to by the `actual value` of the
16783 	* base [attribute] must be one of the following:
16784 	*/
16785 	if (WXS_IS_SIMPLE(base)) {
16786 	    if (WXS_IS_EXTENSION(type) == 0) {
16787 		xmlChar *str = NULL;
16788 		/*
16789 		* 2.1.3 only if the <extension> alternative is also
16790 		* chosen, a simple type definition.
16791 		*/
16792 		/* TODO: Change error code to ..._SRC_CT_2_1_3. */
16793 		xmlSchemaPCustomErr(ctxt,
16794 		    XML_SCHEMAP_SRC_CT_1,
16795 		    WXS_BASIC_CAST type, NULL,
16796 		    "If using <simpleContent> and <restriction>, the base "
16797 		    "type must be a complex type. The base type '%s' is "
16798 		    "a simple type",
16799 		    xmlSchemaFormatQName(&str, base->targetNamespace,
16800 			base->name));
16801 		FREE_AND_NULL(str)
16802 		return (XML_SCHEMAP_SRC_CT_1);
16803 	    }
16804 	} else {
16805 	    /* Base type is a complex type. */
16806 	    if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16807 		(base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16808 		/*
16809 		* 2.1.1 a complex type definition whose {content type} is a
16810 		* simple type definition;
16811 		* PASS
16812 		*/
16813 		if (base->contentTypeDef == NULL) {
16814 		    xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
16815 			WXS_BASIC_CAST type, NULL,
16816 			"Internal error: xmlSchemaCheckSRCCT, "
16817 			"'%s', base type has no content type",
16818 			type->name);
16819 		    return (-1);
16820 		}
16821 	    } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16822 		(WXS_IS_RESTRICTION(type))) {
16823 
16824 		/*
16825 		* 2.1.2 only if the <restriction> alternative is also
16826 		* chosen, a complex type definition whose {content type}
16827 		* is mixed and a particle emptiable.
16828 		*/
16829 		if (! xmlSchemaIsParticleEmptiable(
16830 		    (xmlSchemaParticlePtr) base->subtypes)) {
16831 		    ret = XML_SCHEMAP_SRC_CT_1;
16832 		} else
16833 		    /*
16834 		    * Attention: at this point the <simpleType> child is in
16835 		    * ->contentTypeDef (put there during parsing).
16836 		    */
16837 		    if (type->contentTypeDef == NULL) {
16838 		    xmlChar *str = NULL;
16839 		    /*
16840 		    * 2.2 If clause 2.1.2 above is satisfied, then there
16841 		    * must be a <simpleType> among the [children] of
16842 		    * <restriction>.
16843 		    */
16844 		    /* TODO: Change error code to ..._SRC_CT_2_2. */
16845 		    xmlSchemaPCustomErr(ctxt,
16846 			XML_SCHEMAP_SRC_CT_1,
16847 			WXS_BASIC_CAST type, NULL,
16848 			"A <simpleType> is expected among the children "
16849 			"of <restriction>, if <simpleContent> is used and "
16850 			"the base type '%s' is a complex type",
16851 			xmlSchemaFormatQName(&str, base->targetNamespace,
16852 			base->name));
16853 		    FREE_AND_NULL(str)
16854 		    return (XML_SCHEMAP_SRC_CT_1);
16855 		}
16856 	    } else {
16857 		ret = XML_SCHEMAP_SRC_CT_1;
16858 	    }
16859 	}
16860 	if (ret > 0) {
16861 	    xmlChar *str = NULL;
16862 	    if (WXS_IS_RESTRICTION(type)) {
16863 		xmlSchemaPCustomErr(ctxt,
16864 		    XML_SCHEMAP_SRC_CT_1,
16865 		    WXS_BASIC_CAST type, NULL,
16866 		    "If <simpleContent> and <restriction> is used, the "
16867 		    "base type must be a simple type or a complex type with "
16868 		    "mixed content and particle emptiable. The base type "
16869 		    "'%s' is none of those",
16870 		    xmlSchemaFormatQName(&str, base->targetNamespace,
16871 		    base->name));
16872 	    } else {
16873 		xmlSchemaPCustomErr(ctxt,
16874 		    XML_SCHEMAP_SRC_CT_1,
16875 		    WXS_BASIC_CAST type, NULL,
16876 		    "If <simpleContent> and <extension> is used, the "
16877 		    "base type must be a simple type. The base type '%s' "
16878 		    "is a complex type",
16879 		    xmlSchemaFormatQName(&str, base->targetNamespace,
16880 		    base->name));
16881 	    }
16882 	    FREE_AND_NULL(str)
16883 	}
16884     }
16885     /*
16886     * SPEC (3) "The corresponding complex type definition component must
16887     * satisfy the conditions set out in Constraints on Complex Type
16888     * Definition Schema Components ($3.4.6);"
16889     * NOTE (3) will be done in xmlSchemaTypeFixup().
16890     */
16891     /*
16892     * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
16893     * above for {attribute wildcard} is satisfied, the intensional
16894     * intersection must be expressible, as defined in Attribute Wildcard
16895     * Intersection ($3.10.6).
16896     * NOTE (4) is done in xmlSchemaFixupTypeAttributeUses().
16897     */
16898     return (ret);
16899 }
16900 
16901 #ifdef ENABLE_PARTICLE_RESTRICTION
16902 /**
16903  * xmlSchemaCheckParticleRangeOK:
16904  * @ctxt:  the schema parser context
16905  * @type:  the complex type definition
16906  *
16907  * (3.9.6) Constraints on Particle Schema Components
16908  * Schema Component Constraint:
16909  * Occurrence Range OK (range-ok)
16910  *
16911  * STATUS: complete
16912  *
16913  * Returns 0 if the constraints are satisfied, a positive
16914  * error code if not and -1 if an internal error occurred.
16915  */
16916 static int
xmlSchemaCheckParticleRangeOK(int rmin,int rmax,int bmin,int bmax)16917 xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
16918 			      int bmin, int bmax)
16919 {
16920     if (rmin < bmin)
16921 	return (1);
16922     if ((bmax != UNBOUNDED) &&
16923 	(rmax > bmax))
16924 	return (1);
16925     return (0);
16926 }
16927 
16928 /**
16929  * xmlSchemaCheckRCaseNameAndTypeOK:
16930  * @ctxt:  the schema parser context
16931  * @r: the restricting element declaration particle
16932  * @b: the base element declaration particle
16933  *
16934  * (3.9.6) Constraints on Particle Schema Components
16935  * Schema Component Constraint:
16936  * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
16937  * (rcase-NameAndTypeOK)
16938  *
16939  * STATUS:
16940  *   MISSING (3.2.3)
16941  *   CLARIFY: (3.2.2)
16942  *
16943  * Returns 0 if the constraints are satisfied, a positive
16944  * error code if not and -1 if an internal error occurred.
16945  */
16946 static int
xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)16947 xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
16948 				 xmlSchemaParticlePtr r,
16949 				 xmlSchemaParticlePtr b)
16950 {
16951     xmlSchemaElementPtr elemR, elemB;
16952 
16953     /* TODO: Error codes (rcase-NameAndTypeOK). */
16954     elemR = (xmlSchemaElementPtr) r->children;
16955     elemB = (xmlSchemaElementPtr) b->children;
16956     /*
16957     * SPEC (1) "The declarations' {name}s and {target namespace}s are
16958     * the same."
16959     */
16960     if ((elemR != elemB) &&
16961 	((! xmlStrEqual(elemR->name, elemB->name)) ||
16962 	(! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
16963 	return (1);
16964     /*
16965     * SPEC (2) "R's occurrence range is a valid restriction of B's
16966     * occurrence range as defined by Occurrence Range OK ($3.9.6)."
16967     */
16968     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16969 	    b->minOccurs, b->maxOccurs) != 0)
16970 	return (1);
16971     /*
16972     * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
16973     * {scope} are global."
16974     */
16975     if (elemR == elemB)
16976 	return (0);
16977     /*
16978     * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
16979     */
16980     if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
16981 	(elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
16982 	 return (1);
16983     /*
16984     * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
16985     * or is not fixed, or R's declaration's {value constraint} is fixed
16986     * with the same value."
16987     */
16988     if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
16989 	((elemR->value == NULL) ||
16990 	 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
16991 	 /* TODO: Equality of the initial value or normalized or canonical? */
16992 	 (! xmlStrEqual(elemR->value, elemB->value))))
16993 	 return (1);
16994     /*
16995     * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
16996     * definitions} is a subset of B's declaration's {identity-constraint
16997     * definitions}, if any."
16998     */
16999     if (elemB->idcs != NULL) {
17000 	/* TODO */
17001     }
17002     /*
17003     * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
17004     * superset of B's declaration's {disallowed substitutions}."
17005     */
17006     if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
17007 	 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
17008 	((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
17009 	 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
17010 	((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
17011 	 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
17012 	 return (1);
17013     /*
17014     * SPEC (3.2.5) "R's {type definition} is validly derived given
17015     * {extension, list, union} from B's {type definition}"
17016     *
17017     * BADSPEC TODO: What's the point of adding "list" and "union" to the
17018     * set, if the corresponding constraints handle "restriction" and
17019     * "extension" only?
17020     *
17021     */
17022     {
17023 	int set = 0;
17024 
17025 	set |= SUBSET_EXTENSION;
17026 	set |= SUBSET_LIST;
17027 	set |= SUBSET_UNION;
17028 	if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST ctxt, elemR->subtypes,
17029 	    elemB->subtypes, set) != 0)
17030 	    return (1);
17031     }
17032     return (0);
17033 }
17034 
17035 /**
17036  * xmlSchemaCheckRCaseNSCompat:
17037  * @ctxt:  the schema parser context
17038  * @r: the restricting element declaration particle
17039  * @b: the base wildcard particle
17040  *
17041  * (3.9.6) Constraints on Particle Schema Components
17042  * Schema Component Constraint:
17043  * Particle Derivation OK (Elt:Any -- NSCompat)
17044  * (rcase-NSCompat)
17045  *
17046  * STATUS: complete
17047  *
17048  * Returns 0 if the constraints are satisfied, a positive
17049  * error code if not and -1 if an internal error occurred.
17050  */
17051 static int
xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)17052 xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
17053 			    xmlSchemaParticlePtr r,
17054 			    xmlSchemaParticlePtr b)
17055 {
17056     /* TODO:Error codes (rcase-NSCompat). */
17057     /*
17058     * SPEC "For an element declaration particle to be a `valid restriction`
17059     * of a wildcard particle all of the following must be true:"
17060     *
17061     * SPEC (1) "The element declaration's {target namespace} is `valid`
17062     * with respect to the wildcard's {namespace constraint} as defined by
17063     * Wildcard allows Namespace Name ($3.10.4)."
17064     */
17065     if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
17066 	((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
17067 	return (1);
17068     /*
17069     * SPEC (2) "R's occurrence range is a valid restriction of B's
17070     * occurrence range as defined by Occurrence Range OK ($3.9.6)."
17071     */
17072     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17073 	    b->minOccurs, b->maxOccurs) != 0)
17074 	return (1);
17075 
17076     return (0);
17077 }
17078 
17079 /**
17080  * xmlSchemaCheckRCaseRecurseAsIfGroup:
17081  * @ctxt:  the schema parser context
17082  * @r: the restricting element declaration particle
17083  * @b: the base model group particle
17084  *
17085  * (3.9.6) Constraints on Particle Schema Components
17086  * Schema Component Constraint:
17087  * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
17088  * (rcase-RecurseAsIfGroup)
17089  *
17090  * STATUS: TODO
17091  *
17092  * Returns 0 if the constraints are satisfied, a positive
17093  * error code if not and -1 if an internal error occurred.
17094  */
17095 static int
xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)17096 xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
17097 				    xmlSchemaParticlePtr r,
17098 				    xmlSchemaParticlePtr b)
17099 {
17100     /* TODO: Error codes (rcase-RecurseAsIfGroup). */
17101     TODO
17102     return (0);
17103 }
17104 
17105 /**
17106  * xmlSchemaCheckRCaseNSSubset:
17107  * @ctxt:  the schema parser context
17108  * @r: the restricting wildcard particle
17109  * @b: the base wildcard particle
17110  *
17111  * (3.9.6) Constraints on Particle Schema Components
17112  * Schema Component Constraint:
17113  * Particle Derivation OK (Any:Any -- NSSubset)
17114  * (rcase-NSSubset)
17115  *
17116  * STATUS: complete
17117  *
17118  * Returns 0 if the constraints are satisfied, a positive
17119  * error code if not and -1 if an internal error occurred.
17120  */
17121 static int
xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b,int isAnyTypeBase)17122 xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
17123 				    xmlSchemaParticlePtr r,
17124 				    xmlSchemaParticlePtr b,
17125 				    int isAnyTypeBase)
17126 {
17127     /* TODO: Error codes (rcase-NSSubset). */
17128     /*
17129     * SPEC (1) "R's occurrence range is a valid restriction of B's
17130     * occurrence range as defined by Occurrence Range OK ($3.9.6)."
17131     */
17132     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17133 	    b->minOccurs, b->maxOccurs))
17134 	return (1);
17135     /*
17136     * SPEC (2) "R's {namespace constraint} must be an intensional subset
17137     * of B's {namespace constraint} as defined by Wildcard Subset ($3.10.6)."
17138     */
17139     if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
17140 	(xmlSchemaWildcardPtr) b->children))
17141 	return (1);
17142     /*
17143     * SPEC (3) "Unless B is the content model wildcard of the `ur-type
17144     * definition`, R's {process contents} must be identical to or stronger
17145     * than B's {process contents}, where strict is stronger than lax is
17146     * stronger than skip."
17147     */
17148     if (! isAnyTypeBase) {
17149 	if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
17150 	    ((xmlSchemaWildcardPtr) b->children)->processContents)
17151 	    return (1);
17152     }
17153 
17154     return (0);
17155 }
17156 
17157 /**
17158  * xmlSchemaCheckCOSParticleRestrict:
17159  * @ctxt:  the schema parser context
17160  * @type:  the complex type definition
17161  *
17162  * (3.9.6) Constraints on Particle Schema Components
17163  * Schema Component Constraint:
17164  * Particle Valid (Restriction) (cos-particle-restrict)
17165  *
17166  * STATUS: TODO
17167  *
17168  * Returns 0 if the constraints are satisfied, a positive
17169  * error code if not and -1 if an internal error occurred.
17170  */
17171 static int
xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)17172 xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
17173 				  xmlSchemaParticlePtr r,
17174 				  xmlSchemaParticlePtr b)
17175 {
17176     int ret = 0;
17177 
17178     /*part = WXS_TYPE_PARTICLE(type);
17179     basePart = WXS_TYPE_PARTICLE(base);
17180     */
17181 
17182     TODO
17183 
17184     /*
17185     * SPEC (1) "They are the same particle."
17186     */
17187     if (r == b)
17188 	return (0);
17189 
17190 
17191     return (0);
17192 }
17193 
17194 #if 0
17195 /**
17196  * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
17197  * @ctxt:  the schema parser context
17198  * @r: the model group particle
17199  * @b: the base wildcard particle
17200  *
17201  * (3.9.6) Constraints on Particle Schema Components
17202  * Schema Component Constraint:
17203  * Particle Derivation OK (All/Choice/Sequence:Any --
17204  *                         NSRecurseCheckCardinality)
17205  * (rcase-NSRecurseCheckCardinality)
17206  *
17207  * STATUS: TODO: subst-groups
17208  *
17209  * Returns 0 if the constraints are satisfied, a positive
17210  * error code if not and -1 if an internal error occurred.
17211  */
17212 static int
17213 xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
17214 					     xmlSchemaParticlePtr r,
17215 					     xmlSchemaParticlePtr b)
17216 {
17217     xmlSchemaParticlePtr part;
17218     /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
17219     if ((r->children == NULL) || (r->children->children == NULL))
17220 	return (-1);
17221     /*
17222     * SPEC "For a group particle to be a `valid restriction` of a
17223     * wildcard particle..."
17224     *
17225     * SPEC (1) "Every member of the {particles} of the group is a `valid
17226     * restriction` of the wildcard as defined by
17227     * Particle Valid (Restriction) ($3.9.6)."
17228     */
17229     part = (xmlSchemaParticlePtr) r->children->children;
17230     do {
17231 	if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
17232 	    return (1);
17233 	part = (xmlSchemaParticlePtr) part->next;
17234     } while (part != NULL);
17235     /*
17236     * SPEC (2) "The effective total range of the group [...] is a
17237     * valid restriction of B's occurrence range as defined by
17238     * Occurrence Range OK ($3.9.6)."
17239     */
17240     if (xmlSchemaCheckParticleRangeOK(
17241 	    xmlSchemaGetParticleTotalRangeMin(r),
17242 	    xmlSchemaGetParticleTotalRangeMax(r),
17243 	    b->minOccurs, b->maxOccurs) != 0)
17244 	return (1);
17245     return (0);
17246 }
17247 #endif
17248 
17249 /**
17250  * xmlSchemaCheckRCaseRecurse:
17251  * @ctxt:  the schema parser context
17252  * @r: the <all> or <sequence> model group particle
17253  * @b: the base <all> or <sequence> model group particle
17254  *
17255  * (3.9.6) Constraints on Particle Schema Components
17256  * Schema Component Constraint:
17257  * Particle Derivation OK (All:All,Sequence:Sequence --
17258                            Recurse)
17259  * (rcase-Recurse)
17260  *
17261  * STATUS:  ?
17262  * TODO: subst-groups
17263  *
17264  * Returns 0 if the constraints are satisfied, a positive
17265  * error code if not and -1 if an internal error occurred.
17266  */
17267 static int
xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)17268 xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
17269 			   xmlSchemaParticlePtr r,
17270 			   xmlSchemaParticlePtr b)
17271 {
17272     /* xmlSchemaParticlePtr part; */
17273     /* TODO: Error codes (rcase-Recurse). */
17274     if ((r->children == NULL) || (b->children == NULL) ||
17275 	(r->children->type != b->children->type))
17276 	return (-1);
17277     /*
17278     * SPEC "For an all or sequence group particle to be a `valid
17279     * restriction` of another group particle with the same {compositor}..."
17280     *
17281     * SPEC (1) "R's occurrence range is a valid restriction of B's
17282     * occurrence range as defined by Occurrence Range OK ($3.9.6)."
17283     */
17284     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17285 	    b->minOccurs, b->maxOccurs))
17286 	return (1);
17287 
17288 
17289     return (0);
17290 }
17291 
17292 #endif
17293 
17294 #define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
17295     xmlSchemaPCustomErrExt(pctxt,      \
17296 	XML_SCHEMAP_INVALID_FACET_VALUE, \
17297 	WXS_BASIC_CAST fac1, fac1->node, \
17298 	"It is an error for both '%s' and '%s' to be specified on the "\
17299 	"same type definition", \
17300 	BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
17301 	BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
17302 
17303 #define FACET_RESTR_ERR(fac1, msg) \
17304     xmlSchemaPCustomErr(pctxt,      \
17305 	XML_SCHEMAP_INVALID_FACET_VALUE, \
17306 	WXS_BASIC_CAST fac1, fac1->node, \
17307 	msg, NULL);
17308 
17309 #define FACET_RESTR_FIXED_ERR(fac) \
17310     xmlSchemaPCustomErr(pctxt, \
17311 	XML_SCHEMAP_INVALID_FACET_VALUE, \
17312 	WXS_BASIC_CAST fac, fac->node, \
17313 	"The base type's facet is 'fixed', thus the value must not " \
17314 	"differ", NULL);
17315 
17316 static void
xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,xmlSchemaFacetPtr facet1,xmlSchemaFacetPtr facet2,int lessGreater,int orEqual,int ofBase)17317 xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
17318 			xmlSchemaFacetPtr facet1,
17319 			xmlSchemaFacetPtr facet2,
17320 			int lessGreater,
17321 			int orEqual,
17322 			int ofBase)
17323 {
17324     xmlChar *msg = NULL;
17325 
17326     msg = xmlStrdup(BAD_CAST "'");
17327     msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
17328     msg = xmlStrcat(msg, BAD_CAST "' has to be");
17329     if (lessGreater == 0)
17330 	msg = xmlStrcat(msg, BAD_CAST " equal to");
17331     if (lessGreater == 1)
17332 	msg = xmlStrcat(msg, BAD_CAST " greater than");
17333     else
17334 	msg = xmlStrcat(msg, BAD_CAST " less than");
17335 
17336     if (orEqual)
17337 	msg = xmlStrcat(msg, BAD_CAST " or equal to");
17338     msg = xmlStrcat(msg, BAD_CAST " '");
17339     msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
17340     if (ofBase)
17341 	msg = xmlStrcat(msg, BAD_CAST "' of the base type");
17342     else
17343 	msg = xmlStrcat(msg, BAD_CAST "'");
17344 
17345     xmlSchemaPCustomErr(pctxt,
17346 	XML_SCHEMAP_INVALID_FACET_VALUE,
17347 	WXS_BASIC_CAST facet1, NULL,
17348 	(const char *) msg, NULL);
17349 
17350     if (msg != NULL)
17351 	xmlFree(msg);
17352 }
17353 
17354 /*
17355 * xmlSchemaDeriveAndValidateFacets:
17356 *
17357 * Schema Component Constraint: Simple Type Restriction (Facets)
17358 * (st-restrict-facets)
17359 */
17360 static int
xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)17361 xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
17362 				 xmlSchemaTypePtr type)
17363 {
17364     xmlSchemaTypePtr base = type->baseType;
17365     xmlSchemaFacetLinkPtr link, cur, last = NULL;
17366     xmlSchemaFacetPtr facet, bfacet,
17367 	flength = NULL, ftotdig = NULL, ffracdig = NULL,
17368 	fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
17369 	fmininc = NULL, fmaxinc = NULL,
17370 	fminexc = NULL, fmaxexc = NULL,
17371 	bflength = NULL, bftotdig = NULL, bffracdig = NULL,
17372 	bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
17373 	bfmininc = NULL, bfmaxinc = NULL,
17374 	bfminexc = NULL, bfmaxexc = NULL;
17375     int res; /* err = 0, fixedErr; */
17376 
17377     /*
17378     * SPEC st-restrict-facets 1:
17379     * "The {variety} of R is the same as that of B."
17380     */
17381     /*
17382     * SPEC st-restrict-facets 2:
17383     * "If {variety} is atomic, the {primitive type definition}
17384     * of R is the same as that of B."
17385     *
17386     * NOTE: we leave 1 & 2 out for now, since this will be
17387     * satisfied by the derivation process.
17388     * CONSTRUCTION TODO: Maybe needed if using a construction API.
17389     */
17390     /*
17391     * SPEC st-restrict-facets 3:
17392     * "The {facets} of R are the union of S and the {facets}
17393     * of B, eliminating duplicates. To eliminate duplicates,
17394     * when a facet of the same kind occurs in both S and the
17395     * {facets} of B, the one in the {facets} of B is not
17396     * included, with the exception of enumeration and pattern
17397     * facets, for which multiple occurrences with distinct values
17398     * are allowed."
17399     */
17400 
17401     if ((type->facetSet == NULL) && (base->facetSet == NULL))
17402 	return (0);
17403 
17404     last = type->facetSet;
17405     if (last != NULL)
17406 	while (last->next != NULL)
17407 	    last = last->next;
17408 
17409     for (cur = type->facetSet; cur != NULL; cur = cur->next) {
17410 	facet = cur->facet;
17411 	switch (facet->type) {
17412 	    case XML_SCHEMA_FACET_LENGTH:
17413 		flength = facet; break;
17414 	    case XML_SCHEMA_FACET_MINLENGTH:
17415 		fminlen = facet; break;
17416 	    case XML_SCHEMA_FACET_MININCLUSIVE:
17417 		fmininc = facet; break;
17418 	    case XML_SCHEMA_FACET_MINEXCLUSIVE:
17419 		fminexc = facet; break;
17420 	    case XML_SCHEMA_FACET_MAXLENGTH:
17421 		fmaxlen = facet; break;
17422 	    case XML_SCHEMA_FACET_MAXINCLUSIVE:
17423 		fmaxinc = facet; break;
17424 	    case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17425 		fmaxexc = facet; break;
17426 	    case XML_SCHEMA_FACET_TOTALDIGITS:
17427 		ftotdig = facet; break;
17428 	    case XML_SCHEMA_FACET_FRACTIONDIGITS:
17429 		ffracdig = facet; break;
17430 	    default:
17431 		break;
17432 	}
17433     }
17434     for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17435 	facet = cur->facet;
17436 	switch (facet->type) {
17437 	    case XML_SCHEMA_FACET_LENGTH:
17438 		bflength = facet; break;
17439 	    case XML_SCHEMA_FACET_MINLENGTH:
17440 		bfminlen = facet; break;
17441 	    case XML_SCHEMA_FACET_MININCLUSIVE:
17442 		bfmininc = facet; break;
17443 	    case XML_SCHEMA_FACET_MINEXCLUSIVE:
17444 		bfminexc = facet; break;
17445 	    case XML_SCHEMA_FACET_MAXLENGTH:
17446 		bfmaxlen = facet; break;
17447 	    case XML_SCHEMA_FACET_MAXINCLUSIVE:
17448 		bfmaxinc = facet; break;
17449 	    case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17450 		bfmaxexc = facet; break;
17451 	    case XML_SCHEMA_FACET_TOTALDIGITS:
17452 		bftotdig = facet; break;
17453 	    case XML_SCHEMA_FACET_FRACTIONDIGITS:
17454 		bffracdig = facet; break;
17455 	    default:
17456 		break;
17457 	}
17458     }
17459     /*
17460     * length and minLength or maxLength (2.2) + (3.2)
17461     */
17462     if (flength && (fminlen || fmaxlen)) {
17463 	FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
17464 	    "either of 'minLength' or 'maxLength' to be specified on "
17465 	    "the same type definition")
17466     }
17467     /*
17468     * Mutual exclusions in the same derivation step.
17469     */
17470     if ((fmaxinc) && (fmaxexc)) {
17471 	/*
17472 	* SCC "maxInclusive and maxExclusive"
17473 	*/
17474 	FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
17475     }
17476     if ((fmininc) && (fminexc)) {
17477 	/*
17478 	* SCC "minInclusive and minExclusive"
17479 	*/
17480 	FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
17481     }
17482 
17483     if (flength && bflength) {
17484 	/*
17485 	* SCC "length valid restriction"
17486 	* The values have to be equal.
17487 	*/
17488 	res = xmlSchemaCompareValues(flength->val, bflength->val);
17489 	if (res == -2)
17490 	    goto internal_error;
17491 	if (res != 0)
17492 	    xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
17493 	if ((res != 0) && (bflength->fixed)) {
17494 	    FACET_RESTR_FIXED_ERR(flength)
17495 	}
17496 
17497     }
17498     if (fminlen && bfminlen) {
17499 	/*
17500 	* SCC "minLength valid restriction"
17501 	* minLength >= BASE minLength
17502 	*/
17503 	res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
17504 	if (res == -2)
17505 	    goto internal_error;
17506 	if (res == -1)
17507 	    xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
17508 	if ((res != 0) && (bfminlen->fixed)) {
17509 	    FACET_RESTR_FIXED_ERR(fminlen)
17510 	}
17511     }
17512     if (fmaxlen && bfmaxlen) {
17513 	/*
17514 	* SCC "maxLength valid restriction"
17515 	* maxLength <= BASE minLength
17516 	*/
17517 	res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
17518 	if (res == -2)
17519 	    goto internal_error;
17520 	if (res == 1)
17521 	    xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
17522 	if ((res != 0) && (bfmaxlen->fixed)) {
17523 	    FACET_RESTR_FIXED_ERR(fmaxlen)
17524 	}
17525     }
17526     /*
17527     * SCC "length and minLength or maxLength"
17528     */
17529     if (! flength)
17530 	flength = bflength;
17531     if (flength) {
17532 	if (! fminlen)
17533 	    fminlen = bfminlen;
17534 	if (fminlen) {
17535 	    /* (1.1) length >= minLength */
17536 	    res = xmlSchemaCompareValues(flength->val, fminlen->val);
17537 	    if (res == -2)
17538 		goto internal_error;
17539 	    if (res == -1)
17540 		xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
17541 	}
17542 	if (! fmaxlen)
17543 	    fmaxlen = bfmaxlen;
17544 	if (fmaxlen) {
17545 	    /* (2.1) length <= maxLength */
17546 	    res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
17547 	    if (res == -2)
17548 		goto internal_error;
17549 	    if (res == 1)
17550 		xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
17551 	}
17552     }
17553     if (fmaxinc) {
17554 	/*
17555 	* "maxInclusive"
17556 	*/
17557 	if (fmininc) {
17558 	    /* SCC "maxInclusive >= minInclusive" */
17559 	    res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
17560 	    if (res == -2)
17561 		goto internal_error;
17562 	    if (res == -1) {
17563 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
17564 	    }
17565 	}
17566 	/*
17567 	* SCC "maxInclusive valid restriction"
17568 	*/
17569 	if (bfmaxinc) {
17570 	    /* maxInclusive <= BASE maxInclusive */
17571 	    res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
17572 	    if (res == -2)
17573 		goto internal_error;
17574 	    if (res == 1)
17575 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
17576 	    if ((res != 0) && (bfmaxinc->fixed)) {
17577 		FACET_RESTR_FIXED_ERR(fmaxinc)
17578 	    }
17579 	}
17580 	if (bfmaxexc) {
17581 	    /* maxInclusive < BASE maxExclusive */
17582 	    res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
17583 	    if (res == -2)
17584 		goto internal_error;
17585 	    if (res != -1) {
17586 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
17587 	    }
17588 	}
17589 	if (bfmininc) {
17590 	    /* maxInclusive >= BASE minInclusive */
17591 	    res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
17592 	    if (res == -2)
17593 		goto internal_error;
17594 	    if (res == -1) {
17595 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
17596 	    }
17597 	}
17598 	if (bfminexc) {
17599 	    /* maxInclusive > BASE minExclusive */
17600 	    res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
17601 	    if (res == -2)
17602 		goto internal_error;
17603 	    if (res != 1) {
17604 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
17605 	    }
17606 	}
17607     }
17608     if (fmaxexc) {
17609 	/*
17610 	* "maxExclusive >= minExclusive"
17611 	*/
17612 	if (fminexc) {
17613 	    res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
17614 	    if (res == -2)
17615 		goto internal_error;
17616 	    if (res == -1) {
17617 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
17618 	    }
17619 	}
17620 	/*
17621 	* "maxExclusive valid restriction"
17622 	*/
17623 	if (bfmaxexc) {
17624 	    /* maxExclusive <= BASE maxExclusive */
17625 	    res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
17626 	    if (res == -2)
17627 		goto internal_error;
17628 	    if (res == 1) {
17629 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
17630 	    }
17631 	    if ((res != 0) && (bfmaxexc->fixed)) {
17632 		FACET_RESTR_FIXED_ERR(fmaxexc)
17633 	    }
17634 	}
17635 	if (bfmaxinc) {
17636 	    /* maxExclusive <= BASE maxInclusive */
17637 	    res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
17638 	    if (res == -2)
17639 		goto internal_error;
17640 	    if (res == 1) {
17641 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
17642 	    }
17643 	}
17644 	if (bfmininc) {
17645 	    /* maxExclusive > BASE minInclusive */
17646 	    res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
17647 	    if (res == -2)
17648 		goto internal_error;
17649 	    if (res != 1) {
17650 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
17651 	    }
17652 	}
17653 	if (bfminexc) {
17654 	    /* maxExclusive > BASE minExclusive */
17655 	    res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
17656 	    if (res == -2)
17657 		goto internal_error;
17658 	    if (res != 1) {
17659 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
17660 	    }
17661 	}
17662     }
17663     if (fminexc) {
17664 	/*
17665 	* "minExclusive < maxInclusive"
17666 	*/
17667 	if (fmaxinc) {
17668 	    res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
17669 	    if (res == -2)
17670 		goto internal_error;
17671 	    if (res != -1) {
17672 		xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
17673 	    }
17674 	}
17675 	/*
17676 	* "minExclusive valid restriction"
17677 	*/
17678 	if (bfminexc) {
17679 	    /* minExclusive >= BASE minExclusive */
17680 	    res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
17681 	    if (res == -2)
17682 		goto internal_error;
17683 	    if (res == -1) {
17684 		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
17685 	    }
17686 	    if ((res != 0) && (bfminexc->fixed)) {
17687 		FACET_RESTR_FIXED_ERR(fminexc)
17688 	    }
17689 	}
17690 	if (bfmaxinc) {
17691 	    /* minExclusive <= BASE maxInclusive */
17692 	    res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
17693 	    if (res == -2)
17694 		goto internal_error;
17695 	    if (res == 1) {
17696 		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
17697 	    }
17698 	}
17699 	if (bfmininc) {
17700 	    /* minExclusive >= BASE minInclusive */
17701 	    res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
17702 	    if (res == -2)
17703 		goto internal_error;
17704 	    if (res == -1) {
17705 		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
17706 	    }
17707 	}
17708 	if (bfmaxexc) {
17709 	    /* minExclusive < BASE maxExclusive */
17710 	    res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
17711 	    if (res == -2)
17712 		goto internal_error;
17713 	    if (res != -1) {
17714 		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
17715 	    }
17716 	}
17717     }
17718     if (fmininc) {
17719 	/*
17720 	* "minInclusive < maxExclusive"
17721 	*/
17722 	if (fmaxexc) {
17723 	    res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
17724 	    if (res == -2)
17725 		goto internal_error;
17726 	    if (res != -1) {
17727 		xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
17728 	    }
17729 	}
17730 	/*
17731 	* "minExclusive valid restriction"
17732 	*/
17733 	if (bfmininc) {
17734 	    /* minInclusive >= BASE minInclusive */
17735 	    res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
17736 	    if (res == -2)
17737 		goto internal_error;
17738 	    if (res == -1) {
17739 		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
17740 	    }
17741 	    if ((res != 0) && (bfmininc->fixed)) {
17742 		FACET_RESTR_FIXED_ERR(fmininc)
17743 	    }
17744 	}
17745 	if (bfmaxinc) {
17746 	    /* minInclusive <= BASE maxInclusive */
17747 	    res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
17748 	    if (res == -2)
17749 		goto internal_error;
17750 	    if (res == 1) {
17751 		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
17752 	    }
17753 	}
17754 	if (bfminexc) {
17755 	    /* minInclusive > BASE minExclusive */
17756 	    res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
17757 	    if (res == -2)
17758 		goto internal_error;
17759 	    if (res != 1)
17760 		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
17761 	}
17762 	if (bfmaxexc) {
17763 	    /* minInclusive < BASE maxExclusive */
17764 	    res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
17765 	    if (res == -2)
17766 		goto internal_error;
17767 	    if (res != -1)
17768 		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
17769 	}
17770     }
17771     if (ftotdig && bftotdig) {
17772 	/*
17773 	* SCC " totalDigits valid restriction"
17774 	* totalDigits <= BASE totalDigits
17775 	*/
17776 	res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
17777 	if (res == -2)
17778 	    goto internal_error;
17779 	if (res == 1)
17780 	    xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
17781 	    -1, 1, 1);
17782 	if ((res != 0) && (bftotdig->fixed)) {
17783 	    FACET_RESTR_FIXED_ERR(ftotdig)
17784 	}
17785     }
17786     if (ffracdig && bffracdig) {
17787 	/*
17788 	* SCC  "fractionDigits valid restriction"
17789 	* fractionDigits <= BASE fractionDigits
17790 	*/
17791 	res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
17792 	if (res == -2)
17793 	    goto internal_error;
17794 	if (res == 1)
17795 	    xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
17796 	    -1, 1, 1);
17797 	if ((res != 0) && (bffracdig->fixed)) {
17798 	    FACET_RESTR_FIXED_ERR(ffracdig)
17799 	}
17800     }
17801     /*
17802     * SCC "fractionDigits less than or equal to totalDigits"
17803     */
17804     if (! ftotdig)
17805 	ftotdig = bftotdig;
17806     if (! ffracdig)
17807 	ffracdig = bffracdig;
17808     if (ftotdig && ffracdig) {
17809 	res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
17810 	if (res == -2)
17811 	    goto internal_error;
17812 	if (res == 1)
17813 	    xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
17814 		-1, 1, 0);
17815     }
17816     /*
17817     * *Enumerations* won' be added here, since only the first set
17818     * of enumerations in the ancestor-or-self axis is used
17819     * for validation, plus we need to use the base type of those
17820     * enumerations for whitespace.
17821     *
17822     * *Patterns*: won't be add here, since they are ORed at
17823     * type level and ANDed at ancestor level. This will
17824     * happen during validation by walking the base axis
17825     * of the type.
17826     */
17827     for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17828 	bfacet = cur->facet;
17829 	/*
17830 	* Special handling of enumerations and patterns.
17831 	* TODO: hmm, they should not appear in the set, so remove this.
17832 	*/
17833 	if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
17834 	    (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
17835 	    continue;
17836 	/*
17837 	* Search for a duplicate facet in the current type.
17838 	*/
17839 	link = type->facetSet;
17840 	/* err = 0; */
17841 	/* fixedErr = 0; */
17842 	while (link != NULL) {
17843 	    facet = link->facet;
17844 	    if (facet->type == bfacet->type) {
17845 		switch (facet->type) {
17846 		    case XML_SCHEMA_FACET_WHITESPACE:
17847 			/*
17848 			* The whitespace must be stronger.
17849 			*/
17850 			if (facet->whitespace < bfacet->whitespace) {
17851 			    FACET_RESTR_ERR(facet,
17852 				"The 'whitespace' value has to be equal to "
17853 				"or stronger than the 'whitespace' value of "
17854 				"the base type")
17855 			}
17856 			if ((bfacet->fixed) &&
17857 			    (facet->whitespace != bfacet->whitespace)) {
17858 			    FACET_RESTR_FIXED_ERR(facet)
17859 			}
17860 			break;
17861 		    default:
17862 			break;
17863 		}
17864 		/* Duplicate found. */
17865 		break;
17866 	    }
17867 	    link = link->next;
17868 	}
17869 	/*
17870 	* If no duplicate was found: add the base types's facet
17871 	* to the set.
17872 	*/
17873 	if (link == NULL) {
17874 	    link = (xmlSchemaFacetLinkPtr)
17875 		xmlMalloc(sizeof(xmlSchemaFacetLink));
17876 	    if (link == NULL) {
17877 		xmlSchemaPErrMemory(pctxt,
17878 		    "deriving facets, creating a facet link", NULL);
17879 		return (-1);
17880 	    }
17881 	    link->facet = cur->facet;
17882 	    link->next = NULL;
17883 	    if (last == NULL)
17884 		type->facetSet = link;
17885 	    else
17886 		last->next = link;
17887 	    last = link;
17888 	}
17889 
17890     }
17891 
17892     return (0);
17893 internal_error:
17894     PERROR_INT("xmlSchemaDeriveAndValidateFacets",
17895 	"an error occurred");
17896     return (-1);
17897 }
17898 
17899 static int
xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)17900 xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
17901 					     xmlSchemaTypePtr type)
17902 {
17903     xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
17904     /*
17905     * The actual value is then formed by replacing any union type
17906     * definition in the `explicit members` with the members of their
17907     * {member type definitions}, in order.
17908     *
17909     * TODO: There's a bug entry at
17910     * "http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0287.html"
17911     * which indicates that we'll keep the union types the future.
17912     */
17913     link = type->memberTypes;
17914     while (link != NULL) {
17915 
17916 	if (WXS_IS_TYPE_NOT_FIXED(link->type))
17917 	    xmlSchemaTypeFixup(link->type, ACTXT_CAST pctxt);
17918 
17919 	if (WXS_IS_UNION(link->type)) {
17920 	    subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
17921 	    if (subLink != NULL) {
17922 		link->type = subLink->type;
17923 		if (subLink->next != NULL) {
17924 		    lastLink = link->next;
17925 		    subLink = subLink->next;
17926 		    prevLink = link;
17927 		    while (subLink != NULL) {
17928 			newLink = (xmlSchemaTypeLinkPtr)
17929 			    xmlMalloc(sizeof(xmlSchemaTypeLink));
17930 			if (newLink == NULL) {
17931 			    xmlSchemaPErrMemory(pctxt, "allocating a type link",
17932 				NULL);
17933 			    return (-1);
17934 			}
17935 			newLink->type = subLink->type;
17936 			prevLink->next = newLink;
17937 			prevLink = newLink;
17938 			newLink->next = lastLink;
17939 
17940 			subLink = subLink->next;
17941 		    }
17942 		}
17943 	    }
17944 	}
17945 	link = link->next;
17946     }
17947     return (0);
17948 }
17949 
17950 static void
xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)17951 xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
17952 {
17953     int has = 0, needVal = 0, normVal = 0;
17954 
17955     has	= (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
17956     if (has) {
17957 	needVal = (type->baseType->flags &
17958 	    XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
17959 	normVal = (type->baseType->flags &
17960 	    XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
17961     }
17962     if (type->facets != NULL) {
17963 	xmlSchemaFacetPtr fac;
17964 
17965 	for (fac = type->facets; fac != NULL; fac = fac->next) {
17966 	    switch (fac->type) {
17967 		case XML_SCHEMA_FACET_WHITESPACE:
17968 		    break;
17969 		case XML_SCHEMA_FACET_PATTERN:
17970 		    normVal = 1;
17971 		    has = 1;
17972 		    break;
17973 		case XML_SCHEMA_FACET_ENUMERATION:
17974 		    needVal = 1;
17975 		    normVal = 1;
17976 		    has = 1;
17977 		    break;
17978 		default:
17979 		    has = 1;
17980 		    break;
17981 	    }
17982 	}
17983     }
17984     if (normVal)
17985 	type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
17986     if (needVal)
17987 	type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17988     if (has)
17989 	type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
17990 
17991     if (has && (! needVal) && WXS_IS_ATOMIC(type)) {
17992 	xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
17993 	/*
17994 	* OPTIMIZE VAL TODO: Some facets need a computed value.
17995 	*/
17996 	if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
17997 	    (prim->builtInType != XML_SCHEMAS_STRING)) {
17998 	    type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17999 	}
18000     }
18001 }
18002 
18003 static int
xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)18004 xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
18005 {
18006 
18007 
18008     /*
18009     * Evaluate the whitespace-facet value.
18010     */
18011     if (WXS_IS_LIST(type)) {
18012 	type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
18013 	return (0);
18014     } else if (WXS_IS_UNION(type))
18015 	return (0);
18016 
18017     if (type->facetSet != NULL) {
18018 	xmlSchemaFacetLinkPtr lin;
18019 
18020 	for (lin = type->facetSet; lin != NULL; lin = lin->next) {
18021 	    if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
18022 		switch (lin->facet->whitespace) {
18023 		case XML_SCHEMAS_FACET_PRESERVE:
18024 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
18025 		    break;
18026 		case XML_SCHEMAS_FACET_REPLACE:
18027 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
18028 		    break;
18029 		case XML_SCHEMAS_FACET_COLLAPSE:
18030 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
18031 		    break;
18032 		default:
18033 		    return (-1);
18034 		}
18035 		return (0);
18036 	    }
18037 	}
18038     }
18039     /*
18040     * For all `atomic` datatypes other than string (and types `derived`
18041     * by `restriction` from it) the value of whiteSpace is fixed to
18042     * collapse
18043     */
18044     {
18045 	xmlSchemaTypePtr anc;
18046 
18047 	for (anc = type->baseType; anc != NULL &&
18048 		anc->builtInType != XML_SCHEMAS_ANYTYPE;
18049 		anc = anc->baseType) {
18050 
18051 	    if (anc->type == XML_SCHEMA_TYPE_BASIC) {
18052 		if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
18053 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
18054 
18055 		} else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
18056 		    (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
18057 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
18058 
18059 		} else
18060 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
18061 		break;
18062 	    }
18063 	}
18064     }
18065     return (0);
18066 }
18067 
18068 static int
xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)18069 xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,
18070 			  xmlSchemaTypePtr type)
18071 {
18072     if (type->type != XML_SCHEMA_TYPE_SIMPLE)
18073 	return(0);
18074     if (! WXS_IS_TYPE_NOT_FIXED_1(type))
18075 	return(0);
18076     type->flags |= XML_SCHEMAS_TYPE_FIXUP_1;
18077 
18078     if (WXS_IS_LIST(type)) {
18079 	/*
18080 	* Corresponds to <simpleType><list>...
18081 	*/
18082 	if (type->subtypes == NULL) {
18083 	    /*
18084 	    * This one is really needed, so get out.
18085 	    */
18086 	    PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
18087 		"list type has no item-type assigned");
18088 	    return(-1);
18089 	}
18090     } else if (WXS_IS_UNION(type)) {
18091 	/*
18092 	* Corresponds to <simpleType><union>...
18093 	*/
18094 	if (type->memberTypes == NULL) {
18095 	    /*
18096 	    * This one is really needed, so get out.
18097 	    */
18098 	    PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
18099 		"union type has no member-types assigned");
18100 	    return(-1);
18101 	}
18102     } else {
18103 	/*
18104 	* Corresponds to <simpleType><restriction>...
18105 	*/
18106 	if (type->baseType == NULL) {
18107 	    PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
18108 		"type has no base-type assigned");
18109 	    return(-1);
18110 	}
18111 	if (WXS_IS_TYPE_NOT_FIXED_1(type->baseType))
18112 	    if (xmlSchemaFixupSimpleTypeStageOne(pctxt, type->baseType) == -1)
18113 		return(-1);
18114 	/*
18115 	* Variety
18116 	* If the <restriction> alternative is chosen, then the
18117 	* {variety} of the {base type definition}.
18118 	*/
18119 	if (WXS_IS_ATOMIC(type->baseType))
18120 	    type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
18121 	else if (WXS_IS_LIST(type->baseType)) {
18122 	    type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
18123 	    /*
18124 	    * Inherit the itemType.
18125 	    */
18126 	    type->subtypes = type->baseType->subtypes;
18127 	} else if (WXS_IS_UNION(type->baseType)) {
18128 	    type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
18129 	    /*
18130 	    * NOTE that we won't assign the memberTypes of the base,
18131 	    * since this will make trouble when freeing them; we will
18132 	    * use a lookup function to access them instead.
18133 	    */
18134 	}
18135     }
18136     return(0);
18137 }
18138 
18139 #ifdef DEBUG_TYPE
18140 static void
xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)18141 xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt,
18142 		       xmlSchemaTypePtr type)
18143 {
18144     if (type->node != NULL) {
18145         xmlGenericError(xmlGenericErrorContext,
18146                         "Type of %s : %s:%d :", name,
18147                         type->node->doc->URL,
18148                         xmlGetLineNo(type->node));
18149     } else {
18150         xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
18151     }
18152     if ((WXS_IS_SIMPLE(type)) || (WXS_IS_COMPLEX(type))) {
18153 	switch (type->contentType) {
18154 	    case XML_SCHEMA_CONTENT_SIMPLE:
18155 		xmlGenericError(xmlGenericErrorContext, "simple\n");
18156 		break;
18157 	    case XML_SCHEMA_CONTENT_ELEMENTS:
18158 		xmlGenericError(xmlGenericErrorContext, "elements\n");
18159 		break;
18160 	    case XML_SCHEMA_CONTENT_UNKNOWN:
18161 		xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
18162 		break;
18163 	    case XML_SCHEMA_CONTENT_EMPTY:
18164 		xmlGenericError(xmlGenericErrorContext, "empty\n");
18165 		break;
18166 	    case XML_SCHEMA_CONTENT_MIXED:
18167 		if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
18168 		    type->subtypes))
18169 		    xmlGenericError(xmlGenericErrorContext,
18170 			"mixed as emptiable particle\n");
18171 		else
18172 		    xmlGenericError(xmlGenericErrorContext, "mixed\n");
18173 		break;
18174 		/* Removed, since not used. */
18175 		/*
18176 		case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
18177 		xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
18178 		break;
18179 		*/
18180 	    case XML_SCHEMA_CONTENT_BASIC:
18181 		xmlGenericError(xmlGenericErrorContext, "basic\n");
18182 		break;
18183 	    default:
18184 		xmlGenericError(xmlGenericErrorContext,
18185 		    "not registered !!!\n");
18186 		break;
18187 	}
18188     }
18189 }
18190 #endif
18191 
18192 /*
18193 * 3.14.6 Constraints on Simple Type Definition Schema Components
18194 */
18195 static int
xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)18196 xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,
18197 				 xmlSchemaTypePtr type)
18198 {
18199     int res, olderrs = pctxt->nberrors;
18200 
18201     if (type->type != XML_SCHEMA_TYPE_SIMPLE)
18202 	return(-1);
18203 
18204     if (! WXS_IS_TYPE_NOT_FIXED(type))
18205 	return(0);
18206 
18207     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18208     type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
18209 
18210     if (type->baseType == NULL) {
18211 	PERROR_INT("xmlSchemaFixupSimpleTypeStageTwo",
18212 	    "missing baseType");
18213 	goto exit_failure;
18214     }
18215     if (WXS_IS_TYPE_NOT_FIXED(type->baseType))
18216 	xmlSchemaTypeFixup(type->baseType, ACTXT_CAST pctxt);
18217     /*
18218     * If a member type of a union is a union itself, we need to substitute
18219     * that member type for its member types.
18220     * NOTE that this might change in WXS 1.1; i.e. we will keep the union
18221     * types in WXS 1.1.
18222     */
18223     if ((type->memberTypes != NULL) &&
18224 	(xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1))
18225 	return(-1);
18226     /*
18227     * SPEC src-simple-type 1
18228     * "The corresponding simple type definition, if any, must satisfy
18229     * the conditions set out in Constraints on Simple Type Definition
18230     * Schema Components ($3.14.6)."
18231     */
18232     /*
18233     * Schema Component Constraint: Simple Type Definition Properties Correct
18234     * (st-props-correct)
18235     */
18236     res = xmlSchemaCheckSTPropsCorrect(pctxt, type);
18237     HFAILURE HERROR
18238     /*
18239     * Schema Component Constraint: Derivation Valid (Restriction, Simple)
18240     * (cos-st-restricts)
18241     */
18242     res = xmlSchemaCheckCOSSTRestricts(pctxt, type);
18243     HFAILURE HERROR
18244     /*
18245     * TODO: Removed the error report, since it got annoying to get an
18246     * extra error report, if anything failed until now.
18247     * Enable this if needed.
18248     *
18249     * xmlSchemaPErr(ctxt, type->node,
18250     *    XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
18251     *    "Simple type '%s' does not satisfy the constraints "
18252     *    "on simple type definitions.\n",
18253     *    type->name, NULL);
18254     */
18255     /*
18256     * Schema Component Constraint: Simple Type Restriction (Facets)
18257     * (st-restrict-facets)
18258     */
18259     res = xmlSchemaCheckFacetValues(type, pctxt);
18260     HFAILURE HERROR
18261     if ((type->facetSet != NULL) ||
18262 	(type->baseType->facetSet != NULL)) {
18263 	res = xmlSchemaDeriveAndValidateFacets(pctxt, type);
18264 	HFAILURE HERROR
18265     }
18266     /*
18267     * Whitespace value.
18268     */
18269     res = xmlSchemaTypeFixupWhitespace(type);
18270     HFAILURE HERROR
18271     xmlSchemaTypeFixupOptimFacets(type);
18272 
18273 exit_error:
18274 #ifdef DEBUG_TYPE
18275     xmlSchemaDebugFixedType(pctxt, type);
18276 #endif
18277     if (olderrs != pctxt->nberrors)
18278 	return(pctxt->err);
18279     return(0);
18280 
18281 exit_failure:
18282 #ifdef DEBUG_TYPE
18283     xmlSchemaDebugFixedType(pctxt, type);
18284 #endif
18285     return(-1);
18286 }
18287 
18288 static int
xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)18289 xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,
18290 			  xmlSchemaTypePtr type)
18291 {
18292     int res = 0, olderrs = pctxt->nberrors;
18293     xmlSchemaTypePtr baseType = type->baseType;
18294 
18295     if (! WXS_IS_TYPE_NOT_FIXED(type))
18296 	return(0);
18297     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18298     if (baseType == NULL) {
18299 	PERROR_INT("xmlSchemaFixupComplexType",
18300 	    "missing baseType");
18301 	goto exit_failure;
18302     }
18303     /*
18304     * Fixup the base type.
18305     */
18306     if (WXS_IS_TYPE_NOT_FIXED(baseType))
18307 	xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt);
18308     if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
18309 	/*
18310 	* Skip fixup if the base type is invalid.
18311 	* TODO: Generate a warning!
18312 	*/
18313 	return(0);
18314     }
18315     /*
18316     * This basically checks if the base type can be derived.
18317     */
18318     res = xmlSchemaCheckSRCCT(pctxt, type);
18319     HFAILURE HERROR
18320     /*
18321     * Fixup the content type.
18322     */
18323     if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
18324 	/*
18325 	* Corresponds to <complexType><simpleContent>...
18326 	*/
18327 	if ((WXS_IS_COMPLEX(baseType)) &&
18328 	    (baseType->contentTypeDef != NULL) &&
18329 	    (WXS_IS_RESTRICTION(type))) {
18330 	    xmlSchemaTypePtr contentBase, content;
18331 #ifdef ENABLE_NAMED_LOCALS
18332 	    char buf[30];
18333 	    const xmlChar *tmpname;
18334 #endif
18335 	    /*
18336 	    * SPEC (1) If <restriction> + base type is <complexType>,
18337 	    * "whose own {content type} is a simple type..."
18338 	    */
18339 	    if (type->contentTypeDef != NULL) {
18340 		/*
18341 		* SPEC (1.1) "the simple type definition corresponding to the
18342 		* <simpleType> among the [children] of <restriction> if there
18343 		* is one;"
18344 		* Note that this "<simpleType> among the [children]" was put
18345 		* into ->contentTypeDef during parsing.
18346 		*/
18347 		contentBase = type->contentTypeDef;
18348 		type->contentTypeDef = NULL;
18349 	    } else {
18350 		/*
18351 		* (1.2) "...otherwise (<restriction> has no <simpleType>
18352 		* among its [children]), the simple type definition which
18353 		* is the {content type} of the ... base type."
18354 		*/
18355 		contentBase = baseType->contentTypeDef;
18356 	    }
18357 	    /*
18358 	    * SPEC
18359 	    * "... a simple type definition which restricts the simple
18360 	    * type definition identified in clause 1.1 or clause 1.2
18361 	    * with a set of facet components"
18362 	    *
18363 	    * Create the anonymous simple type, which will be the content
18364 	    * type of the complex type.
18365 	    */
18366 #ifdef ENABLE_NAMED_LOCALS
18367 	    snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
18368 	    tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
18369 	    content = xmlSchemaAddType(pctxt, pctxt->schema,
18370 		XML_SCHEMA_TYPE_SIMPLE, tmpname, type->targetNamespace,
18371 		type->node, 0);
18372 #else
18373 	    content = xmlSchemaAddType(pctxt, pctxt->schema,
18374 		XML_SCHEMA_TYPE_SIMPLE, NULL, type->targetNamespace,
18375 		type->node, 0);
18376 #endif
18377 	    if (content == NULL)
18378 		goto exit_failure;
18379 	    /*
18380 	    * We will use the same node as for the <complexType>
18381 	    * to have it somehow anchored in the schema doc.
18382 	    */
18383 	    content->type = XML_SCHEMA_TYPE_SIMPLE;
18384 	    content->baseType = contentBase;
18385 	    /*
18386 	    * Move the facets, previously anchored on the
18387 	    * complexType during parsing.
18388 	    */
18389 	    content->facets = type->facets;
18390 	    type->facets = NULL;
18391 	    content->facetSet = type->facetSet;
18392 	    type->facetSet = NULL;
18393 
18394 	    type->contentTypeDef = content;
18395 	    if (WXS_IS_TYPE_NOT_FIXED(contentBase))
18396 		xmlSchemaTypeFixup(contentBase, ACTXT_CAST pctxt);
18397 	    /*
18398 	    * Fixup the newly created type. We don't need to check
18399 	    * for circularity here.
18400 	    */
18401 	    res = xmlSchemaFixupSimpleTypeStageOne(pctxt, content);
18402 	    HFAILURE HERROR
18403 	    res = xmlSchemaFixupSimpleTypeStageTwo(pctxt, content);
18404 	    HFAILURE HERROR
18405 
18406 	} else if ((WXS_IS_COMPLEX(baseType)) &&
18407 	    (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
18408 	    (WXS_IS_RESTRICTION(type))) {
18409 	    /*
18410 	    * SPEC (2) If <restriction> + base is a mixed <complexType> with
18411 	    * an emptiable particle, then a simple type definition which
18412 	    * restricts the <restriction>'s <simpleType> child.
18413 	    */
18414 	    if ((type->contentTypeDef == NULL) ||
18415 		(type->contentTypeDef->baseType == NULL)) {
18416 		/*
18417 		* TODO: Check if this ever happens.
18418 		*/
18419 		xmlSchemaPCustomErr(pctxt,
18420 		    XML_SCHEMAP_INTERNAL,
18421 		    WXS_BASIC_CAST type, NULL,
18422 		    "Internal error: xmlSchemaTypeFixup, "
18423 		    "complex type '%s': the <simpleContent><restriction> "
18424 		    "is missing a <simpleType> child, but was not caught "
18425 		    "by xmlSchemaCheckSRCCT()", type->name);
18426 		goto exit_failure;
18427 	    }
18428 	} else if ((WXS_IS_COMPLEX(baseType)) && WXS_IS_EXTENSION(type)) {
18429 	    /*
18430 	    * SPEC (3) If <extension> + base is <complexType> with
18431 	    * <simpleType> content, "...then the {content type} of that
18432 	    * complex type definition"
18433 	    */
18434 	    if (baseType->contentTypeDef == NULL) {
18435 		/*
18436 		* TODO: Check if this ever happens. xmlSchemaCheckSRCCT
18437 		* should have caught this already.
18438 		*/
18439 		xmlSchemaPCustomErr(pctxt,
18440 		    XML_SCHEMAP_INTERNAL,
18441 		    WXS_BASIC_CAST type, NULL,
18442 		    "Internal error: xmlSchemaTypeFixup, "
18443 		    "complex type '%s': the <extension>ed base type is "
18444 		    "a complex type with no simple content type",
18445 		    type->name);
18446 		goto exit_failure;
18447 	    }
18448 	    type->contentTypeDef = baseType->contentTypeDef;
18449 	} else if ((WXS_IS_SIMPLE(baseType)) && WXS_IS_EXTENSION(type)) {
18450 	    /*
18451 	    * SPEC (4) <extension> + base is <simpleType>
18452 	    * "... then that simple type definition"
18453 	    */
18454 	    type->contentTypeDef = baseType;
18455 	} else {
18456 	    /*
18457 	    * TODO: Check if this ever happens.
18458 	    */
18459 	    xmlSchemaPCustomErr(pctxt,
18460 		XML_SCHEMAP_INTERNAL,
18461 		WXS_BASIC_CAST type, NULL,
18462 		"Internal error: xmlSchemaTypeFixup, "
18463 		"complex type '%s' with <simpleContent>: unhandled "
18464 		"derivation case", type->name);
18465 	    goto exit_failure;
18466 	}
18467     } else {
18468 	int dummySequence = 0;
18469 	xmlSchemaParticlePtr particle =
18470 	    (xmlSchemaParticlePtr) type->subtypes;
18471 	/*
18472 	* Corresponds to <complexType><complexContent>...
18473 	*
18474 	* NOTE that the effective mixed was already set during parsing of
18475 	* <complexType> and <complexContent>; its flag value is
18476 	* XML_SCHEMAS_TYPE_MIXED.
18477 	*
18478 	* Compute the "effective content":
18479 	* (2.1.1) + (2.1.2) + (2.1.3)
18480 	*/
18481 	if ((particle == NULL) ||
18482 	    ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
18483 	    ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
18484 	    (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
18485 	    ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
18486 	    (particle->minOccurs == 0))) &&
18487 	    ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
18488 	    if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
18489 		/*
18490 		* SPEC (2.1.4) "If the `effective mixed` is true, then
18491 		* a particle whose properties are as follows:..."
18492 		*
18493 		* Empty sequence model group with
18494 		* minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
18495 		* NOTE that we sill assign it the <complexType> node to
18496 		* somehow anchor it in the doc.
18497 		*/
18498 		if ((particle == NULL) ||
18499 		    (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
18500 		    /*
18501 		    * Create the particle.
18502 		    */
18503 		    particle = xmlSchemaAddParticle(pctxt,
18504 			type->node, 1, 1);
18505 		    if (particle == NULL)
18506 			goto exit_failure;
18507 		    /*
18508 		    * Create the model group.
18509 		    */ /* URGENT TODO: avoid adding to pending items. */
18510 		    particle->children = (xmlSchemaTreeItemPtr)
18511 			xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18512 			XML_SCHEMA_TYPE_SEQUENCE, type->node);
18513 		    if (particle->children == NULL)
18514 			goto exit_failure;
18515 
18516 		    type->subtypes = (xmlSchemaTypePtr) particle;
18517 		}
18518 		dummySequence = 1;
18519 		type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18520 	    } else {
18521 		/*
18522 		* SPEC (2.1.5) "otherwise empty"
18523 		*/
18524 		type->contentType = XML_SCHEMA_CONTENT_EMPTY;
18525 	    }
18526 	} else {
18527 	    /*
18528 	    * SPEC (2.2) "otherwise the particle corresponding to the
18529 	    * <all>, <choice>, <group> or <sequence> among the
18530 	    * [children]."
18531 	    */
18532 	    type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18533 	}
18534 	/*
18535 	* Compute the "content type".
18536 	*/
18537 	if (WXS_IS_RESTRICTION(type)) {
18538 	    /*
18539 	    * SPEC (3.1) "If <restriction>..."
18540 	    * (3.1.1) + (3.1.2) */
18541 	    if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
18542 		if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18543 		    type->contentType = XML_SCHEMA_CONTENT_MIXED;
18544 	    }
18545 	} else {
18546 	    /*
18547 	    * SPEC (3.2) "If <extension>..."
18548 	    */
18549 	    if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18550 		/*
18551 		* SPEC (3.2.1)
18552 		* "If the `effective content` is empty, then the
18553 		*  {content type} of the [...] base ..."
18554 		*/
18555 		type->contentType = baseType->contentType;
18556 		type->subtypes = baseType->subtypes;
18557 		/*
18558 		* Fixes bug #347316:
18559 		* This is the case when the base type has a simple
18560 		* type definition as content.
18561 		*/
18562 		type->contentTypeDef = baseType->contentTypeDef;
18563 		/*
18564 		* NOTE that the effective mixed is ignored here.
18565 		*/
18566 	    } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18567 		/*
18568 		* SPEC (3.2.2)
18569 		*/
18570 		if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18571 		    type->contentType = XML_SCHEMA_CONTENT_MIXED;
18572 	    } else {
18573 		/*
18574 		* SPEC (3.2.3)
18575 		*/
18576 		if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18577 		    type->contentType = XML_SCHEMA_CONTENT_MIXED;
18578 		    /*
18579 		    * "A model group whose {compositor} is sequence and whose
18580 		    * {particles} are..."
18581 		    */
18582 		if ((WXS_TYPE_PARTICLE(type) != NULL) &&
18583 		    (WXS_TYPE_PARTICLE_TERM(type) != NULL) &&
18584 		    ((WXS_TYPE_PARTICLE_TERM(type))->type ==
18585 			XML_SCHEMA_TYPE_ALL))
18586 		{
18587 		    /*
18588 		    * SPEC cos-all-limited (1)
18589 		    */
18590 		    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18591 			/* TODO: error code */
18592 			XML_SCHEMAP_COS_ALL_LIMITED,
18593 			WXS_ITEM_NODE(type), NULL,
18594 			"The type has an 'all' model group in its "
18595 			"{content type} and thus cannot be derived from "
18596 			"a non-empty type, since this would produce a "
18597 			"'sequence' model group containing the 'all' "
18598 			"model group; 'all' model groups are not "
18599 			"allowed to appear inside other model groups",
18600 			NULL, NULL);
18601 
18602 		} else if ((WXS_TYPE_PARTICLE(baseType) != NULL) &&
18603 		    (WXS_TYPE_PARTICLE_TERM(baseType) != NULL) &&
18604 		    ((WXS_TYPE_PARTICLE_TERM(baseType))->type ==
18605 			XML_SCHEMA_TYPE_ALL))
18606 		{
18607 		    /*
18608 		    * SPEC cos-all-limited (1)
18609 		    */
18610 		    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18611 			/* TODO: error code */
18612 			XML_SCHEMAP_COS_ALL_LIMITED,
18613 			WXS_ITEM_NODE(type), NULL,
18614 			"A type cannot be derived by extension from a type "
18615 			"which has an 'all' model group in its "
18616 			"{content type}, since this would produce a "
18617 			"'sequence' model group containing the 'all' "
18618 			"model group; 'all' model groups are not "
18619 			"allowed to appear inside other model groups",
18620 			NULL, NULL);
18621 
18622 		} else if ((!dummySequence) && (baseType->subtypes != NULL)) {
18623 		    xmlSchemaTreeItemPtr effectiveContent =
18624 			(xmlSchemaTreeItemPtr) type->subtypes;
18625 		    /*
18626 		    * Create the particle.
18627 		    */
18628 		    particle = xmlSchemaAddParticle(pctxt,
18629 			type->node, 1, 1);
18630 		    if (particle == NULL)
18631 			goto exit_failure;
18632 		    /*
18633 		    * Create the "sequence" model group.
18634 		    */
18635 		    particle->children = (xmlSchemaTreeItemPtr)
18636 			xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18637 			XML_SCHEMA_TYPE_SEQUENCE, type->node);
18638 		    if (particle->children == NULL)
18639 			goto exit_failure;
18640 		    WXS_TYPE_CONTENTTYPE(type) = (xmlSchemaTypePtr) particle;
18641 		    /*
18642 		    * SPEC "the particle of the {content type} of
18643 		    * the ... base ..."
18644 		    * Create a duplicate of the base type's particle
18645 		    * and assign its "term" to it.
18646 		    */
18647 		    particle->children->children =
18648 			(xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
18649 			type->node,
18650 			((xmlSchemaParticlePtr) baseType->subtypes)->minOccurs,
18651 			((xmlSchemaParticlePtr) baseType->subtypes)->maxOccurs);
18652 		    if (particle->children->children == NULL)
18653 			goto exit_failure;
18654 		    particle = (xmlSchemaParticlePtr)
18655 			particle->children->children;
18656 		    particle->children =
18657 			((xmlSchemaParticlePtr) baseType->subtypes)->children;
18658 		    /*
18659 		    * SPEC "followed by the `effective content`."
18660 		    */
18661 		    particle->next = effectiveContent;
18662 		    /*
18663 		    * This all will result in:
18664 		    * new-particle
18665 		    *   --> new-sequence(
18666 		    *         new-particle
18667 		    *           --> base-model,
18668 		    *         this-particle
18669 		    *	        --> this-model
18670 		    *	    )
18671 		    */
18672 		} else {
18673 		    /*
18674 		    * This is the case when there is already an empty
18675 		    * <sequence> with minOccurs==maxOccurs==1.
18676 		    * Just add the base types's content type.
18677 		    * NOTE that, although we miss to add an intermediate
18678 		    * <sequence>, this should produce no difference to
18679 		    * neither the regex compilation of the content model,
18680 		    * nor to the complex type constraints.
18681 		    */
18682 		    particle->children->children =
18683 			(xmlSchemaTreeItemPtr) baseType->subtypes;
18684 		}
18685 	    }
18686 	}
18687     }
18688     /*
18689     * Now fixup attribute uses:
18690     *   - expand attr. group references
18691     *     - intersect attribute wildcards
18692     *   - inherit attribute uses of the base type
18693     *   - inherit or union attr. wildcards if extending
18694     *   - apply attr. use prohibitions if restricting
18695     */
18696     res = xmlSchemaFixupTypeAttributeUses(pctxt, type);
18697     HFAILURE HERROR
18698     /*
18699     * Apply the complex type component constraints; this will not
18700     * check attributes, since this is done in
18701     * xmlSchemaFixupTypeAttributeUses().
18702     */
18703     res = xmlSchemaCheckCTComponent(pctxt, type);
18704     HFAILURE HERROR
18705 
18706 #ifdef DEBUG_TYPE
18707     xmlSchemaDebugFixedType(pctxt, type);
18708 #endif
18709     if (olderrs != pctxt->nberrors)
18710 	return(pctxt->err);
18711     else
18712 	return(0);
18713 
18714 exit_error:
18715     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18716 #ifdef DEBUG_TYPE
18717     xmlSchemaDebugFixedType(pctxt, type);
18718 #endif
18719     return(pctxt->err);
18720 
18721 exit_failure:
18722     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18723 #ifdef DEBUG_TYPE
18724     xmlSchemaDebugFixedType(pctxt, type);
18725 #endif
18726     return(-1);
18727 }
18728 
18729 
18730 /**
18731  * xmlSchemaTypeFixup:
18732  * @typeDecl:  the schema type definition
18733  * @ctxt:  the schema parser context
18734  *
18735  * Fixes the content model of the type.
18736  * URGENT TODO: We need an int result!
18737  */
18738 static int
xmlSchemaTypeFixup(xmlSchemaTypePtr type,xmlSchemaAbstractCtxtPtr actxt)18739 xmlSchemaTypeFixup(xmlSchemaTypePtr type,
18740                    xmlSchemaAbstractCtxtPtr actxt)
18741 {
18742     if (type == NULL)
18743         return(0);
18744     if (actxt->type != XML_SCHEMA_CTXT_PARSER) {
18745 	AERROR_INT("xmlSchemaTypeFixup",
18746 	    "this function needs a parser context");
18747 	return(-1);
18748     }
18749     if (! WXS_IS_TYPE_NOT_FIXED(type))
18750 	return(0);
18751     if (type->type == XML_SCHEMA_TYPE_COMPLEX)
18752 	return(xmlSchemaFixupComplexType(PCTXT_CAST actxt, type));
18753     else if (type->type == XML_SCHEMA_TYPE_SIMPLE)
18754 	return(xmlSchemaFixupSimpleTypeStageTwo(PCTXT_CAST actxt, type));
18755     return(0);
18756 }
18757 
18758 /**
18759  * xmlSchemaCheckFacet:
18760  * @facet:  the facet
18761  * @typeDecl:  the schema type definition
18762  * @pctxt:  the schema parser context or NULL
18763  * @name: the optional name of the type
18764  *
18765  * Checks and computes the values of facets.
18766  *
18767  * Returns 0 if valid, a positive error code if not valid and
18768  *         -1 in case of an internal or API error.
18769  */
18770 int
xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,xmlSchemaTypePtr typeDecl,xmlSchemaParserCtxtPtr pctxt,const xmlChar * name ATTRIBUTE_UNUSED)18771 xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
18772                     xmlSchemaTypePtr typeDecl,
18773                     xmlSchemaParserCtxtPtr pctxt,
18774 		    const xmlChar * name ATTRIBUTE_UNUSED)
18775 {
18776     int ret = 0, ctxtGiven;
18777 
18778     if ((facet == NULL) || (typeDecl == NULL))
18779         return(-1);
18780     /*
18781     * TODO: will the parser context be given if used from
18782     * the relaxNG module?
18783     */
18784     if (pctxt == NULL)
18785 	ctxtGiven = 0;
18786     else
18787 	ctxtGiven = 1;
18788 
18789     switch (facet->type) {
18790         case XML_SCHEMA_FACET_MININCLUSIVE:
18791         case XML_SCHEMA_FACET_MINEXCLUSIVE:
18792         case XML_SCHEMA_FACET_MAXINCLUSIVE:
18793         case XML_SCHEMA_FACET_MAXEXCLUSIVE:
18794 	case XML_SCHEMA_FACET_ENUMERATION: {
18795                 /*
18796                  * Okay we need to validate the value
18797                  * at that point.
18798                  */
18799 		xmlSchemaTypePtr base;
18800 
18801 		/* 4.3.5.5 Constraints on enumeration Schema Components
18802 		* Schema Component Constraint: enumeration valid restriction
18803 		* It is an `error` if any member of {value} is not in the
18804 		* `value space` of {base type definition}.
18805 		*
18806 		* minInclusive, maxInclusive, minExclusive, maxExclusive:
18807 		* The value `must` be in the
18808 		* `value space` of the `base type`.
18809 		*/
18810 		/*
18811 		* This function is intended to deliver a compiled value
18812 		* on the facet. In this implementation of XML Schemata the
18813 		* type holding a facet, won't be a built-in type.
18814 		* Thus to ensure that other API
18815 		* calls (relaxng) do work, if the given type is a built-in
18816 		* type, we will assume that the given built-in type *is
18817 		* already* the base type.
18818 		*/
18819 		if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
18820 		    base = typeDecl->baseType;
18821 		    if (base == NULL) {
18822 			PERROR_INT("xmlSchemaCheckFacet",
18823 			    "a type user derived type has no base type");
18824 			return (-1);
18825 		    }
18826 		} else
18827 		    base = typeDecl;
18828 
18829 		if (! ctxtGiven) {
18830 		    /*
18831 		    * A context is needed if called from RelaxNG.
18832 		    */
18833 		    pctxt = xmlSchemaNewParserCtxt("*");
18834 		    if (pctxt == NULL)
18835 			return (-1);
18836 		}
18837 		/*
18838 		* NOTE: This call does not check the content nodes,
18839 		* since they are not available:
18840 		* facet->node is just the node holding the facet
18841 		* definition, *not* the attribute holding the *value*
18842 		* of the facet.
18843 		*/
18844 		ret = xmlSchemaVCheckCVCSimpleType(
18845 		    ACTXT_CAST pctxt, facet->node, base,
18846 		    facet->value, &(facet->val), 1, 1, 0);
18847                 if (ret != 0) {
18848 		    if (ret < 0) {
18849 			/* No error message for RelaxNG. */
18850 			if (ctxtGiven) {
18851 			    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18852 				XML_SCHEMAP_INTERNAL, facet->node, NULL,
18853 				"Internal error: xmlSchemaCheckFacet, "
18854 				"failed to validate the value '%s' of the "
18855 				"facet '%s' against the base type",
18856 				facet->value, xmlSchemaFacetTypeToString(facet->type));
18857 			}
18858 			goto internal_error;
18859 		    }
18860 		    ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18861 		    /* No error message for RelaxNG. */
18862 		    if (ctxtGiven) {
18863 			xmlChar *str = NULL;
18864 
18865 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
18866 			    ret, facet->node, WXS_BASIC_CAST facet,
18867 			    "The value '%s' of the facet does not validate "
18868 			    "against the base type '%s'",
18869 			    facet->value,
18870 			    xmlSchemaFormatQName(&str,
18871 				base->targetNamespace, base->name));
18872 			FREE_AND_NULL(str);
18873 		    }
18874 		    goto exit;
18875                 } else if (facet->val == NULL) {
18876 		    if (ctxtGiven) {
18877 			PERROR_INT("xmlSchemaCheckFacet",
18878 			    "value was not computed");
18879 		    }
18880 		    TODO
18881 		}
18882                 break;
18883             }
18884         case XML_SCHEMA_FACET_PATTERN:
18885             facet->regexp = xmlRegexpCompile(facet->value);
18886             if (facet->regexp == NULL) {
18887 		ret = XML_SCHEMAP_REGEXP_INVALID;
18888 		/* No error message for RelaxNG. */
18889 		if (ctxtGiven) {
18890 		    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18891 			ret, facet->node, WXS_BASIC_CAST typeDecl,
18892 			"The value '%s' of the facet 'pattern' is not a "
18893 			"valid regular expression",
18894 			facet->value, NULL);
18895 		}
18896             }
18897             break;
18898         case XML_SCHEMA_FACET_TOTALDIGITS:
18899         case XML_SCHEMA_FACET_FRACTIONDIGITS:
18900         case XML_SCHEMA_FACET_LENGTH:
18901         case XML_SCHEMA_FACET_MAXLENGTH:
18902         case XML_SCHEMA_FACET_MINLENGTH:
18903 
18904 	    if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
18905 		ret = xmlSchemaValidatePredefinedType(
18906 		    xmlSchemaGetBuiltInType(XML_SCHEMAS_PINTEGER),
18907 		    facet->value, &(facet->val));
18908 	    } else {
18909 		ret = xmlSchemaValidatePredefinedType(
18910 		    xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
18911 		    facet->value, &(facet->val));
18912 	    }
18913 	    if (ret != 0) {
18914 		if (ret < 0) {
18915 		    /* No error message for RelaxNG. */
18916 		    if (ctxtGiven) {
18917 			PERROR_INT("xmlSchemaCheckFacet",
18918 			    "validating facet value");
18919 		    }
18920 		    goto internal_error;
18921 		}
18922 		ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18923 		/* No error message for RelaxNG. */
18924 		if (ctxtGiven) {
18925 		    /* error code */
18926 		    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
18927 			ret, facet->node, WXS_BASIC_CAST typeDecl,
18928 			"The value '%s' of the facet '%s' is not a valid '%s'",
18929 			facet->value,
18930 			xmlSchemaFacetTypeToString(facet->type),
18931 			(facet->type != XML_SCHEMA_FACET_TOTALDIGITS) ?
18932 			    BAD_CAST "nonNegativeInteger" :
18933 			    BAD_CAST "positiveInteger",
18934 			NULL);
18935 		}
18936 	    }
18937 	    break;
18938 
18939         case XML_SCHEMA_FACET_WHITESPACE:{
18940                 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
18941                     facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
18942                 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
18943                     facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
18944                 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
18945                     facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
18946                 } else {
18947 		    ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18948                     /* No error message for RelaxNG. */
18949 		    if (ctxtGiven) {
18950 			/* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
18951 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
18952 			    ret, facet->node, WXS_BASIC_CAST typeDecl,
18953 			    "The value '%s' of the facet 'whitespace' is not "
18954 			    "valid", facet->value, NULL);
18955                     }
18956                 }
18957             }
18958         default:
18959             break;
18960     }
18961 exit:
18962     if ((! ctxtGiven) && (pctxt != NULL))
18963 	xmlSchemaFreeParserCtxt(pctxt);
18964     return (ret);
18965 internal_error:
18966     if ((! ctxtGiven) && (pctxt != NULL))
18967 	xmlSchemaFreeParserCtxt(pctxt);
18968     return (-1);
18969 }
18970 
18971 /**
18972  * xmlSchemaCheckFacetValues:
18973  * @typeDecl:  the schema type definition
18974  * @ctxt:  the schema parser context
18975  *
18976  * Checks the default values types, especially for facets
18977  */
18978 static int
xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,xmlSchemaParserCtxtPtr pctxt)18979 xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
18980 			  xmlSchemaParserCtxtPtr pctxt)
18981 {
18982     int res, olderrs = pctxt->nberrors;
18983     const xmlChar *name = typeDecl->name;
18984     /*
18985     * NOTE: It is intended to use the facets list, instead
18986     * of facetSet.
18987     */
18988     if (typeDecl->facets != NULL) {
18989 	xmlSchemaFacetPtr facet = typeDecl->facets;
18990 
18991 	/*
18992 	* Temporarily assign the "schema" to the validation context
18993 	* of the parser context. This is needed for NOTATION validation.
18994 	*/
18995 	if (pctxt->vctxt == NULL) {
18996 	    if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1)
18997 		return(-1);
18998 	}
18999 	pctxt->vctxt->schema = pctxt->schema;
19000 	while (facet != NULL) {
19001 	    res = xmlSchemaCheckFacet(facet, typeDecl, pctxt, name);
19002 	    HFAILURE
19003 	    facet = facet->next;
19004 	}
19005 	pctxt->vctxt->schema = NULL;
19006     }
19007     if (olderrs != pctxt->nberrors)
19008 	return(pctxt->err);
19009     return(0);
19010 exit_failure:
19011     return(-1);
19012 }
19013 
19014 /**
19015  * xmlSchemaGetCircModelGrDefRef:
19016  * @ctxtMGroup: the searched model group
19017  * @selfMGroup: the second searched model group
19018  * @particle: the first particle
19019  *
19020  * This one is intended to be used by
19021  * xmlSchemaCheckGroupDefCircular only.
19022  *
19023  * Returns the particle with the circular model group definition reference,
19024  * otherwise NULL.
19025  */
19026 static xmlSchemaTreeItemPtr
xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,xmlSchemaTreeItemPtr particle)19027 xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
19028 			      xmlSchemaTreeItemPtr particle)
19029 {
19030     xmlSchemaTreeItemPtr circ = NULL;
19031     xmlSchemaTreeItemPtr term;
19032     xmlSchemaModelGroupDefPtr gdef;
19033 
19034     for (; particle != NULL; particle = particle->next) {
19035 	term = particle->children;
19036 	if (term == NULL)
19037 	    continue;
19038 	switch (term->type) {
19039 	    case XML_SCHEMA_TYPE_GROUP:
19040 		gdef = (xmlSchemaModelGroupDefPtr) term;
19041 		if (gdef == groupDef)
19042 		    return (particle);
19043 		/*
19044 		* Mark this model group definition to avoid infinite
19045 		* recursion on circular references not yet examined.
19046 		*/
19047 		if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
19048 		    continue;
19049 		if (gdef->children != NULL) {
19050 		    gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
19051 		    circ = xmlSchemaGetCircModelGrDefRef(groupDef,
19052 			gdef->children->children);
19053 		    gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
19054 		    if (circ != NULL)
19055 			return (circ);
19056 		}
19057 		break;
19058 	    case XML_SCHEMA_TYPE_SEQUENCE:
19059 	    case XML_SCHEMA_TYPE_CHOICE:
19060 	    case XML_SCHEMA_TYPE_ALL:
19061 		circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
19062 		if (circ != NULL)
19063 		    return (circ);
19064 		break;
19065 	    default:
19066 		break;
19067 	}
19068     }
19069     return (NULL);
19070 }
19071 
19072 /**
19073  * xmlSchemaCheckGroupDefCircular:
19074  * @item:  the model group definition
19075  * @ctxt:  the parser context
19076  * @name:  the name
19077  *
19078  * Checks for circular references to model group definitions.
19079  */
19080 static void
xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,xmlSchemaParserCtxtPtr ctxt)19081 xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
19082 			       xmlSchemaParserCtxtPtr ctxt)
19083 {
19084     /*
19085     * Schema Component Constraint: Model Group Correct
19086     * 2 Circular groups are disallowed. That is, within the {particles}
19087     * of a group there must not be at any depth a particle whose {term}
19088     * is the group itself.
19089     */
19090     if ((item == NULL) ||
19091 	(item->type != XML_SCHEMA_TYPE_GROUP) ||
19092 	(item->children == NULL))
19093 	return;
19094     {
19095 	xmlSchemaTreeItemPtr circ;
19096 
19097 	circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
19098 	if (circ != NULL) {
19099 	    xmlChar *str = NULL;
19100 	    /*
19101 	    * TODO: The error report is not adequate: this constraint
19102 	    * is defined for model groups but not definitions, but since
19103 	    * there cannot be any circular model groups without a model group
19104 	    * definition (if not using a construction API), we check those
19105 	    * definitions only.
19106 	    */
19107 	    xmlSchemaPCustomErr(ctxt,
19108 		XML_SCHEMAP_MG_PROPS_CORRECT_2,
19109 		NULL, WXS_ITEM_NODE(circ),
19110 		"Circular reference to the model group definition '%s' "
19111 		"defined", xmlSchemaFormatQName(&str,
19112 		    item->targetNamespace, item->name));
19113 	    FREE_AND_NULL(str)
19114 	    /*
19115 	    * NOTE: We will cut the reference to avoid further
19116 	    * confusion of the processor. This is a fatal error.
19117 	    */
19118 	    circ->children = NULL;
19119 	}
19120     }
19121 }
19122 
19123 /**
19124  * xmlSchemaModelGroupToModelGroupDefFixup:
19125  * @ctxt:  the parser context
19126  * @mg:  the model group
19127  *
19128  * Assigns the model group of model group definitions to the "term"
19129  * of the referencing particle.
19130  * In xmlSchemaResolveModelGroupParticleReferences the model group
19131  * definitions were assigned to the "term", since needed for the
19132  * circularity check.
19133  *
19134  * Schema Component Constraint:
19135  *     All Group Limited (cos-all-limited) (1.2)
19136  */
19137 static void
xmlSchemaModelGroupToModelGroupDefFixup(xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,xmlSchemaModelGroupPtr mg)19138 xmlSchemaModelGroupToModelGroupDefFixup(
19139     xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
19140     xmlSchemaModelGroupPtr mg)
19141 {
19142     xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
19143 
19144     while (particle != NULL) {
19145 	if ((WXS_PARTICLE_TERM(particle) == NULL) ||
19146 	    ((WXS_PARTICLE_TERM(particle))->type !=
19147 		XML_SCHEMA_TYPE_GROUP))
19148 	{
19149 	    particle = WXS_PTC_CAST particle->next;
19150 	    continue;
19151 	}
19152 	if (WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle)) == NULL) {
19153 	    /*
19154 	    * TODO: Remove the particle.
19155 	    */
19156 	    WXS_PARTICLE_TERM(particle) = NULL;
19157 	    particle = WXS_PTC_CAST particle->next;
19158 	    continue;
19159 	}
19160 	/*
19161 	* Assign the model group to the {term} of the particle.
19162 	*/
19163 	WXS_PARTICLE_TERM(particle) =
19164 	    WXS_TREE_CAST WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle));
19165 
19166 	particle = WXS_PTC_CAST particle->next;
19167     }
19168 }
19169 
19170 /**
19171  * xmlSchemaCheckAttrGroupCircularRecur:
19172  * @ctxtGr: the searched attribute group
19173  * @attr: the current attribute list to be processed
19174  *
19175  * This one is intended to be used by
19176  * xmlSchemaCheckAttrGroupCircular only.
19177  *
19178  * Returns the circular attribute group reference, otherwise NULL.
19179  */
19180 static xmlSchemaQNameRefPtr
xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,xmlSchemaItemListPtr list)19181 xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,
19182 				     xmlSchemaItemListPtr list)
19183 {
19184     xmlSchemaAttributeGroupPtr gr;
19185     xmlSchemaQNameRefPtr ref, circ;
19186     int i;
19187     /*
19188     * We will search for an attribute group reference which
19189     * references the context attribute group.
19190     */
19191     for (i = 0; i < list->nbItems; i++) {
19192 	ref = list->items[i];
19193 	if ((ref->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19194 	    (ref->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
19195 	    (ref->item != NULL))
19196 	{
19197 	    gr = WXS_ATTR_GROUP_CAST ref->item;
19198 	    if (gr == ctxtGr)
19199 		return(ref);
19200 	    if (gr->flags & XML_SCHEMAS_ATTRGROUP_MARKED)
19201 		continue;
19202 	    /*
19203 	    * Mark as visited to avoid infinite recursion on
19204 	    * circular references not yet examined.
19205 	    */
19206 	    if ((gr->attrUses) &&
19207 		(gr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS))
19208 	    {
19209 		gr->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
19210 		circ = xmlSchemaCheckAttrGroupCircularRecur(ctxtGr,
19211 		    (xmlSchemaItemListPtr) gr->attrUses);
19212 		gr->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
19213 		if (circ != NULL)
19214 		    return (circ);
19215 	    }
19216 
19217 	}
19218     }
19219     return (NULL);
19220 }
19221 
19222 /**
19223  * xmlSchemaCheckAttrGroupCircular:
19224  * attrGr:  the attribute group definition
19225  * @ctxt:  the parser context
19226  * @name:  the name
19227  *
19228  * Checks for circular references of attribute groups.
19229  */
19230 static int
xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,xmlSchemaParserCtxtPtr ctxt)19231 xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
19232 				xmlSchemaParserCtxtPtr ctxt)
19233 {
19234     /*
19235     * Schema Representation Constraint:
19236     * Attribute Group Definition Representation OK
19237     * 3 Circular group reference is disallowed outside <redefine>.
19238     * That is, unless this element information item's parent is
19239     * <redefine>, then among the [children], if any, there must
19240     * not be an <attributeGroup> with ref [attribute] which resolves
19241     * to the component corresponding to this <attributeGroup>. Indirect
19242     * circularity is also ruled out. That is, when QName resolution
19243     * (Schema Document) ($3.15.3) is applied to a `QName` arising from
19244     * any <attributeGroup>s with a ref [attribute] among the [children],
19245     * it must not be the case that a `QName` is encountered at any depth
19246     * which resolves to the component corresponding to this <attributeGroup>.
19247     */
19248     if (attrGr->attrUses == NULL)
19249 	return(0);
19250     else if ((attrGr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS) == 0)
19251 	return(0);
19252     else {
19253 	xmlSchemaQNameRefPtr circ;
19254 
19255 	circ = xmlSchemaCheckAttrGroupCircularRecur(attrGr,
19256 	    (xmlSchemaItemListPtr) attrGr->attrUses);
19257 	if (circ != NULL) {
19258 	    xmlChar *str = NULL;
19259 	    /*
19260 	    * TODO: Report the referenced attr group as QName.
19261 	    */
19262 	    xmlSchemaPCustomErr(ctxt,
19263 		XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
19264 		NULL, WXS_ITEM_NODE(WXS_BASIC_CAST circ),
19265 		"Circular reference to the attribute group '%s' "
19266 		"defined", xmlSchemaGetComponentQName(&str, attrGr));
19267 	    FREE_AND_NULL(str);
19268 	    /*
19269 	    * NOTE: We will cut the reference to avoid further
19270 	    * confusion of the processor.
19271 	    * BADSPEC TODO: The spec should define how to process in this case.
19272 	    */
19273 	    circ->item = NULL;
19274 	    return(ctxt->err);
19275 	}
19276     }
19277     return(0);
19278 }
19279 
19280 static int
19281 xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19282 				  xmlSchemaAttributeGroupPtr attrGr);
19283 
19284 /**
19285  * xmlSchemaExpandAttributeGroupRefs:
19286  * @pctxt: the parser context
19287  * @node: the node of the component holding the attribute uses
19288  * @completeWild: the intersected wildcard to be returned
19289  * @list: the attribute uses
19290  *
19291  * Substitutes contained attribute group references
19292  * for their attribute uses. Wildcards are intersected.
19293  * Attribute use prohibitions are removed from the list
19294  * and returned via the @prohibs list.
19295  * Pointlessness of attr. prohibs, if a matching attr. decl
19296  * is existent a well, are checked.
19297  */
19298 static int
xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBasicItemPtr item,xmlSchemaWildcardPtr * completeWild,xmlSchemaItemListPtr list,xmlSchemaItemListPtr prohibs)19299 xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
19300 				  xmlSchemaBasicItemPtr item,
19301 				  xmlSchemaWildcardPtr *completeWild,
19302 				  xmlSchemaItemListPtr list,
19303 				  xmlSchemaItemListPtr prohibs)
19304 {
19305     xmlSchemaAttributeGroupPtr gr;
19306     xmlSchemaAttributeUsePtr use;
19307     xmlSchemaItemListPtr sublist;
19308     int i, j;
19309     int created = (*completeWild == NULL) ? 0 : 1;
19310 
19311     if (prohibs)
19312 	prohibs->nbItems = 0;
19313 
19314     for (i = 0; i < list->nbItems; i++) {
19315 	use = list->items[i];
19316 
19317 	if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
19318 	    if (prohibs == NULL) {
19319 		PERROR_INT("xmlSchemaExpandAttributeGroupRefs",
19320 		    "unexpected attr prohibition found");
19321 		return(-1);
19322 	    }
19323 	    /*
19324 	    * Remove from attribute uses.
19325 	    */
19326 	    if (xmlSchemaItemListRemove(list, i) == -1)
19327 		return(-1);
19328 	    i--;
19329 	    /*
19330 	    * Note that duplicate prohibitions were already
19331 	    * handled at parsing time.
19332 	    */
19333 	    /*
19334 	    * Add to list of prohibitions.
19335 	    */
19336 	    xmlSchemaItemListAddSize(prohibs, 2, use);
19337 	    continue;
19338 	}
19339 	if ((use->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19340 	    ((WXS_QNAME_CAST use)->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP))
19341 	{
19342 	    if ((WXS_QNAME_CAST use)->item == NULL)
19343 		return(-1);
19344 	    gr = WXS_ATTR_GROUP_CAST (WXS_QNAME_CAST use)->item;
19345 	    /*
19346 	    * Expand the referenced attr. group.
19347 	    * TODO: remove this, this is done in a previous step, so
19348 	    * already done here.
19349 	    */
19350 	    if ((gr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
19351 		if (xmlSchemaAttributeGroupExpandRefs(pctxt, gr) == -1)
19352 		    return(-1);
19353 	    }
19354 	    /*
19355 	    * Build the 'complete' wildcard; i.e. intersect multiple
19356 	    * wildcards.
19357 	    */
19358 	    if (gr->attributeWildcard != NULL) {
19359 		if (*completeWild == NULL) {
19360 		    *completeWild = gr->attributeWildcard;
19361 		} else {
19362 		    if (! created) {
19363 			xmlSchemaWildcardPtr tmpWild;
19364 
19365 			 /*
19366 			* Copy the first encountered wildcard as context,
19367 			* except for the annotation.
19368 			*
19369 			* Although the complete wildcard might not correspond
19370 			* to any node in the schema, we will anchor it on
19371 			* the node of the owner component.
19372 			*/
19373 			tmpWild =  xmlSchemaAddWildcard(pctxt, pctxt->schema,
19374 			    XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
19375 			    WXS_ITEM_NODE(item));
19376 			if (tmpWild == NULL)
19377 			    return(-1);
19378 			if (xmlSchemaCloneWildcardNsConstraints(pctxt,
19379 			    tmpWild, *completeWild) == -1)
19380 			    return (-1);
19381 			tmpWild->processContents = (*completeWild)->processContents;
19382 			*completeWild = tmpWild;
19383 			created = 1;
19384 		    }
19385 
19386 		    if (xmlSchemaIntersectWildcards(pctxt, *completeWild,
19387 			gr->attributeWildcard) == -1)
19388 			return(-1);
19389 		}
19390 	    }
19391 	    /*
19392 	    * Just remove the reference if the referenced group does not
19393 	    * contain any attribute uses.
19394 	    */
19395 	    sublist = ((xmlSchemaItemListPtr) gr->attrUses);
19396 	    if ((sublist == NULL) || sublist->nbItems == 0) {
19397 		if (xmlSchemaItemListRemove(list, i) == -1)
19398 		    return(-1);
19399 		i--;
19400 		continue;
19401 	    }
19402 	    /*
19403 	    * Add the attribute uses.
19404 	    */
19405 	    list->items[i] = sublist->items[0];
19406 	    if (sublist->nbItems != 1) {
19407 		for (j = 1; j < sublist->nbItems; j++) {
19408 		    i++;
19409 		    if (xmlSchemaItemListInsert(list,
19410 			    sublist->items[j], i) == -1)
19411 			return(-1);
19412 		}
19413 	    }
19414 	}
19415 
19416     }
19417     /*
19418     * Handle pointless prohibitions of declared attributes.
19419     */
19420     if (prohibs && (prohibs->nbItems != 0) && (list->nbItems != 0)) {
19421 	xmlSchemaAttributeUseProhibPtr prohib;
19422 
19423 	for (i = prohibs->nbItems -1; i >= 0; i--) {
19424 	    prohib = prohibs->items[i];
19425 	    for (j = 0; j < list->nbItems; j++) {
19426 		use = list->items[j];
19427 
19428 		if ((prohib->name == WXS_ATTRUSE_DECL_NAME(use)) &&
19429 		    (prohib->targetNamespace == WXS_ATTRUSE_DECL_TNS(use)))
19430 		{
19431 		    xmlChar *str = NULL;
19432 
19433 		    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
19434 			XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
19435 			prohib->node, NULL,
19436 			"Skipping pointless attribute use prohibition "
19437 			"'%s', since a corresponding attribute use "
19438 			"exists already in the type definition",
19439 			xmlSchemaFormatQName(&str,
19440 			    prohib->targetNamespace, prohib->name),
19441 			NULL, NULL);
19442 		    FREE_AND_NULL(str);
19443 		    /*
19444 		    * Remove the prohibition.
19445 		    */
19446 		    if (xmlSchemaItemListRemove(prohibs, i) == -1)
19447 			return(-1);
19448 		    break;
19449 		}
19450 	    }
19451 	}
19452     }
19453     return(0);
19454 }
19455 
19456 /**
19457  * xmlSchemaAttributeGroupExpandRefs:
19458  * @pctxt:  the parser context
19459  * @attrGr:  the attribute group definition
19460  *
19461  * Computation of:
19462  * {attribute uses} property
19463  * {attribute wildcard} property
19464  *
19465  * Substitutes contained attribute group references
19466  * for their attribute uses. Wildcards are intersected.
19467  */
19468 static int
xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,xmlSchemaAttributeGroupPtr attrGr)19469 xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19470 				  xmlSchemaAttributeGroupPtr attrGr)
19471 {
19472     if ((attrGr->attrUses == NULL) ||
19473 	(attrGr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED))
19474 	return(0);
19475 
19476     attrGr->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
19477     if (xmlSchemaExpandAttributeGroupRefs(pctxt, WXS_BASIC_CAST attrGr,
19478 	&(attrGr->attributeWildcard), attrGr->attrUses, NULL) == -1)
19479 	return(-1);
19480     return(0);
19481 }
19482 
19483 /**
19484  * xmlSchemaAttributeGroupExpandRefs:
19485  * @pctxt:  the parser context
19486  * @attrGr:  the attribute group definition
19487  *
19488  * Substitutes contained attribute group references
19489  * for their attribute uses. Wildcards are intersected.
19490  *
19491  * Schema Component Constraint:
19492  *    Attribute Group Definition Properties Correct (ag-props-correct)
19493  */
19494 static int
xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,xmlSchemaAttributeGroupPtr attrGr)19495 xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19496 				  xmlSchemaAttributeGroupPtr attrGr)
19497 {
19498     /*
19499     * SPEC ag-props-correct
19500     * (1) "The values of the properties of an attribute group definition
19501     * must be as described in the property tableau in The Attribute
19502     * Group Definition Schema Component ($3.6.1), modulo the impact of
19503     * Missing Sub-components ($5.3);"
19504     */
19505 
19506     if ((attrGr->attrUses != NULL) &&
19507 	(WXS_LIST_CAST attrGr->attrUses)->nbItems > 1)
19508     {
19509 	xmlSchemaItemListPtr uses = WXS_LIST_CAST attrGr->attrUses;
19510 	xmlSchemaAttributeUsePtr use, tmp;
19511 	int i, j, hasId = 0;
19512 
19513 	for (i = uses->nbItems -1; i >= 0; i--) {
19514 	    use = uses->items[i];
19515 	    /*
19516 	    * SPEC ag-props-correct
19517 	    * (2) "Two distinct members of the {attribute uses} must not have
19518 	    * {attribute declaration}s both of whose {name}s match and whose
19519 	    * {target namespace}s are identical."
19520 	    */
19521 	    if (i > 0) {
19522 		for (j = i -1; j >= 0; j--) {
19523 		    tmp = uses->items[j];
19524 		    if ((WXS_ATTRUSE_DECL_NAME(use) ==
19525 			WXS_ATTRUSE_DECL_NAME(tmp)) &&
19526 			(WXS_ATTRUSE_DECL_TNS(use) ==
19527 			WXS_ATTRUSE_DECL_TNS(tmp)))
19528 		    {
19529 			xmlChar *str = NULL;
19530 
19531 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
19532 			    XML_SCHEMAP_AG_PROPS_CORRECT,
19533 			    attrGr->node, WXS_BASIC_CAST attrGr,
19534 			    "Duplicate %s",
19535 			    xmlSchemaGetComponentDesignation(&str, use),
19536 			    NULL);
19537 			FREE_AND_NULL(str);
19538 			/*
19539 			* Remove the duplicate.
19540 			*/
19541 			if (xmlSchemaItemListRemove(uses, i) == -1)
19542 			    return(-1);
19543 			goto next_use;
19544 		    }
19545 		}
19546 	    }
19547 	    /*
19548 	    * SPEC ag-props-correct
19549 	    * (3) "Two distinct members of the {attribute uses} must not have
19550 	    * {attribute declaration}s both of whose {type definition}s are or
19551 	    * are derived from ID."
19552 	    * TODO: Does 'derived' include member-types of unions?
19553 	    */
19554 	    if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
19555 		if (xmlSchemaIsDerivedFromBuiltInType(
19556 		    WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
19557 		{
19558 		    if (hasId) {
19559 			xmlChar *str = NULL;
19560 
19561 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
19562 			    XML_SCHEMAP_AG_PROPS_CORRECT,
19563 			    attrGr->node, WXS_BASIC_CAST attrGr,
19564 			    "There must not exist more than one attribute "
19565 			    "declaration of type 'xs:ID' "
19566 			    "(or derived from 'xs:ID'). The %s violates this "
19567 			    "constraint",
19568 			    xmlSchemaGetComponentDesignation(&str, use),
19569 			    NULL);
19570 			FREE_AND_NULL(str);
19571 			if (xmlSchemaItemListRemove(uses, i) == -1)
19572 			    return(-1);
19573 		    }
19574 		    hasId = 1;
19575 		}
19576 	    }
19577 next_use: {}
19578 	}
19579     }
19580     return(0);
19581 }
19582 
19583 /**
19584  * xmlSchemaResolveAttrGroupReferences:
19585  * @attrgrpDecl:  the schema attribute definition
19586  * @ctxt:  the schema parser context
19587  * @name:  the attribute name
19588  *
19589  * Resolves references to attribute group definitions.
19590  */
19591 static int
xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,xmlSchemaParserCtxtPtr ctxt)19592 xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,
19593 				    xmlSchemaParserCtxtPtr ctxt)
19594 {
19595     xmlSchemaAttributeGroupPtr group;
19596 
19597     if (ref->item != NULL)
19598         return(0);
19599     group = xmlSchemaGetAttributeGroup(ctxt->schema,
19600 	ref->name,
19601 	ref->targetNamespace);
19602     if (group == NULL) {
19603 	xmlSchemaPResCompAttrErr(ctxt,
19604 	    XML_SCHEMAP_SRC_RESOLVE,
19605 	    NULL, ref->node,
19606 	    "ref", ref->name, ref->targetNamespace,
19607 	    ref->itemType, NULL);
19608 	return(ctxt->err);
19609     }
19610     ref->item = WXS_BASIC_CAST group;
19611     return(0);
19612 }
19613 
19614 /**
19615  * xmlSchemaCheckAttrPropsCorrect:
19616  * @item:  an schema attribute declaration/use
19617  * @ctxt:  a schema parser context
19618  * @name:  the name of the attribute
19619  *
19620  *
19621  * Schema Component Constraint:
19622  *    Attribute Declaration Properties Correct (a-props-correct)
19623  *
19624  * Validates the value constraints of an attribute declaration/use.
19625  * NOTE that this needs the simple type definitions to be already
19626  *   built and checked.
19627  */
19628 static int
xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,xmlSchemaAttributePtr attr)19629 xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19630 			       xmlSchemaAttributePtr attr)
19631 {
19632 
19633     /*
19634     * SPEC a-props-correct (1)
19635     * "The values of the properties of an attribute declaration must
19636     * be as described in the property tableau in The Attribute
19637     * Declaration Schema Component ($3.2.1), modulo the impact of
19638     * Missing Sub-components ($5.3)."
19639     */
19640 
19641     if (WXS_ATTR_TYPEDEF(attr) == NULL)
19642 	return(0);
19643 
19644     if (attr->defValue != NULL) {
19645 	int ret;
19646 
19647 	/*
19648 	* SPEC a-props-correct (3)
19649 	* "If the {type definition} is or is derived from ID then there
19650 	* must not be a {value constraint}."
19651 	*/
19652 	if (xmlSchemaIsDerivedFromBuiltInType(
19653 	    WXS_ATTR_TYPEDEF(attr), XML_SCHEMAS_ID))
19654 	{
19655 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
19656 		XML_SCHEMAP_A_PROPS_CORRECT_3,
19657 		NULL, WXS_BASIC_CAST attr,
19658 		"Value constraints are not allowed if the type definition "
19659 		"is or is derived from xs:ID",
19660 		NULL, NULL);
19661 	    return(pctxt->err);
19662 	}
19663 	/*
19664 	* SPEC a-props-correct (2)
19665 	* "if there is a {value constraint}, the canonical lexical
19666 	* representation of its value must be `valid` with respect
19667 	* to the {type definition} as defined in String Valid ($3.14.4)."
19668 	* TODO: Don't care about the *canonical* stuff here, this requirement
19669 	* will be removed in WXS 1.1 anyway.
19670 	*/
19671 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt,
19672 	    attr->node, WXS_ATTR_TYPEDEF(attr),
19673 	    attr->defValue, &(attr->defVal),
19674 	    1, 1, 0);
19675 	if (ret != 0) {
19676 	    if (ret < 0) {
19677 		PERROR_INT("xmlSchemaCheckAttrPropsCorrect",
19678 		    "calling xmlSchemaVCheckCVCSimpleType()");
19679 		return(-1);
19680 	    }
19681 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
19682 		XML_SCHEMAP_A_PROPS_CORRECT_2,
19683 		NULL, WXS_BASIC_CAST attr,
19684 		"The value of the value constraint is not valid",
19685 		NULL, NULL);
19686 	    return(pctxt->err);
19687 	}
19688     }
19689 
19690     return(0);
19691 }
19692 
19693 static xmlSchemaElementPtr
xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,xmlSchemaElementPtr ancestor)19694 xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
19695 				 xmlSchemaElementPtr ancestor)
19696 {
19697     xmlSchemaElementPtr ret;
19698 
19699     if (WXS_SUBST_HEAD(ancestor) == NULL)
19700 	return (NULL);
19701     if (WXS_SUBST_HEAD(ancestor) == elemDecl)
19702 	return (ancestor);
19703 
19704     if (WXS_SUBST_HEAD(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
19705 	return (NULL);
19706     WXS_SUBST_HEAD(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
19707     ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
19708 	WXS_SUBST_HEAD(ancestor));
19709     WXS_SUBST_HEAD(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
19710 
19711     return (ret);
19712 }
19713 
19714 /**
19715  * xmlSchemaCheckElemPropsCorrect:
19716  * @ctxt:  a schema parser context
19717  * @decl: the element declaration
19718  * @name:  the name of the attribute
19719  *
19720  * Schema Component Constraint:
19721  * Element Declaration Properties Correct (e-props-correct)
19722  *
19723  * STATUS:
19724  *   missing: (6)
19725  */
19726 static int
xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,xmlSchemaElementPtr elemDecl)19727 xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19728 			       xmlSchemaElementPtr elemDecl)
19729 {
19730     int ret = 0;
19731     xmlSchemaTypePtr typeDef = WXS_ELEM_TYPEDEF(elemDecl);
19732     /*
19733     * SPEC (1) "The values of the properties of an element declaration
19734     * must be as described in the property tableau in The Element
19735     * Declaration Schema Component ($3.3.1), modulo the impact of Missing
19736     * Sub-components ($5.3)."
19737     */
19738     if (WXS_SUBST_HEAD(elemDecl) != NULL) {
19739 	xmlSchemaElementPtr head = WXS_SUBST_HEAD(elemDecl), circ;
19740 
19741 	xmlSchemaCheckElementDeclComponent(head, pctxt);
19742 	/*
19743 	* SPEC (3) "If there is a non-`absent` {substitution group
19744 	* affiliation}, then {scope} must be global."
19745 	*/
19746 	if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
19747 	    xmlSchemaPCustomErr(pctxt,
19748 		XML_SCHEMAP_E_PROPS_CORRECT_3,
19749 		WXS_BASIC_CAST elemDecl, NULL,
19750 		"Only global element declarations can have a "
19751 		"substitution group affiliation", NULL);
19752 	    ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
19753 	}
19754 	/*
19755 	* TODO: SPEC (6) "Circular substitution groups are disallowed.
19756 	* That is, it must not be possible to return to an element declaration
19757 	* by repeatedly following the {substitution group affiliation}
19758 	* property."
19759 	*/
19760 	if (head == elemDecl)
19761 	    circ = head;
19762 	else if (WXS_SUBST_HEAD(head) != NULL)
19763 	    circ = xmlSchemaCheckSubstGroupCircular(head, head);
19764 	else
19765 	    circ = NULL;
19766 	if (circ != NULL) {
19767 	    xmlChar *strA = NULL, *strB = NULL;
19768 
19769 	    xmlSchemaPCustomErrExt(pctxt,
19770 		XML_SCHEMAP_E_PROPS_CORRECT_6,
19771 		WXS_BASIC_CAST circ, NULL,
19772 		"The element declaration '%s' defines a circular "
19773 		"substitution group to element declaration '%s'",
19774 		xmlSchemaGetComponentQName(&strA, circ),
19775 		xmlSchemaGetComponentQName(&strB, head),
19776 		NULL);
19777 	    FREE_AND_NULL(strA)
19778 	    FREE_AND_NULL(strB)
19779 	    ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
19780 	}
19781 	/*
19782 	* SPEC (4) "If there is a {substitution group affiliation},
19783 	* the {type definition}
19784 	* of the element declaration must be validly derived from the {type
19785 	* definition} of the {substitution group affiliation}, given the value
19786 	* of the {substitution group exclusions} of the {substitution group
19787 	* affiliation}, as defined in Type Derivation OK (Complex) ($3.4.6)
19788 	* (if the {type definition} is complex) or as defined in
19789 	* Type Derivation OK (Simple) ($3.14.6) (if the {type definition} is
19790 	* simple)."
19791 	*
19792 	* NOTE: {substitution group exclusions} means the values of the
19793 	* attribute "final".
19794 	*/
19795 
19796 	if (typeDef != WXS_ELEM_TYPEDEF(WXS_SUBST_HEAD(elemDecl))) {
19797 	    int set = 0;
19798 
19799 	    if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
19800 		set |= SUBSET_EXTENSION;
19801 	    if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
19802 		set |= SUBSET_RESTRICTION;
19803 
19804 	    if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST pctxt, typeDef,
19805 		WXS_ELEM_TYPEDEF(head), set) != 0) {
19806 		xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
19807 
19808 		ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
19809 		xmlSchemaPCustomErrExt(pctxt,
19810 		    XML_SCHEMAP_E_PROPS_CORRECT_4,
19811 		    WXS_BASIC_CAST elemDecl, NULL,
19812 		    "The type definition '%s' was "
19813 		    "either rejected by the substitution group "
19814 		    "affiliation '%s', or not validly derived from its type "
19815 		    "definition '%s'",
19816 		    xmlSchemaGetComponentQName(&strA, typeDef),
19817 		    xmlSchemaGetComponentQName(&strB, head),
19818 		    xmlSchemaGetComponentQName(&strC, WXS_ELEM_TYPEDEF(head)));
19819 		FREE_AND_NULL(strA)
19820 		FREE_AND_NULL(strB)
19821 		FREE_AND_NULL(strC)
19822 	    }
19823 	}
19824     }
19825     /*
19826     * SPEC (5) "If the {type definition} or {type definition}'s
19827     * {content type}
19828     * is or is derived from ID then there must not be a {value constraint}.
19829     * Note: The use of ID as a type definition for elements goes beyond
19830     * XML 1.0, and should be avoided if backwards compatibility is desired"
19831     */
19832     if ((elemDecl->value != NULL) &&
19833 	((WXS_IS_SIMPLE(typeDef) &&
19834 	  xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
19835 	 (WXS_IS_COMPLEX(typeDef) &&
19836 	  WXS_HAS_SIMPLE_CONTENT(typeDef) &&
19837 	  xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
19838 	    XML_SCHEMAS_ID)))) {
19839 
19840 	ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
19841 	xmlSchemaPCustomErr(pctxt,
19842 	    XML_SCHEMAP_E_PROPS_CORRECT_5,
19843 	    WXS_BASIC_CAST elemDecl, NULL,
19844 	    "The type definition (or type definition's content type) is or "
19845 	    "is derived from ID; value constraints are not allowed in "
19846 	    "conjunction with such a type definition", NULL);
19847     } else if (elemDecl->value != NULL) {
19848 	int vcret;
19849 	xmlNodePtr node = NULL;
19850 
19851 	/*
19852 	* SPEC (2) "If there is a {value constraint}, the canonical lexical
19853 	* representation of its value must be `valid` with respect to the
19854 	* {type definition} as defined in Element Default Valid (Immediate)
19855 	* ($3.3.6)."
19856 	*/
19857 	if (typeDef == NULL) {
19858 	    xmlSchemaPErr(pctxt, elemDecl->node,
19859 		XML_SCHEMAP_INTERNAL,
19860 		"Internal error: xmlSchemaCheckElemPropsCorrect, "
19861 		"type is missing... skipping validation of "
19862 		"the value constraint", NULL, NULL);
19863 	    return (-1);
19864 	}
19865 	if (elemDecl->node != NULL) {
19866 	    if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
19867 		node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19868 		    BAD_CAST "fixed");
19869 	    else
19870 		node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19871 		    BAD_CAST "default");
19872 	}
19873 	vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
19874 	    typeDef, elemDecl->value, &(elemDecl->defVal));
19875 	if (vcret != 0) {
19876 	    if (vcret < 0) {
19877 		PERROR_INT("xmlSchemaElemCheckValConstr",
19878 		    "failed to validate the value constraint of an "
19879 		    "element declaration");
19880 		return (-1);
19881 	    }
19882 	    return (vcret);
19883 	}
19884     }
19885 
19886     return (ret);
19887 }
19888 
19889 /**
19890  * xmlSchemaCheckElemSubstGroup:
19891  * @ctxt:  a schema parser context
19892  * @decl: the element declaration
19893  * @name:  the name of the attribute
19894  *
19895  * Schema Component Constraint:
19896  * Substitution Group (cos-equiv-class)
19897  *
19898  * In Libxml2 the subst. groups will be precomputed, in terms of that
19899  * a list will be built for each subst. group head, holding all direct
19900  * referents to this head.
19901  * NOTE that this function needs:
19902  *   1. circular subst. groups to be checked beforehand
19903  *   2. the declaration's type to be derived from the head's type
19904  *
19905  * STATUS:
19906  *
19907  */
19908 static void
xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,xmlSchemaElementPtr elemDecl)19909 xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
19910 			     xmlSchemaElementPtr elemDecl)
19911 {
19912     if ((WXS_SUBST_HEAD(elemDecl) == NULL) ||
19913 	/* SPEC (1) "Its {abstract} is false." */
19914 	(elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
19915 	return;
19916     {
19917 	xmlSchemaElementPtr head;
19918 	xmlSchemaTypePtr headType, type;
19919 	int set, methSet;
19920 	/*
19921 	* SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
19922 	* {disallowed substitutions} as the blocking constraint, as defined in
19923 	* Substitution Group OK (Transitive) ($3.3.6)."
19924 	*/
19925 	for (head = WXS_SUBST_HEAD(elemDecl); head != NULL;
19926 	    head = WXS_SUBST_HEAD(head)) {
19927 	    set = 0;
19928 	    methSet = 0;
19929 	    /*
19930 	    * The blocking constraints.
19931 	    */
19932 	    if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
19933 		continue;
19934 	    headType = head->subtypes;
19935 	    type = elemDecl->subtypes;
19936 	    if (headType == type)
19937 		goto add_member;
19938 	    if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
19939 		set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19940 	    if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
19941 		set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19942 	    /*
19943 	    * SPEC: Substitution Group OK (Transitive) (2.3)
19944 	    * "The set of all {derivation method}s involved in the
19945 	    * derivation of D's {type definition} from C's {type definition}
19946 	    * does not intersect with the union of the blocking constraint,
19947 	    * C's {prohibited substitutions} (if C is complex, otherwise the
19948 	    * empty set) and the {prohibited substitutions} (respectively the
19949 	    * empty set) of any intermediate {type definition}s in the
19950 	    * derivation of D's {type definition} from C's {type definition}."
19951 	    */
19952 	    /*
19953 	    * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
19954 	    * subst.head axis, the methSet does not need to be computed for
19955 	    * the full depth over and over.
19956 	    */
19957 	    /*
19958 	    * The set of all {derivation method}s involved in the derivation
19959 	    */
19960 	    while ((type != NULL) && (type != headType)) {
19961 		if ((WXS_IS_EXTENSION(type)) &&
19962 		    ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19963 		    methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19964 
19965 		if (WXS_IS_RESTRICTION(type) &&
19966 		    ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19967 		    methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19968 
19969 		type = type->baseType;
19970 	    }
19971 	    /*
19972 	    * The {prohibited substitutions} of all intermediate types +
19973 	    * the head's type.
19974 	    */
19975 	    type = elemDecl->subtypes->baseType;
19976 	    while (type != NULL) {
19977 		if (WXS_IS_COMPLEX(type)) {
19978 		    if ((type->flags &
19979 			    XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19980 			((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
19981 		    set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19982 		    if ((type->flags &
19983 			    XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19984 			((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19985 		    set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19986 		} else
19987 		    break;
19988 		if (type == headType)
19989 		    break;
19990 		type = type->baseType;
19991 	    }
19992 	    if ((set != 0) &&
19993 		(((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19994 		(methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
19995 		((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19996 		(methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
19997 		continue;
19998 	    }
19999 add_member:
20000 	    xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
20001 	    if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
20002 		head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
20003 	}
20004     }
20005 }
20006 
20007 #ifdef WXS_ELEM_DECL_CONS_ENABLED /* enable when finished */
20008 /**
20009  * xmlSchemaCheckElementDeclComponent
20010  * @pctxt: the schema parser context
20011  * @ctxtComponent: the context component (an element declaration)
20012  * @ctxtParticle: the first particle of the context component
20013  * @searchParticle: the element declaration particle to be analysed
20014  *
20015  * Schema Component Constraint: Element Declarations Consistent
20016  */
20017 static int
xmlSchemaCheckElementDeclConsistent(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBasicItemPtr ctxtComponent,xmlSchemaParticlePtr ctxtParticle,xmlSchemaParticlePtr searchParticle,xmlSchemaParticlePtr curParticle,int search)20018 xmlSchemaCheckElementDeclConsistent(xmlSchemaParserCtxtPtr pctxt,
20019 				    xmlSchemaBasicItemPtr ctxtComponent,
20020 				    xmlSchemaParticlePtr ctxtParticle,
20021 				    xmlSchemaParticlePtr searchParticle,
20022 				    xmlSchemaParticlePtr curParticle,
20023 				    int search)
20024 {
20025     return(0);
20026 
20027     int ret = 0;
20028     xmlSchemaParticlePtr cur = curParticle;
20029     if (curParticle == NULL) {
20030 	return(0);
20031     }
20032     if (WXS_PARTICLE_TERM(curParticle) == NULL) {
20033 	/*
20034 	* Just return in this case. A missing "term" of the particle
20035 	* might arise due to an invalid "term" component.
20036 	*/
20037 	return(0);
20038     }
20039     while (cur != NULL) {
20040 	switch (WXS_PARTICLE_TERM(cur)->type) {
20041 	    case XML_SCHEMA_TYPE_ANY:
20042 		break;
20043 	    case XML_SCHEMA_TYPE_ELEMENT:
20044 		if (search == 0) {
20045 		    ret = xmlSchemaCheckElementDeclConsistent(pctxt,
20046 			ctxtComponent, ctxtParticle, cur, ctxtParticle, 1);
20047 		    if (ret != 0)
20048 			return(ret);
20049 		} else {
20050 		    xmlSchemaElementPtr elem =
20051 			WXS_ELEM_CAST(WXS_PARTICLE_TERM(cur));
20052 		    /*
20053 		    * SPEC Element Declarations Consistent:
20054 		    * "If the {particles} contains, either directly,
20055 		    * indirectly (that is, within the {particles} of a
20056 		    * contained model group, recursively) or `implicitly`
20057 		    * two or more element declaration particles with
20058 		    * the same {name} and {target namespace}, then
20059 		    * all their type definitions must be the same
20060 		    * top-level definition [...]"
20061 		    */
20062 		    if (xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->name,
20063 			    WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->name) &&
20064 			xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
20065 			    WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->targetNamespace))
20066 		    {
20067 			xmlChar *strA = NULL, *strB = NULL;
20068 
20069 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
20070 			    /* TODO: error code */
20071 			    XML_SCHEMAP_COS_NONAMBIG,
20072 			    WXS_ITEM_NODE(cur), NULL,
20073 			    "In the content model of %s, there are multiple "
20074 			    "element declarations for '%s' with different "
20075 			    "type definitions",
20076 			    xmlSchemaGetComponentDesignation(&strA,
20077 				ctxtComponent),
20078 			    xmlSchemaFormatQName(&strB,
20079 				WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
20080 				WXS_PARTICLE_TERM_AS_ELEM(cur)->name));
20081 			FREE_AND_NULL(strA);
20082 			FREE_AND_NULL(strB);
20083 			return(XML_SCHEMAP_COS_NONAMBIG);
20084 		    }
20085 		}
20086 		break;
20087 	    case XML_SCHEMA_TYPE_SEQUENCE: {
20088 		break;
20089 		}
20090 	    case XML_SCHEMA_TYPE_CHOICE:{
20091 		/*
20092 		xmlSchemaTreeItemPtr sub;
20093 
20094 		sub = WXS_PARTICLE_TERM(particle)->children;  (xmlSchemaParticlePtr)
20095 		while (sub != NULL) {
20096 		    ret = xmlSchemaCheckElementDeclConsistent(pctxt, ctxtComponent,
20097 			ctxtParticle, ctxtElem);
20098 		    if (ret != 0)
20099 			return(ret);
20100 		    sub = sub->next;
20101 		}
20102 		*/
20103 		break;
20104 		}
20105 	    case XML_SCHEMA_TYPE_ALL:
20106 		break;
20107 	    case XML_SCHEMA_TYPE_GROUP:
20108 		break;
20109 	    default:
20110 		xmlSchemaInternalErr2(ACTXT_CAST pctxt,
20111 		    "xmlSchemaCheckElementDeclConsistent",
20112 		    "found unexpected term of type '%s' in content model",
20113 		    WXS_ITEM_TYPE_NAME(WXS_PARTICLE_TERM(cur)), NULL);
20114 		return(-1);
20115 	}
20116 	cur = (xmlSchemaParticlePtr) cur->next;
20117     }
20118 
20119 exit:
20120     return(ret);
20121 }
20122 #endif
20123 
20124 /**
20125  * xmlSchemaCheckElementDeclComponent
20126  * @item:  an schema element declaration/particle
20127  * @ctxt:  a schema parser context
20128  * @name:  the name of the attribute
20129  *
20130  * Validates the value constraints of an element declaration.
20131  * Adds substitution group members.
20132  */
20133 static void
xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,xmlSchemaParserCtxtPtr ctxt)20134 xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
20135 				   xmlSchemaParserCtxtPtr ctxt)
20136 {
20137     if (elemDecl == NULL)
20138 	return;
20139     if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
20140 	return;
20141     elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
20142     if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0) {
20143 	/*
20144 	* Adds substitution group members.
20145 	*/
20146 	xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
20147     }
20148 }
20149 
20150 /**
20151  * xmlSchemaResolveModelGroupParticleReferences:
20152  * @particle:  a particle component
20153  * @ctxt:  a parser context
20154  *
20155  * Resolves references of a model group's {particles} to
20156  * model group definitions and to element declarations.
20157  */
20158 static void
xmlSchemaResolveModelGroupParticleReferences(xmlSchemaParserCtxtPtr ctxt,xmlSchemaModelGroupPtr mg)20159 xmlSchemaResolveModelGroupParticleReferences(
20160     xmlSchemaParserCtxtPtr ctxt,
20161     xmlSchemaModelGroupPtr mg)
20162 {
20163     xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
20164     xmlSchemaQNameRefPtr ref;
20165     xmlSchemaBasicItemPtr refItem;
20166 
20167     /*
20168     * URGENT TODO: Test this.
20169     */
20170     while (particle != NULL) {
20171 	if ((WXS_PARTICLE_TERM(particle) == NULL) ||
20172 	    ((WXS_PARTICLE_TERM(particle))->type !=
20173 		XML_SCHEMA_EXTRA_QNAMEREF))
20174 	{
20175 	    goto next_particle;
20176 	}
20177 	ref = WXS_QNAME_CAST WXS_PARTICLE_TERM(particle);
20178 	/*
20179 	* Resolve the reference.
20180 	* NULL the {term} by default.
20181 	*/
20182 	particle->children = NULL;
20183 
20184 	refItem = xmlSchemaGetNamedComponent(ctxt->schema,
20185 	    ref->itemType, ref->name, ref->targetNamespace);
20186 	if (refItem == NULL) {
20187 	    xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
20188 		NULL, WXS_ITEM_NODE(particle), "ref", ref->name,
20189 		ref->targetNamespace, ref->itemType, NULL);
20190 	    /* TODO: remove the particle. */
20191 	    goto next_particle;
20192 	}
20193 	if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
20194 	    if (WXS_MODELGROUPDEF_MODEL(refItem) == NULL)
20195 		/* TODO: remove the particle. */
20196 		goto next_particle;
20197 	    /*
20198 	    * NOTE that we will assign the model group definition
20199 	    * itself to the "term" of the particle. This will ease
20200 	    * the check for circular model group definitions. After
20201 	    * that the "term" will be assigned the model group of the
20202 	    * model group definition.
20203 	    */
20204 	    if ((WXS_MODELGROUPDEF_MODEL(refItem))->type ==
20205 		    XML_SCHEMA_TYPE_ALL) {
20206 		/*
20207 		* SPEC cos-all-limited (1)
20208 		* SPEC cos-all-limited (1.2)
20209 		* "It appears only as the value of one or both of the
20210 		* following properties:"
20211 		* (1.1) "the {model group} property of a model group
20212 		*        definition."
20213 		* (1.2) "the {term} property of a particle [... of] the "
20214 		* {content type} of a complex type definition."
20215 		*/
20216 		xmlSchemaCustomErr(ACTXT_CAST ctxt,
20217 		    /* TODO: error code */
20218 		    XML_SCHEMAP_COS_ALL_LIMITED,
20219 		    WXS_ITEM_NODE(particle), NULL,
20220 		    "A model group definition is referenced, but "
20221 		    "it contains an 'all' model group, which "
20222 		    "cannot be contained by model groups",
20223 		    NULL, NULL);
20224 		/* TODO: remove the particle. */
20225 		goto next_particle;
20226 	    }
20227 	    particle->children = (xmlSchemaTreeItemPtr) refItem;
20228 	} else {
20229 	    /*
20230 	    * TODO: Are referenced element declarations the only
20231 	    * other components we expect here?
20232 	    */
20233 	    particle->children = (xmlSchemaTreeItemPtr) refItem;
20234 	}
20235 next_particle:
20236 	particle = WXS_PTC_CAST particle->next;
20237     }
20238 }
20239 
20240 static int
xmlSchemaAreValuesEqual(xmlSchemaValPtr x,xmlSchemaValPtr y)20241 xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
20242 		       xmlSchemaValPtr y)
20243 {
20244     xmlSchemaTypePtr tx, ty, ptx, pty;
20245     int ret;
20246 
20247     while (x != NULL) {
20248 	/* Same types. */
20249 	tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
20250 	ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
20251 	ptx = xmlSchemaGetPrimitiveType(tx);
20252 	pty = xmlSchemaGetPrimitiveType(ty);
20253 	/*
20254 	* (1) if a datatype T' is `derived` by `restriction` from an
20255 	* atomic datatype T then the `value space` of T' is a subset of
20256 	* the `value space` of T. */
20257 	/*
20258 	* (2) if datatypes T' and T'' are `derived` by `restriction`
20259 	* from a common atomic ancestor T then the `value space`s of T'
20260 	* and T'' may overlap.
20261 	*/
20262 	if (ptx != pty)
20263 	    return(0);
20264 	/*
20265 	* We assume computed values to be normalized, so do a fast
20266 	* string comparison for string based types.
20267 	*/
20268 	if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
20269 	    WXS_IS_ANY_SIMPLE_TYPE(ptx)) {
20270 	    if (! xmlStrEqual(
20271 		xmlSchemaValueGetAsString(x),
20272 		xmlSchemaValueGetAsString(y)))
20273 		return (0);
20274 	} else {
20275 	    ret = xmlSchemaCompareValuesWhtsp(
20276 		x, XML_SCHEMA_WHITESPACE_PRESERVE,
20277 		y, XML_SCHEMA_WHITESPACE_PRESERVE);
20278 	    if (ret == -2)
20279 		return(-1);
20280 	    if (ret != 0)
20281 		return(0);
20282 	}
20283 	/*
20284 	* Lists.
20285 	*/
20286 	x = xmlSchemaValueGetNext(x);
20287 	if (x != NULL) {
20288 	    y = xmlSchemaValueGetNext(y);
20289 	    if (y == NULL)
20290 		return (0);
20291 	} else if (xmlSchemaValueGetNext(y) != NULL)
20292 	    return (0);
20293 	else
20294 	    return (1);
20295     }
20296     return (0);
20297 }
20298 
20299 /**
20300  * xmlSchemaResolveAttrUseReferences:
20301  * @item:  an attribute use
20302  * @ctxt:  a parser context
20303  *
20304  * Resolves the referenced attribute declaration.
20305  */
20306 static int
xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,xmlSchemaParserCtxtPtr ctxt)20307 xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,
20308 				  xmlSchemaParserCtxtPtr ctxt)
20309 {
20310     if ((ctxt == NULL) || (ause == NULL))
20311 	return(-1);
20312     if ((ause->attrDecl == NULL) ||
20313 	(ause->attrDecl->type != XML_SCHEMA_EXTRA_QNAMEREF))
20314 	return(0);
20315 
20316     {
20317 	xmlSchemaQNameRefPtr ref = WXS_QNAME_CAST ause->attrDecl;
20318 
20319 	/*
20320 	* TODO: Evaluate, what errors could occur if the declaration is not
20321 	* found.
20322 	*/
20323 	ause->attrDecl = xmlSchemaGetAttributeDecl(ctxt->schema,
20324 	    ref->name, ref->targetNamespace);
20325         if (ause->attrDecl == NULL) {
20326 	    xmlSchemaPResCompAttrErr(ctxt,
20327 		XML_SCHEMAP_SRC_RESOLVE,
20328 		WXS_BASIC_CAST ause, ause->node,
20329 		"ref", ref->name, ref->targetNamespace,
20330 		XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20331             return(ctxt->err);;
20332         }
20333     }
20334     return(0);
20335 }
20336 
20337 /**
20338  * xmlSchemaCheckAttrUsePropsCorrect:
20339  * @ctxt:  a parser context
20340  * @use:  an attribute use
20341  *
20342  * Schema Component Constraint:
20343  * Attribute Use Correct (au-props-correct)
20344  *
20345  */
20346 static int
xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,xmlSchemaAttributeUsePtr use)20347 xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,
20348 			     xmlSchemaAttributeUsePtr use)
20349 {
20350     if ((ctxt == NULL) || (use == NULL))
20351 	return(-1);
20352     if ((use->defValue == NULL) || (WXS_ATTRUSE_DECL(use) == NULL) ||
20353 	((WXS_ATTRUSE_DECL(use))->type != XML_SCHEMA_TYPE_ATTRIBUTE))
20354 	return(0);
20355 
20356     /*
20357     * SPEC au-props-correct (1)
20358     * "The values of the properties of an attribute use must be as
20359     * described in the property tableau in The Attribute Use Schema
20360     * Component ($3.5.1), modulo the impact of Missing
20361     * Sub-components ($5.3)."
20362     */
20363 
20364     if (((WXS_ATTRUSE_DECL(use))->defValue != NULL) &&
20365 	((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMAS_ATTR_FIXED) &&
20366         ((use->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20367     {
20368 	xmlSchemaPCustomErr(ctxt,
20369 	    XML_SCHEMAP_AU_PROPS_CORRECT_2,
20370 	    WXS_BASIC_CAST use, NULL,
20371 	    "The attribute declaration has a 'fixed' value constraint "
20372 	    ", thus the attribute use must also have a 'fixed' value "
20373 	    "constraint",
20374 	    NULL);
20375 	return(ctxt->err);
20376     }
20377     /*
20378     * Compute and check the value constraint's value.
20379     */
20380     if ((use->defVal != NULL) && (WXS_ATTRUSE_TYPEDEF(use) != NULL)) {
20381 	int ret;
20382 	/*
20383 	* TODO: The spec seems to be missing a check of the
20384 	* value constraint of the attribute use. We will do it here.
20385 	*/
20386 	/*
20387 	* SPEC a-props-correct (3)
20388 	*/
20389 	if (xmlSchemaIsDerivedFromBuiltInType(
20390 	    WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
20391 	{
20392 	    xmlSchemaCustomErr(ACTXT_CAST ctxt,
20393 		XML_SCHEMAP_AU_PROPS_CORRECT,
20394 		NULL, WXS_BASIC_CAST use,
20395 		"Value constraints are not allowed if the type definition "
20396 		"is or is derived from xs:ID",
20397 		NULL, NULL);
20398 	    return(ctxt->err);
20399 	}
20400 
20401 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST ctxt,
20402 	    use->node, WXS_ATTRUSE_TYPEDEF(use),
20403 	    use->defValue, &(use->defVal),
20404 	    1, 1, 0);
20405 	if (ret != 0) {
20406 	    if (ret < 0) {
20407 		PERROR_INT2("xmlSchemaCheckAttrUsePropsCorrect",
20408 		    "calling xmlSchemaVCheckCVCSimpleType()");
20409 		return(-1);
20410 	    }
20411 	    xmlSchemaCustomErr(ACTXT_CAST ctxt,
20412 		XML_SCHEMAP_AU_PROPS_CORRECT,
20413 		NULL, WXS_BASIC_CAST use,
20414 		"The value of the value constraint is not valid",
20415 		NULL, NULL);
20416 	    return(ctxt->err);
20417 	}
20418     }
20419     /*
20420     * SPEC au-props-correct (2)
20421     * "If the {attribute declaration} has a fixed
20422     * {value constraint}, then if the attribute use itself has a
20423     * {value constraint}, it must also be fixed and its value must match
20424     * that of the {attribute declaration}'s {value constraint}."
20425     */
20426     if (((WXS_ATTRUSE_DECL(use))->defVal != NULL) &&
20427 	(((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20428     {
20429 	if (! xmlSchemaAreValuesEqual(use->defVal,
20430 		(WXS_ATTRUSE_DECL(use))->defVal))
20431 	{
20432 	    xmlSchemaPCustomErr(ctxt,
20433 		XML_SCHEMAP_AU_PROPS_CORRECT_2,
20434 		WXS_BASIC_CAST use, NULL,
20435 		"The 'fixed' value constraint of the attribute use "
20436 		"must match the attribute declaration's value "
20437 		"constraint '%s'",
20438 		(WXS_ATTRUSE_DECL(use))->defValue);
20439 	}
20440 	return(ctxt->err);
20441     }
20442     return(0);
20443 }
20444 
20445 
20446 
20447 
20448 /**
20449  * xmlSchemaResolveAttrTypeReferences:
20450  * @item:  an attribute declaration
20451  * @ctxt:  a parser context
20452  *
20453  * Resolves the referenced type definition component.
20454  */
20455 static int
xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,xmlSchemaParserCtxtPtr ctxt)20456 xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,
20457 				   xmlSchemaParserCtxtPtr ctxt)
20458 {
20459     /*
20460     * The simple type definition corresponding to the <simpleType> element
20461     * information item in the [children], if present, otherwise the simple
20462     * type definition `resolved` to by the `actual value` of the type
20463     * [attribute], if present, otherwise the `simple ur-type definition`.
20464     */
20465     if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
20466 	return(0);
20467     item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
20468     if (item->subtypes != NULL)
20469         return(0);
20470     if (item->typeName != NULL) {
20471         xmlSchemaTypePtr type;
20472 
20473 	type = xmlSchemaGetType(ctxt->schema, item->typeName,
20474 	    item->typeNs);
20475 	if ((type == NULL) || (! WXS_IS_SIMPLE(type))) {
20476 	    xmlSchemaPResCompAttrErr(ctxt,
20477 		XML_SCHEMAP_SRC_RESOLVE,
20478 		WXS_BASIC_CAST item, item->node,
20479 		"type", item->typeName, item->typeNs,
20480 		XML_SCHEMA_TYPE_SIMPLE, NULL);
20481 	    return(ctxt->err);
20482 	} else
20483 	    item->subtypes = type;
20484 
20485     } else {
20486 	/*
20487 	* The type defaults to the xs:anySimpleType.
20488 	*/
20489 	item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
20490     }
20491     return(0);
20492 }
20493 
20494 /**
20495  * xmlSchemaResolveIDCKeyReferences:
20496  * @idc:  the identity-constraint definition
20497  * @ctxt:  the schema parser context
20498  * @name:  the attribute name
20499  *
20500  * Resolve keyRef references to key/unique IDCs.
20501  * Schema Component Constraint:
20502  *   Identity-constraint Definition Properties Correct (c-props-correct)
20503  */
20504 static int
xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,xmlSchemaParserCtxtPtr pctxt)20505 xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,
20506 			  xmlSchemaParserCtxtPtr pctxt)
20507 {
20508     if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
20509         return(0);
20510     if (idc->ref->name != NULL) {
20511 	idc->ref->item = (xmlSchemaBasicItemPtr)
20512 	    xmlSchemaGetIDC(pctxt->schema, idc->ref->name,
20513 		idc->ref->targetNamespace);
20514         if (idc->ref->item == NULL) {
20515 	    /*
20516 	    * TODO: It is actually not an error to fail to resolve
20517 	    * at this stage. BUT we need to be that strict!
20518 	    */
20519 	    xmlSchemaPResCompAttrErr(pctxt,
20520 		XML_SCHEMAP_SRC_RESOLVE,
20521 		WXS_BASIC_CAST idc, idc->node,
20522 		"refer", idc->ref->name,
20523 		idc->ref->targetNamespace,
20524 		XML_SCHEMA_TYPE_IDC_KEY, NULL);
20525             return(pctxt->err);
20526 	} else if (idc->ref->item->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20527 	    /*
20528 	    * SPEC c-props-correct (1)
20529 	    */
20530 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20531 		XML_SCHEMAP_C_PROPS_CORRECT,
20532 		NULL, WXS_BASIC_CAST idc,
20533 		"The keyref references a keyref",
20534 		NULL, NULL);
20535 	    idc->ref->item = NULL;
20536 	    return(pctxt->err);
20537 	} else {
20538 	    if (idc->nbFields !=
20539 		((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
20540 		xmlChar *str = NULL;
20541 		xmlSchemaIDCPtr refer;
20542 
20543 		refer = (xmlSchemaIDCPtr) idc->ref->item;
20544 		/*
20545 		* SPEC c-props-correct(2)
20546 		* "If the {identity-constraint category} is keyref,
20547 		* the cardinality of the {fields} must equal that of
20548 		* the {fields} of the {referenced key}.
20549 		*/
20550 		xmlSchemaCustomErr(ACTXT_CAST pctxt,
20551 		    XML_SCHEMAP_C_PROPS_CORRECT,
20552 		    NULL, WXS_BASIC_CAST idc,
20553 		    "The cardinality of the keyref differs from the "
20554 		    "cardinality of the referenced key/unique '%s'",
20555 		    xmlSchemaFormatQName(&str, refer->targetNamespace,
20556 			refer->name),
20557 		    NULL);
20558 		FREE_AND_NULL(str)
20559 		return(pctxt->err);
20560 	    }
20561 	}
20562     }
20563     return(0);
20564 }
20565 
20566 static int
xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,xmlSchemaParserCtxtPtr pctxt)20567 xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,
20568 				       xmlSchemaParserCtxtPtr pctxt)
20569 {
20570     if (xmlSchemaGetAttributeDecl(pctxt->schema, prohib->name,
20571 	prohib->targetNamespace) == NULL) {
20572 
20573 	xmlSchemaPResCompAttrErr(pctxt,
20574 	    XML_SCHEMAP_SRC_RESOLVE,
20575 	    NULL, prohib->node,
20576 	    "ref", prohib->name, prohib->targetNamespace,
20577 	    XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20578 	return(XML_SCHEMAP_SRC_RESOLVE);
20579     }
20580     return(0);
20581 }
20582 
20583 #define WXS_REDEFINED_TYPE(c) \
20584 (((xmlSchemaTypePtr) item)->flags & XML_SCHEMAS_TYPE_REDEFINED)
20585 
20586 #define WXS_REDEFINED_MODEL_GROUP_DEF(c) \
20587 (((xmlSchemaModelGroupDefPtr) item)->flags & XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20588 
20589 #define WXS_REDEFINED_ATTR_GROUP(c) \
20590 (((xmlSchemaAttributeGroupPtr) item)->flags & XML_SCHEMAS_ATTRGROUP_REDEFINED)
20591 
20592 static int
xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)20593 xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)
20594 {
20595     int err = 0;
20596     xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20597     xmlSchemaBasicItemPtr prev, item;
20598     int wasRedefined;
20599 
20600     if (redef == NULL)
20601 	return(0);
20602 
20603     do {
20604 	item = redef->item;
20605 	/*
20606 	* First try to locate the redefined component in the
20607 	* schema graph starting with the redefined schema.
20608 	* NOTE: According to this schema bug entry:
20609 	*   http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005OctDec/0019.html
20610 	*   it's not clear if the referenced component needs to originate
20611 	*   from the <redefine>d schema _document_ or the schema; the latter
20612 	*   would include all imported and included sub-schemas of the
20613 	*   <redefine>d schema. Currently the latter approach is used.
20614 	*   SUPPLEMENT: It seems that the WG moves towards the latter
20615 	*   approach, so we are doing it right.
20616 	*
20617 	*/
20618 	prev = xmlSchemaFindRedefCompInGraph(
20619 	    redef->targetBucket, item->type,
20620 	    redef->refName, redef->refTargetNs);
20621 	if (prev == NULL) {
20622 	    xmlChar *str = NULL;
20623 	    xmlNodePtr node;
20624 
20625 	    /*
20626 	    * SPEC src-redefine:
20627 	    * (6.2.1) "The `actual value` of its own name attribute plus
20628 	    * target namespace must successfully `resolve` to a model
20629 	    * group definition in I."
20630 	    * (7.2.1) "The `actual value` of its own name attribute plus
20631 	    * target namespace must successfully `resolve` to an attribute
20632 	    * group definition in I."
20633 
20634 	    *
20635 	    * Note that, if we are redefining with the use of references
20636 	    * to components, the spec assumes the src-resolve to be used;
20637 	    * but this won't assure that we search only *inside* the
20638 	    * redefined schema.
20639 	    */
20640 	    if (redef->reference)
20641 		node = WXS_ITEM_NODE(redef->reference);
20642 	    else
20643 		node = WXS_ITEM_NODE(item);
20644 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20645 		/*
20646 		* TODO: error code.
20647 		* Probably XML_SCHEMAP_SRC_RESOLVE, if this is using the
20648 		* reference kind.
20649 		*/
20650 		XML_SCHEMAP_SRC_REDEFINE, node, NULL,
20651 		"The %s '%s' to be redefined could not be found in "
20652 		"the redefined schema",
20653 		WXS_ITEM_TYPE_NAME(item),
20654 		xmlSchemaFormatQName(&str, redef->refTargetNs,
20655 		    redef->refName));
20656 	    FREE_AND_NULL(str);
20657 	    err = pctxt->err;
20658 	    redef = redef->next;
20659 	    continue;
20660 	}
20661 	/*
20662 	* TODO: Obtaining and setting the redefinition state is really
20663 	* clumsy.
20664 	*/
20665 	wasRedefined = 0;
20666 	switch (item->type) {
20667 	    case XML_SCHEMA_TYPE_COMPLEX:
20668 	    case XML_SCHEMA_TYPE_SIMPLE:
20669 		if ((WXS_TYPE_CAST prev)->flags &
20670 		    XML_SCHEMAS_TYPE_REDEFINED)
20671 		{
20672 		    wasRedefined = 1;
20673 		    break;
20674 		}
20675 		/* Mark it as redefined. */
20676 		(WXS_TYPE_CAST prev)->flags |= XML_SCHEMAS_TYPE_REDEFINED;
20677 		/*
20678 		* Assign the redefined type to the
20679 		* base type of the redefining type.
20680 		* TODO: How
20681 		*/
20682 		((xmlSchemaTypePtr) item)->baseType =
20683 		    (xmlSchemaTypePtr) prev;
20684 		break;
20685 	    case XML_SCHEMA_TYPE_GROUP:
20686 		if ((WXS_MODEL_GROUPDEF_CAST prev)->flags &
20687 		    XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20688 		{
20689 		    wasRedefined = 1;
20690 		    break;
20691 		}
20692 		/* Mark it as redefined. */
20693 		(WXS_MODEL_GROUPDEF_CAST prev)->flags |=
20694 		    XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED;
20695 		if (redef->reference != NULL) {
20696 		    /*
20697 		    * Overwrite the QName-reference with the
20698 		    * referenced model group def.
20699 		    */
20700 		    (WXS_PTC_CAST redef->reference)->children =
20701 			WXS_TREE_CAST prev;
20702 		}
20703 		redef->target = prev;
20704 		break;
20705 	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20706 		if ((WXS_ATTR_GROUP_CAST prev)->flags &
20707 		    XML_SCHEMAS_ATTRGROUP_REDEFINED)
20708 		{
20709 		    wasRedefined = 1;
20710 		    break;
20711 		}
20712 		(WXS_ATTR_GROUP_CAST prev)->flags |=
20713 		    XML_SCHEMAS_ATTRGROUP_REDEFINED;
20714 		if (redef->reference != NULL) {
20715 		    /*
20716 		    * Assign the redefined attribute group to the
20717 		    * QName-reference component.
20718 		    * This is the easy case, since we will just
20719 		    * expand the redefined group.
20720 		    */
20721 		    (WXS_QNAME_CAST redef->reference)->item = prev;
20722 		    redef->target = NULL;
20723 		} else {
20724 		    /*
20725 		    * This is the complicated case: we need
20726 		    * to apply src-redefine (7.2.2) at a later
20727 		    * stage, i.e. when attribute group references
20728 		    * have been expanded and simple types have
20729 		    * been fixed.
20730 		    */
20731 		    redef->target = prev;
20732 		}
20733 		break;
20734 	    default:
20735 		PERROR_INT("xmlSchemaResolveRedefReferences",
20736 		    "Unexpected redefined component type");
20737 		return(-1);
20738 	}
20739 	if (wasRedefined) {
20740 	    xmlChar *str = NULL;
20741 	    xmlNodePtr node;
20742 
20743 	    if (redef->reference)
20744 		node = WXS_ITEM_NODE(redef->reference);
20745 	    else
20746 		node = WXS_ITEM_NODE(redef->item);
20747 
20748 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20749 		/* TODO: error code. */
20750 		XML_SCHEMAP_SRC_REDEFINE,
20751 		node, NULL,
20752 		"The referenced %s was already redefined. Multiple "
20753 		"redefinition of the same component is not supported",
20754 		xmlSchemaGetComponentDesignation(&str, prev),
20755 		NULL);
20756 	    FREE_AND_NULL(str)
20757 	    err = pctxt->err;
20758 	    redef = redef->next;
20759 	    continue;
20760 	}
20761 	redef = redef->next;
20762     } while (redef != NULL);
20763 
20764     return(err);
20765 }
20766 
20767 static int
xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)20768 xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)
20769 {
20770     int err = 0;
20771     xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20772     xmlSchemaBasicItemPtr item;
20773 
20774     if (redef == NULL)
20775 	return(0);
20776 
20777     do {
20778 	if (redef->target == NULL) {
20779 	    redef = redef->next;
20780 	    continue;
20781 	}
20782 	item = redef->item;
20783 
20784 	switch (item->type) {
20785 	    case XML_SCHEMA_TYPE_SIMPLE:
20786 	    case XML_SCHEMA_TYPE_COMPLEX:
20787 		/*
20788 		* Since the spec wants the {name} of the redefined
20789 		* type to be 'absent', we'll NULL it.
20790 		*/
20791 		(WXS_TYPE_CAST redef->target)->name = NULL;
20792 
20793 		/*
20794 		* TODO: Seems like there's nothing more to do. The normal
20795 		* inheritance mechanism is used. But not 100% sure.
20796 		*/
20797 		break;
20798 	    case XML_SCHEMA_TYPE_GROUP:
20799 		/*
20800 		* URGENT TODO:
20801 		* SPEC src-redefine:
20802 		* (6.2.2) "The {model group} of the model group definition
20803 		* which corresponds to it per XML Representation of Model
20804 		* Group Definition Schema Components ($3.7.2) must be a
20805 		* `valid restriction` of the {model group} of that model
20806 		* group definition in I, as defined in Particle Valid
20807 		* (Restriction) ($3.9.6)."
20808 		*/
20809 		break;
20810 	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20811 		/*
20812 		* SPEC src-redefine:
20813 		* (7.2.2) "The {attribute uses} and {attribute wildcard} of
20814 		* the attribute group definition which corresponds to it
20815 		* per XML Representation of Attribute Group Definition Schema
20816 		* Components ($3.6.2) must be `valid restrictions` of the
20817 		* {attribute uses} and {attribute wildcard} of that attribute
20818 		* group definition in I, as defined in clause 2, clause 3 and
20819 		* clause 4 of Derivation Valid (Restriction, Complex)
20820 		* ($3.4.6) (where references to the base type definition are
20821 		* understood as references to the attribute group definition
20822 		* in I)."
20823 		*/
20824 		err = xmlSchemaCheckDerivationOKRestriction2to4(pctxt,
20825 		    XML_SCHEMA_ACTION_REDEFINE,
20826 		    item, redef->target,
20827 		    (WXS_ATTR_GROUP_CAST item)->attrUses,
20828 		    (WXS_ATTR_GROUP_CAST redef->target)->attrUses,
20829 		    (WXS_ATTR_GROUP_CAST item)->attributeWildcard,
20830 		    (WXS_ATTR_GROUP_CAST redef->target)->attributeWildcard);
20831 		if (err == -1)
20832 		    return(-1);
20833 		break;
20834 	    default:
20835 		break;
20836 	}
20837 	redef = redef->next;
20838     } while (redef != NULL);
20839     return(0);
20840 }
20841 
20842 
20843 static int
xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBucketPtr bucket)20844 xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,
20845 		       xmlSchemaBucketPtr bucket)
20846 {
20847     xmlSchemaBasicItemPtr item;
20848     int err;
20849     xmlHashTablePtr *table;
20850     const xmlChar *name;
20851     int i;
20852 
20853 #define WXS_GET_GLOBAL_HASH(c, slot) { \
20854     if (WXS_IS_BUCKET_IMPMAIN((c)->type)) \
20855 	table = &(WXS_IMPBUCKET((c))->schema->slot); \
20856     else \
20857 	table = &(WXS_INCBUCKET((c))->ownerImport->schema->slot); }
20858 
20859     /*
20860     * Add global components to the schema's hash tables.
20861     * This is the place where duplicate components will be
20862     * detected.
20863     * TODO: I think normally we should support imports of the
20864     *   same namespace from multiple locations. We don't do currently,
20865     *   but if we do then according to:
20866     *   http://www.w3.org/Bugs/Public/show_bug.cgi?id=2224
20867     *   we would need, if imported directly, to import redefined
20868     *   components as well to be able to catch clashing components.
20869     *   (I hope I'll still know what this means after some months :-()
20870     */
20871     if (bucket == NULL)
20872 	return(-1);
20873     if (bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED)
20874 	return(0);
20875     bucket->flags |= XML_SCHEMA_BUCKET_COMPS_ADDED;
20876 
20877     for (i = 0; i < bucket->globals->nbItems; i++) {
20878 	item = bucket->globals->items[i];
20879 	table = NULL;
20880 	switch (item->type) {
20881 	    case XML_SCHEMA_TYPE_COMPLEX:
20882 	    case XML_SCHEMA_TYPE_SIMPLE:
20883 		if (WXS_REDEFINED_TYPE(item))
20884 		    continue;
20885 		name = (WXS_TYPE_CAST item)->name;
20886 		WXS_GET_GLOBAL_HASH(bucket, typeDecl)
20887 		break;
20888 	    case XML_SCHEMA_TYPE_ELEMENT:
20889 		name = (WXS_ELEM_CAST item)->name;
20890 		WXS_GET_GLOBAL_HASH(bucket, elemDecl)
20891 		break;
20892 	    case XML_SCHEMA_TYPE_ATTRIBUTE:
20893 		name = (WXS_ATTR_CAST item)->name;
20894 		WXS_GET_GLOBAL_HASH(bucket, attrDecl)
20895 		break;
20896 	    case XML_SCHEMA_TYPE_GROUP:
20897 		if (WXS_REDEFINED_MODEL_GROUP_DEF(item))
20898 		    continue;
20899 		name = (WXS_MODEL_GROUPDEF_CAST item)->name;
20900 		WXS_GET_GLOBAL_HASH(bucket, groupDecl)
20901 		break;
20902 	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20903 		if (WXS_REDEFINED_ATTR_GROUP(item))
20904 		    continue;
20905 		name = (WXS_ATTR_GROUP_CAST item)->name;
20906 		WXS_GET_GLOBAL_HASH(bucket, attrgrpDecl)
20907 		break;
20908 	    case XML_SCHEMA_TYPE_IDC_KEY:
20909 	    case XML_SCHEMA_TYPE_IDC_UNIQUE:
20910 	    case XML_SCHEMA_TYPE_IDC_KEYREF:
20911 		name = (WXS_IDC_CAST item)->name;
20912 		WXS_GET_GLOBAL_HASH(bucket, idcDef)
20913 		break;
20914 	    case XML_SCHEMA_TYPE_NOTATION:
20915 		name = ((xmlSchemaNotationPtr) item)->name;
20916 		WXS_GET_GLOBAL_HASH(bucket, notaDecl)
20917 		break;
20918 	    default:
20919 		PERROR_INT("xmlSchemaAddComponents",
20920 		    "Unexpected global component type");
20921 		continue;
20922 	}
20923 	if (*table == NULL) {
20924 	    *table = xmlHashCreateDict(10, pctxt->dict);
20925 	    if (*table == NULL) {
20926 		PERROR_INT("xmlSchemaAddComponents",
20927 		    "failed to create a component hash table");
20928 		return(-1);
20929 	    }
20930 	}
20931 	err = xmlHashAddEntry(*table, name, item);
20932 	if (err != 0) {
20933 	    xmlChar *str = NULL;
20934 
20935 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20936 		XML_SCHEMAP_REDEFINED_TYPE,
20937 		WXS_ITEM_NODE(item),
20938 		WXS_BASIC_CAST item,
20939 		"A global %s '%s' does already exist",
20940 		WXS_ITEM_TYPE_NAME(item),
20941 		xmlSchemaGetComponentQName(&str, item));
20942 	    FREE_AND_NULL(str);
20943 	}
20944     }
20945     /*
20946     * Process imported/included schemas.
20947     */
20948     if (bucket->relations != NULL) {
20949 	xmlSchemaSchemaRelationPtr rel = bucket->relations;
20950 	do {
20951 	    if ((rel->bucket != NULL) &&
20952 		((rel->bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED) == 0)) {
20953 		if (xmlSchemaAddComponents(pctxt, rel->bucket) == -1)
20954 		    return(-1);
20955 	    }
20956 	    rel = rel->next;
20957 	} while (rel != NULL);
20958     }
20959     return(0);
20960 }
20961 
20962 static int
xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBucketPtr rootBucket)20963 xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt,
20964 			 xmlSchemaBucketPtr rootBucket)
20965 {
20966     xmlSchemaConstructionCtxtPtr con = pctxt->constructor;
20967     xmlSchemaTreeItemPtr item, *items;
20968     int nbItems, i, ret = 0;
20969     xmlSchemaBucketPtr oldbucket = con->bucket;
20970     xmlSchemaElementPtr elemDecl;
20971 
20972 #define FIXHFAILURE if (pctxt->err == XML_SCHEMAP_INTERNAL) goto exit_failure;
20973 
20974     if ((con->pending == NULL) ||
20975 	(con->pending->nbItems == 0))
20976 	return(0);
20977 
20978     /*
20979     * Since xmlSchemaFixupComplexType() will create new particles
20980     * (local components), and those particle components need a bucket
20981     * on the constructor, we'll assure here that the constructor has
20982     * a bucket.
20983     * TODO: Think about storing locals _only_ on the main bucket.
20984     */
20985     if (con->bucket == NULL)
20986 	con->bucket = rootBucket;
20987 
20988     /* TODO:
20989     * SPEC (src-redefine):
20990     * (6.2) "If it has no such self-reference, then all of the
20991     * following must be true:"
20992 
20993     * (6.2.2) The {model group} of the model group definition which
20994     * corresponds to it per XML Representation of Model Group
20995     * Definition Schema Components ($3.7.2) must be a `valid
20996     * restriction` of the {model group} of that model group definition
20997     * in I, as defined in Particle Valid (Restriction) ($3.9.6)."
20998     */
20999     xmlSchemaCheckSRCRedefineFirst(pctxt);
21000 
21001     /*
21002     * Add global components to the schemata's hash tables.
21003     */
21004     xmlSchemaAddComponents(pctxt, rootBucket);
21005 
21006     pctxt->ctxtType = NULL;
21007     items = (xmlSchemaTreeItemPtr *) con->pending->items;
21008     nbItems = con->pending->nbItems;
21009     /*
21010     * Now that we have parsed *all* the schema document(s) and converted
21011     * them to schema components, we can resolve references, apply component
21012     * constraints, create the FSA from the content model, etc.
21013     */
21014     /*
21015     * Resolve references of..
21016     *
21017     * 1. element declarations:
21018     *   - the type definition
21019     *   - the substitution group affiliation
21020     * 2. simple/complex types:
21021     *   - the base type definition
21022     *   - the memberTypes of union types
21023     *   - the itemType of list types
21024     * 3. attributes declarations and attribute uses:
21025     *   - the type definition
21026     *   - if an attribute use, then the attribute declaration
21027     * 4. attribute group references:
21028     *   - the attribute group definition
21029     * 5. particles:
21030     *   - the term of the particle (e.g. a model group)
21031     * 6. IDC key-references:
21032     *   - the referenced IDC 'key' or 'unique' definition
21033     * 7. Attribute prohibitions which had a "ref" attribute.
21034     */
21035     for (i = 0; i < nbItems; i++) {
21036 	item = items[i];
21037 	switch (item->type) {
21038 	    case XML_SCHEMA_TYPE_ELEMENT:
21039 		xmlSchemaResolveElementReferences(
21040 		    (xmlSchemaElementPtr) item, pctxt);
21041 		FIXHFAILURE;
21042 		break;
21043 	    case XML_SCHEMA_TYPE_COMPLEX:
21044 	    case XML_SCHEMA_TYPE_SIMPLE:
21045 		xmlSchemaResolveTypeReferences(
21046 		    (xmlSchemaTypePtr) item, pctxt);
21047 		FIXHFAILURE;
21048 		break;
21049 	    case XML_SCHEMA_TYPE_ATTRIBUTE:
21050 		xmlSchemaResolveAttrTypeReferences(
21051 		    (xmlSchemaAttributePtr) item, pctxt);
21052 		FIXHFAILURE;
21053 		break;
21054 	    case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
21055 		xmlSchemaResolveAttrUseReferences(
21056 		    (xmlSchemaAttributeUsePtr) item, pctxt);
21057 		FIXHFAILURE;
21058 		break;
21059 	    case XML_SCHEMA_EXTRA_QNAMEREF:
21060 		if ((WXS_QNAME_CAST item)->itemType ==
21061 		    XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
21062 		{
21063 		    xmlSchemaResolveAttrGroupReferences(
21064 			WXS_QNAME_CAST item, pctxt);
21065 		}
21066 		FIXHFAILURE;
21067 		break;
21068 	    case XML_SCHEMA_TYPE_SEQUENCE:
21069 	    case XML_SCHEMA_TYPE_CHOICE:
21070 	    case XML_SCHEMA_TYPE_ALL:
21071 		xmlSchemaResolveModelGroupParticleReferences(pctxt,
21072 		    WXS_MODEL_GROUP_CAST item);
21073 		FIXHFAILURE;
21074 		break;
21075 	    case XML_SCHEMA_TYPE_IDC_KEY:
21076 	    case XML_SCHEMA_TYPE_IDC_UNIQUE:
21077 	    case XML_SCHEMA_TYPE_IDC_KEYREF:
21078 		xmlSchemaResolveIDCKeyReferences(
21079 		    (xmlSchemaIDCPtr) item, pctxt);
21080 		FIXHFAILURE;
21081 		break;
21082 	    case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
21083 		/*
21084 		* Handle attribute prohibition which had a
21085 		* "ref" attribute.
21086 		*/
21087 		xmlSchemaResolveAttrUseProhibReferences(
21088 		    WXS_ATTR_PROHIB_CAST item, pctxt);
21089 		FIXHFAILURE;
21090 		break;
21091 	    default:
21092 		break;
21093 	}
21094     }
21095     if (pctxt->nberrors != 0)
21096 	goto exit_error;
21097 
21098     /*
21099     * Now that all references are resolved we
21100     * can check for circularity of...
21101     * 1. the base axis of type definitions
21102     * 2. nested model group definitions
21103     * 3. nested attribute group definitions
21104     * TODO: check for circular substitution groups.
21105     */
21106     for (i = 0; i < nbItems; i++) {
21107 	item = items[i];
21108 	/*
21109 	* Let's better stop on the first error here.
21110 	*/
21111 	switch (item->type) {
21112 	    case XML_SCHEMA_TYPE_COMPLEX:
21113 	    case XML_SCHEMA_TYPE_SIMPLE:
21114 		xmlSchemaCheckTypeDefCircular(
21115 		    (xmlSchemaTypePtr) item, pctxt);
21116 		FIXHFAILURE;
21117 		if (pctxt->nberrors != 0)
21118 		    goto exit_error;
21119 		break;
21120 	    case XML_SCHEMA_TYPE_GROUP:
21121 		xmlSchemaCheckGroupDefCircular(
21122 		    (xmlSchemaModelGroupDefPtr) item, pctxt);
21123 		FIXHFAILURE;
21124 		if (pctxt->nberrors != 0)
21125 		    goto exit_error;
21126 		break;
21127 	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21128 		xmlSchemaCheckAttrGroupCircular(
21129 		    (xmlSchemaAttributeGroupPtr) item, pctxt);
21130 		FIXHFAILURE;
21131 		if (pctxt->nberrors != 0)
21132 		    goto exit_error;
21133 		break;
21134 	    default:
21135 		break;
21136 	}
21137     }
21138     if (pctxt->nberrors != 0)
21139 	goto exit_error;
21140     /*
21141     * Model group definition references:
21142     * Such a reference is reflected by a particle at the component
21143     * level. Until now the 'term' of such particles pointed
21144     * to the model group definition; this was done, in order to
21145     * ease circularity checks. Now we need to set the 'term' of
21146     * such particles to the model group of the model group definition.
21147     */
21148     for (i = 0; i < nbItems; i++) {
21149 	item = items[i];
21150 	switch (item->type) {
21151 	    case XML_SCHEMA_TYPE_SEQUENCE:
21152 	    case XML_SCHEMA_TYPE_CHOICE:
21153 		xmlSchemaModelGroupToModelGroupDefFixup(pctxt,
21154 		    WXS_MODEL_GROUP_CAST item);
21155 		break;
21156 	    default:
21157 		break;
21158 	}
21159     }
21160     if (pctxt->nberrors != 0)
21161 	goto exit_error;
21162     /*
21163     * Expand attribute group references of attribute group definitions.
21164     */
21165     for (i = 0; i < nbItems; i++) {
21166 	item = items[i];
21167 	switch (item->type) {
21168             case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21169 		if ((! WXS_ATTR_GROUP_EXPANDED(item)) &&
21170 		    WXS_ATTR_GROUP_HAS_REFS(item))
21171 		{
21172 		    xmlSchemaAttributeGroupExpandRefs(pctxt,
21173 			WXS_ATTR_GROUP_CAST item);
21174 		    FIXHFAILURE;
21175 		}
21176 		break;
21177 	    default:
21178 		break;
21179 	}
21180     }
21181     if (pctxt->nberrors != 0)
21182 	goto exit_error;
21183     /*
21184     * First compute the variety of simple types. This is needed as
21185     * a separate step, since otherwise we won't be able to detect
21186     * circular union types in all cases.
21187     */
21188     for (i = 0; i < nbItems; i++) {
21189 	item = items[i];
21190 	switch (item->type) {
21191             case XML_SCHEMA_TYPE_SIMPLE:
21192 		if (WXS_IS_TYPE_NOT_FIXED_1((xmlSchemaTypePtr) item)) {
21193 		    xmlSchemaFixupSimpleTypeStageOne(pctxt,
21194 			(xmlSchemaTypePtr) item);
21195 		    FIXHFAILURE;
21196 		}
21197 		break;
21198 	    default:
21199 		break;
21200 	}
21201     }
21202     if (pctxt->nberrors != 0)
21203 	goto exit_error;
21204     /*
21205     * Detect circular union types. Note that this needs the variety to
21206     * be already computed.
21207     */
21208     for (i = 0; i < nbItems; i++) {
21209 	item = items[i];
21210 	switch (item->type) {
21211             case XML_SCHEMA_TYPE_SIMPLE:
21212 		if (((xmlSchemaTypePtr) item)->memberTypes != NULL) {
21213 		    xmlSchemaCheckUnionTypeDefCircular(pctxt,
21214 			(xmlSchemaTypePtr) item);
21215 		    FIXHFAILURE;
21216 		}
21217 		break;
21218 	    default:
21219 		break;
21220 	}
21221     }
21222     if (pctxt->nberrors != 0)
21223 	goto exit_error;
21224 
21225     /*
21226     * Do the complete type fixup for simple types.
21227     */
21228     for (i = 0; i < nbItems; i++) {
21229 	item = items[i];
21230 	switch (item->type) {
21231             case XML_SCHEMA_TYPE_SIMPLE:
21232 		if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21233 		    xmlSchemaFixupSimpleTypeStageTwo(pctxt, WXS_TYPE_CAST item);
21234 		    FIXHFAILURE;
21235 		}
21236 		break;
21237 	    default:
21238 		break;
21239 	}
21240     }
21241     if (pctxt->nberrors != 0)
21242 	goto exit_error;
21243     /*
21244     * At this point we need build and check all simple types.
21245     */
21246     /*
21247     * Apply constraints for attribute declarations.
21248     */
21249     for (i = 0; i < nbItems; i++) {
21250 	item = items[i];
21251 	switch (item->type) {
21252 	    case XML_SCHEMA_TYPE_ATTRIBUTE:
21253 		xmlSchemaCheckAttrPropsCorrect(pctxt, WXS_ATTR_CAST item);
21254 		FIXHFAILURE;
21255 		break;
21256 	    default:
21257 		break;
21258 	}
21259     }
21260     if (pctxt->nberrors != 0)
21261 	goto exit_error;
21262     /*
21263     * Apply constraints for attribute uses.
21264     */
21265     for (i = 0; i < nbItems; i++) {
21266 	item = items[i];
21267 	switch (item->type) {
21268 	    case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
21269 		if (((xmlSchemaAttributeUsePtr)item)->defValue != NULL) {
21270 		    xmlSchemaCheckAttrUsePropsCorrect(pctxt,
21271 			WXS_ATTR_USE_CAST item);
21272 		    FIXHFAILURE;
21273 		}
21274 		break;
21275 	    default:
21276 		break;
21277 	}
21278     }
21279     if (pctxt->nberrors != 0)
21280 	goto exit_error;
21281 
21282     /*
21283     * Apply constraints for attribute group definitions.
21284     */
21285     for (i = 0; i < nbItems; i++) {
21286 	item = items[i];
21287 	switch (item->type) {
21288 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21289 	    if (( (WXS_ATTR_GROUP_CAST item)->attrUses != NULL) &&
21290 		( (WXS_LIST_CAST (WXS_ATTR_GROUP_CAST item)->attrUses)->nbItems > 1))
21291 	    {
21292 		xmlSchemaCheckAGPropsCorrect(pctxt, WXS_ATTR_GROUP_CAST item);
21293 		FIXHFAILURE;
21294 	    }
21295 	    break;
21296 	default:
21297 	    break;
21298 	}
21299     }
21300     if (pctxt->nberrors != 0)
21301 	goto exit_error;
21302 
21303     /*
21304     * Apply constraints for redefinitions.
21305     */
21306     if (WXS_CONSTRUCTOR(pctxt)->redefs != NULL)
21307 	xmlSchemaCheckSRCRedefineSecond(pctxt);
21308     if (pctxt->nberrors != 0)
21309 	goto exit_error;
21310 
21311     /*
21312     * Complex types are built and checked.
21313     */
21314     for (i = 0; i < nbItems; i++) {
21315 	item = con->pending->items[i];
21316 	switch (item->type) {
21317 	    case XML_SCHEMA_TYPE_COMPLEX:
21318 		if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21319 		    xmlSchemaFixupComplexType(pctxt, WXS_TYPE_CAST item);
21320 		    FIXHFAILURE;
21321 		}
21322 		break;
21323 	    default:
21324 		break;
21325 	}
21326     }
21327     if (pctxt->nberrors != 0)
21328 	goto exit_error;
21329 
21330     /*
21331     * The list could have changed, since xmlSchemaFixupComplexType()
21332     * will create particles and model groups in some cases.
21333     */
21334     items = (xmlSchemaTreeItemPtr *) con->pending->items;
21335     nbItems = con->pending->nbItems;
21336 
21337     /*
21338     * Apply some constraints for element declarations.
21339     */
21340     for (i = 0; i < nbItems; i++) {
21341 	item = items[i];
21342 	switch (item->type) {
21343 	    case XML_SCHEMA_TYPE_ELEMENT:
21344 		elemDecl = (xmlSchemaElementPtr) item;
21345 
21346 		if ((elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED) == 0)
21347 		{
21348 		    xmlSchemaCheckElementDeclComponent(
21349 			(xmlSchemaElementPtr) elemDecl, pctxt);
21350 		    FIXHFAILURE;
21351 		}
21352 
21353 #ifdef WXS_ELEM_DECL_CONS_ENABLED
21354 		/*
21355 		* Schema Component Constraint: Element Declarations Consistent
21356 		* Apply this constraint to local types of element declarations.
21357 		*/
21358 		if ((WXS_ELEM_TYPEDEF(elemDecl) != NULL) &&
21359 		    (WXS_IS_COMPLEX(WXS_ELEM_TYPEDEF(elemDecl))) &&
21360 		    (WXS_TYPE_IS_LOCAL(WXS_ELEM_TYPEDEF(elemDecl))))
21361 		{
21362 		    xmlSchemaCheckElementDeclConsistent(pctxt,
21363 			WXS_BASIC_CAST elemDecl,
21364 			WXS_TYPE_PARTICLE(WXS_ELEM_TYPEDEF(elemDecl)),
21365 			NULL, NULL, 0);
21366 		}
21367 #endif
21368 		break;
21369 	    default:
21370 		break;
21371 	}
21372     }
21373     if (pctxt->nberrors != 0)
21374 	goto exit_error;
21375 
21376     /*
21377     * Finally we can build the automaton from the content model of
21378     * complex types.
21379     */
21380 
21381     for (i = 0; i < nbItems; i++) {
21382 	item = items[i];
21383 	switch (item->type) {
21384 	    case XML_SCHEMA_TYPE_COMPLEX:
21385 		xmlSchemaBuildContentModel((xmlSchemaTypePtr) item, pctxt);
21386 		/* FIXHFAILURE; */
21387 		break;
21388 	    default:
21389 		break;
21390 	}
21391     }
21392     if (pctxt->nberrors != 0)
21393 	goto exit_error;
21394     /*
21395     * URGENT TODO: cos-element-consistent
21396     */
21397     goto exit;
21398 
21399 exit_error:
21400     ret = pctxt->err;
21401     goto exit;
21402 
21403 exit_failure:
21404     ret = -1;
21405 
21406 exit:
21407     /*
21408     * Reset the constructor. This is needed for XSI acquisition, since
21409     * those items will be processed over and over again for every XSI
21410     * if not cleared here.
21411     */
21412     con->bucket = oldbucket;
21413     con->pending->nbItems = 0;
21414     if (con->substGroups != NULL) {
21415 	xmlHashFree(con->substGroups, xmlSchemaSubstGroupFreeEntry);
21416 	con->substGroups = NULL;
21417     }
21418     if (con->redefs != NULL) {
21419 	xmlSchemaRedefListFree(con->redefs);
21420 	con->redefs = NULL;
21421     }
21422     return(ret);
21423 }
21424 /**
21425  * xmlSchemaParse:
21426  * @ctxt:  a schema validation context
21427  *
21428  * parse a schema definition resource and build an internal
21429  * XML Schema structure which can be used to validate instances.
21430  *
21431  * Returns the internal XML Schema structure built from the resource or
21432  *         NULL in case of error
21433  */
21434 xmlSchemaPtr
xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)21435 xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
21436 {
21437     xmlSchemaPtr mainSchema = NULL;
21438     xmlSchemaBucketPtr bucket = NULL;
21439     int res;
21440 
21441     /*
21442     * This one is used if the schema to be parsed was specified via
21443     * the API; i.e. not automatically by the validated instance document.
21444     */
21445 
21446     xmlSchemaInitTypes();
21447 
21448     if (ctxt == NULL)
21449         return (NULL);
21450 
21451     /* TODO: Init the context. Is this all we need?*/
21452     ctxt->nberrors = 0;
21453     ctxt->err = 0;
21454     ctxt->counter = 0;
21455 
21456     /* Create the *main* schema. */
21457     mainSchema = xmlSchemaNewSchema(ctxt);
21458     if (mainSchema == NULL)
21459 	goto exit_failure;
21460     /*
21461     * Create the schema constructor.
21462     */
21463     if (ctxt->constructor == NULL) {
21464 	ctxt->constructor = xmlSchemaConstructionCtxtCreate(ctxt->dict);
21465 	if (ctxt->constructor == NULL)
21466 	    return(NULL);
21467 	/* Take ownership of the constructor to be able to free it. */
21468 	ctxt->ownsConstructor = 1;
21469     }
21470     ctxt->constructor->mainSchema = mainSchema;
21471     /*
21472     * Locate and add the schema document.
21473     */
21474     res = xmlSchemaAddSchemaDoc(ctxt, XML_SCHEMA_SCHEMA_MAIN,
21475 	ctxt->URL, ctxt->doc, ctxt->buffer, ctxt->size, NULL,
21476 	NULL, NULL, &bucket);
21477     if (res == -1)
21478 	goto exit_failure;
21479     if (res != 0)
21480 	goto exit;
21481 
21482     if (bucket == NULL) {
21483 	/* TODO: Error code, actually we failed to *locate* the schema. */
21484 	if (ctxt->URL)
21485 	    xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21486 		NULL, NULL,
21487 		"Failed to locate the main schema resource at '%s'",
21488 		ctxt->URL, NULL);
21489 	else
21490 	    xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21491 		NULL, NULL,
21492 		"Failed to locate the main schema resource",
21493 		    NULL, NULL);
21494 	goto exit;
21495     }
21496     /* Then do the parsing for good. */
21497     if (xmlSchemaParseNewDocWithContext(ctxt, mainSchema, bucket) == -1)
21498 	goto exit_failure;
21499     if (ctxt->nberrors != 0)
21500 	goto exit;
21501 
21502     mainSchema->doc = bucket->doc;
21503     mainSchema->preserve = ctxt->preserve;
21504 
21505     ctxt->schema = mainSchema;
21506 
21507     if (xmlSchemaFixupComponents(ctxt, WXS_CONSTRUCTOR(ctxt)->mainBucket) == -1)
21508 	goto exit_failure;
21509 
21510     /*
21511     * TODO: This is not nice, since we cannot distinguish from the
21512     * result if there was an internal error or not.
21513     */
21514 exit:
21515     if (ctxt->nberrors != 0) {
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     }
21526     ctxt->schema = NULL;
21527     return(mainSchema);
21528 exit_failure:
21529     /*
21530     * Quite verbose, but should catch internal errors, which were
21531     * not communicated.
21532     */
21533     if (mainSchema) {
21534         xmlSchemaFree(mainSchema);
21535 	mainSchema = NULL;
21536     }
21537     if (ctxt->constructor) {
21538 	xmlSchemaConstructionCtxtFree(ctxt->constructor);
21539 	ctxt->constructor = NULL;
21540 	ctxt->ownsConstructor = 0;
21541     }
21542     PERROR_INT2("xmlSchemaParse",
21543 	"An internal error occurred");
21544     ctxt->schema = NULL;
21545     return(NULL);
21546 }
21547 
21548 /**
21549  * xmlSchemaSetParserErrors:
21550  * @ctxt:  a schema validation context
21551  * @err:  the error callback
21552  * @warn:  the warning callback
21553  * @ctx:  contextual data for the callbacks
21554  *
21555  * Set the callback functions used to handle errors for a validation context
21556  */
21557 void
xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,xmlSchemaValidityErrorFunc err,xmlSchemaValidityWarningFunc warn,void * ctx)21558 xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21559                          xmlSchemaValidityErrorFunc err,
21560                          xmlSchemaValidityWarningFunc warn, void *ctx)
21561 {
21562     if (ctxt == NULL)
21563         return;
21564     ctxt->error = err;
21565     ctxt->warning = warn;
21566     ctxt->errCtxt = ctx;
21567     if (ctxt->vctxt != NULL)
21568 	xmlSchemaSetValidErrors(ctxt->vctxt, err, warn, ctx);
21569 }
21570 
21571 /**
21572  * xmlSchemaSetParserStructuredErrors:
21573  * @ctxt:  a schema parser context
21574  * @serror:  the structured error function
21575  * @ctx: the functions context
21576  *
21577  * Set the structured error callback
21578  */
21579 void
xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,xmlStructuredErrorFunc serror,void * ctx)21580 xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,
21581 				   xmlStructuredErrorFunc serror,
21582 				   void *ctx)
21583 {
21584     if (ctxt == NULL)
21585 	return;
21586     ctxt->serror = serror;
21587     ctxt->errCtxt = ctx;
21588     if (ctxt->vctxt != NULL)
21589 	xmlSchemaSetValidStructuredErrors(ctxt->vctxt, serror, ctx);
21590 }
21591 
21592 /**
21593  * xmlSchemaGetParserErrors:
21594  * @ctxt:  a XMl-Schema parser context
21595  * @err: the error callback result
21596  * @warn: the warning callback result
21597  * @ctx: contextual data for the callbacks result
21598  *
21599  * Get the callback information used to handle errors for a parser context
21600  *
21601  * Returns -1 in case of failure, 0 otherwise
21602  */
21603 int
xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,xmlSchemaValidityErrorFunc * err,xmlSchemaValidityWarningFunc * warn,void ** ctx)21604 xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21605 			 xmlSchemaValidityErrorFunc * err,
21606 			 xmlSchemaValidityWarningFunc * warn, void **ctx)
21607 {
21608 	if (ctxt == NULL)
21609 		return(-1);
21610 	if (err != NULL)
21611 		*err = ctxt->error;
21612 	if (warn != NULL)
21613 		*warn = ctxt->warning;
21614 	if (ctx != NULL)
21615 		*ctx = ctxt->errCtxt;
21616 	return(0);
21617 }
21618 
21619 /**
21620  * xmlSchemaFacetTypeToString:
21621  * @type:  the facet type
21622  *
21623  * Convert the xmlSchemaTypeType to a char string.
21624  *
21625  * Returns the char string representation of the facet type if the
21626  *     type is a facet and an "Internal Error" string otherwise.
21627  */
21628 static const xmlChar *
xmlSchemaFacetTypeToString(xmlSchemaTypeType type)21629 xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
21630 {
21631     switch (type) {
21632         case XML_SCHEMA_FACET_PATTERN:
21633             return (BAD_CAST "pattern");
21634         case XML_SCHEMA_FACET_MAXEXCLUSIVE:
21635             return (BAD_CAST "maxExclusive");
21636         case XML_SCHEMA_FACET_MAXINCLUSIVE:
21637             return (BAD_CAST "maxInclusive");
21638         case XML_SCHEMA_FACET_MINEXCLUSIVE:
21639             return (BAD_CAST "minExclusive");
21640         case XML_SCHEMA_FACET_MININCLUSIVE:
21641             return (BAD_CAST "minInclusive");
21642         case XML_SCHEMA_FACET_WHITESPACE:
21643             return (BAD_CAST "whiteSpace");
21644         case XML_SCHEMA_FACET_ENUMERATION:
21645             return (BAD_CAST "enumeration");
21646         case XML_SCHEMA_FACET_LENGTH:
21647             return (BAD_CAST "length");
21648         case XML_SCHEMA_FACET_MAXLENGTH:
21649             return (BAD_CAST "maxLength");
21650         case XML_SCHEMA_FACET_MINLENGTH:
21651             return (BAD_CAST "minLength");
21652         case XML_SCHEMA_FACET_TOTALDIGITS:
21653             return (BAD_CAST "totalDigits");
21654         case XML_SCHEMA_FACET_FRACTIONDIGITS:
21655             return (BAD_CAST "fractionDigits");
21656         default:
21657             break;
21658     }
21659     return (BAD_CAST "Internal Error");
21660 }
21661 
21662 static xmlSchemaWhitespaceValueType
xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)21663 xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
21664 {
21665     /*
21666     * The normalization type can be changed only for types which are derived
21667     * from xsd:string.
21668     */
21669     if (type->type == XML_SCHEMA_TYPE_BASIC) {
21670 	/*
21671 	* Note that we assume a whitespace of preserve for anySimpleType.
21672 	*/
21673 	if ((type->builtInType == XML_SCHEMAS_STRING) ||
21674 	    (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
21675 	    return(XML_SCHEMA_WHITESPACE_PRESERVE);
21676 	else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
21677 	    return(XML_SCHEMA_WHITESPACE_REPLACE);
21678 	else {
21679 	    /*
21680 	    * For all `atomic` datatypes other than string (and types `derived`
21681 	    * by `restriction` from it) the value of whiteSpace is fixed to
21682 	    * collapse
21683 	    * Note that this includes built-in list datatypes.
21684 	    */
21685 	    return(XML_SCHEMA_WHITESPACE_COLLAPSE);
21686 	}
21687     } else if (WXS_IS_LIST(type)) {
21688 	/*
21689 	* For list types the facet "whiteSpace" is fixed to "collapse".
21690 	*/
21691 	return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21692     } else if (WXS_IS_UNION(type)) {
21693 	return (XML_SCHEMA_WHITESPACE_UNKNOWN);
21694     } else if (WXS_IS_ATOMIC(type)) {
21695 	if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
21696 	    return (XML_SCHEMA_WHITESPACE_PRESERVE);
21697 	else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
21698 	    return (XML_SCHEMA_WHITESPACE_REPLACE);
21699 	else
21700 	    return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21701     }
21702     return (-1);
21703 }
21704 
21705 /************************************************************************
21706  *									*
21707  *			Simple type validation				*
21708  *									*
21709  ************************************************************************/
21710 
21711 
21712 /************************************************************************
21713  *									*
21714  *			DOM Validation code				*
21715  *									*
21716  ************************************************************************/
21717 
21718 /**
21719  * xmlSchemaAssembleByLocation:
21720  * @pctxt:  a schema parser context
21721  * @vctxt:  a schema validation context
21722  * @schema: the existing schema
21723  * @node: the node that fired the assembling
21724  * @nsName: the namespace name of the new schema
21725  * @location: the location of the schema
21726  *
21727  * Expands an existing schema by an additional schema.
21728  *
21729  * Returns 0 if the new schema is correct, a positive error code
21730  * number otherwise and -1 in case of an internal or API error.
21731  */
21732 static int
xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,xmlSchemaPtr schema,xmlNodePtr node,const xmlChar * nsName,const xmlChar * location)21733 xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
21734 			    xmlSchemaPtr schema,
21735 			    xmlNodePtr node,
21736 			    const xmlChar *nsName,
21737 			    const xmlChar *location)
21738 {
21739     int ret = 0;
21740     xmlSchemaParserCtxtPtr pctxt;
21741     xmlSchemaBucketPtr bucket = NULL;
21742 
21743     if ((vctxt == NULL) || (schema == NULL))
21744 	return (-1);
21745 
21746     if (vctxt->pctxt == NULL) {
21747 	VERROR_INT("xmlSchemaAssembleByLocation",
21748 	    "no parser context available");
21749 	return(-1);
21750     }
21751     pctxt = vctxt->pctxt;
21752     if (pctxt->constructor == NULL) {
21753 	PERROR_INT("xmlSchemaAssembleByLocation",
21754 	    "no constructor");
21755 	return(-1);
21756     }
21757     /*
21758     * Acquire the schema document.
21759     */
21760     location = xmlSchemaBuildAbsoluteURI(pctxt->dict,
21761 	location, node);
21762     /*
21763     * Note that we pass XML_SCHEMA_SCHEMA_IMPORT here;
21764     * the process will automatically change this to
21765     * XML_SCHEMA_SCHEMA_MAIN if it is the first schema document.
21766     */
21767     ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
21768 	location, NULL, NULL, 0, node, NULL, nsName,
21769 	&bucket);
21770     if (ret != 0)
21771 	return(ret);
21772     if (bucket == NULL) {
21773 	/*
21774 	* Generate a warning that the document could not be located.
21775 	*/
21776 	xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21777 	    node, NULL,
21778 	    "The document at location '%s' could not be acquired",
21779 	    location, NULL, NULL);
21780 	return(ret);
21781     }
21782     /*
21783     * The first located schema will be handled as if all other
21784     * schemas imported by XSI were imported by this first schema.
21785     */
21786     if ((bucket != NULL) &&
21787 	(WXS_CONSTRUCTOR(pctxt)->bucket == NULL))
21788 	WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
21789     /*
21790     * TODO: Is this handled like an import? I.e. is it not an error
21791     * if the schema cannot be located?
21792     */
21793     if ((bucket == NULL) || (! CAN_PARSE_SCHEMA(bucket)))
21794 	return(0);
21795     /*
21796     * We will reuse the parser context for every schema imported
21797     * directly via XSI. So reset the context.
21798     */
21799     pctxt->nberrors = 0;
21800     pctxt->err = 0;
21801     pctxt->doc = bucket->doc;
21802 
21803     ret = xmlSchemaParseNewDocWithContext(pctxt, schema, bucket);
21804     if (ret == -1) {
21805 	pctxt->doc = NULL;
21806 	goto exit_failure;
21807     }
21808     /* Paranoid error channelling. */
21809     if ((ret == 0) && (pctxt->nberrors != 0))
21810 	ret = pctxt->err;
21811     if (pctxt->nberrors == 0) {
21812 	/*
21813 	* Only bother to fixup pending components, if there was
21814 	* no error yet.
21815 	* For every XSI acquired schema (and its sub-schemata) we will
21816 	* fixup the components.
21817 	*/
21818 	xmlSchemaFixupComponents(pctxt, bucket);
21819 	ret = pctxt->err;
21820 	/*
21821 	* Not nice, but we need somehow to channel the schema parser
21822 	* error to the validation context.
21823 	*/
21824 	if ((ret != 0) && (vctxt->err == 0))
21825 	    vctxt->err = ret;
21826 	vctxt->nberrors += pctxt->nberrors;
21827     } else {
21828 	/* Add to validation error sum. */
21829 	vctxt->nberrors += pctxt->nberrors;
21830     }
21831     pctxt->doc = NULL;
21832     return(ret);
21833 exit_failure:
21834     pctxt->doc = NULL;
21835     return (-1);
21836 }
21837 
21838 static xmlSchemaAttrInfoPtr
xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,int metaType)21839 xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
21840 			 int metaType)
21841 {
21842     if (vctxt->nbAttrInfos == 0)
21843 	return (NULL);
21844     {
21845 	int i;
21846 	xmlSchemaAttrInfoPtr iattr;
21847 
21848 	for (i = 0; i < vctxt->nbAttrInfos; i++) {
21849 	    iattr = vctxt->attrInfos[i];
21850 	    if (iattr->metaType == metaType)
21851 		return (iattr);
21852 	}
21853 
21854     }
21855     return (NULL);
21856 }
21857 
21858 /**
21859  * xmlSchemaAssembleByXSI:
21860  * @vctxt:  a schema validation context
21861  *
21862  * Expands an existing schema by an additional schema using
21863  * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
21864  * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
21865  * must be set to 1.
21866  *
21867  * Returns 0 if the new schema is correct, a positive error code
21868  * number otherwise and -1 in case of an internal or API error.
21869  */
21870 static int
xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)21871 xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
21872 {
21873     const xmlChar *cur, *end;
21874     const xmlChar *nsname = NULL, *location;
21875     int count = 0;
21876     int ret = 0;
21877     xmlSchemaAttrInfoPtr iattr;
21878 
21879     /*
21880     * Parse the value; we will assume an even number of values
21881     * to be given (this is how Xerces and XSV work).
21882     *
21883     * URGENT TODO: !! This needs to work for both
21884     * @noNamespaceSchemaLocation AND @schemaLocation on the same
21885     * element !!
21886     */
21887     iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21888 	XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
21889     if (iattr == NULL)
21890 	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21891 	XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
21892     if (iattr == NULL)
21893 	return (0);
21894     cur = iattr->value;
21895     do {
21896 	/*
21897 	* TODO: Move the string parsing mechanism away from here.
21898 	*/
21899 	if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
21900 	    /*
21901 	    * Get the namespace name.
21902 	    */
21903 	    while (IS_BLANK_CH(*cur))
21904 		cur++;
21905 	    end = cur;
21906 	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21907 		end++;
21908 	    if (end == cur)
21909 		break;
21910 	    count++; /* TODO: Don't use the schema's dict. */
21911 	    nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21912 	    cur = end;
21913 	}
21914 	/*
21915 	* Get the URI.
21916 	*/
21917 	while (IS_BLANK_CH(*cur))
21918 	    cur++;
21919 	end = cur;
21920 	while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21921 	    end++;
21922 	if (end == cur) {
21923 	    if (iattr->metaType ==
21924 		XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC)
21925 	    {
21926 		/*
21927 		* If using @schemaLocation then tuples are expected.
21928 		* I.e. the namespace name *and* the document's URI.
21929 		*/
21930 		xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21931 		    iattr->node, NULL,
21932 		    "The value must consist of tuples: the target namespace "
21933 		    "name and the document's URI", NULL, NULL, NULL);
21934 	    }
21935 	    break;
21936 	}
21937 	count++; /* TODO: Don't use the schema's dict. */
21938 	location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21939 	cur = end;
21940 	ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
21941 	    iattr->node, nsname, location);
21942 	if (ret == -1) {
21943 	    VERROR_INT("xmlSchemaAssembleByXSI",
21944 		"assembling schemata");
21945 	    return (-1);
21946 	}
21947     } while (*cur != 0);
21948     return (ret);
21949 }
21950 
21951 static const xmlChar *
xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,const xmlChar * prefix)21952 xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
21953 			 const xmlChar *prefix)
21954 {
21955     if (vctxt->sax != NULL) {
21956 	int i, j;
21957 	xmlSchemaNodeInfoPtr inode;
21958 
21959 	for (i = vctxt->depth; i >= 0; i--) {
21960 	    if (vctxt->elemInfos[i]->nbNsBindings != 0) {
21961 		inode = vctxt->elemInfos[i];
21962 		for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
21963 		    if (((prefix == NULL) &&
21964 			    (inode->nsBindings[j] == NULL)) ||
21965 			((prefix != NULL) && xmlStrEqual(prefix,
21966 			    inode->nsBindings[j]))) {
21967 
21968 			/*
21969 			* Note that the namespace bindings are already
21970 			* in a string dict.
21971 			*/
21972 			return (inode->nsBindings[j+1]);
21973 		    }
21974 		}
21975 	    }
21976 	}
21977 	return (NULL);
21978 #ifdef LIBXML_READER_ENABLED
21979     } else if (vctxt->reader != NULL) {
21980 	xmlChar *nsName;
21981 
21982 	nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
21983 	if (nsName != NULL) {
21984 	    const xmlChar *ret;
21985 
21986 	    ret = xmlDictLookup(vctxt->dict, nsName, -1);
21987 	    xmlFree(nsName);
21988 	    return (ret);
21989 	} else
21990 	    return (NULL);
21991 #endif
21992     } else {
21993 	xmlNsPtr ns;
21994 
21995 	if ((vctxt->inode->node == NULL) ||
21996 	    (vctxt->inode->node->doc == NULL)) {
21997 	    VERROR_INT("xmlSchemaLookupNamespace",
21998 		"no node or node's doc available");
21999 	    return (NULL);
22000 	}
22001 	ns = xmlSearchNs(vctxt->inode->node->doc,
22002 	    vctxt->inode->node, prefix);
22003 	if (ns != NULL)
22004 	    return (ns->href);
22005 	return (NULL);
22006     }
22007 }
22008 
22009 /*
22010 * This one works on the schema of the validation context.
22011 */
22012 static int
xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,xmlSchemaPtr schema,xmlNodePtr node,const xmlChar * value,xmlSchemaValPtr * val,int valNeeded)22013 xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
22014 			  xmlSchemaPtr schema,
22015 			  xmlNodePtr node,
22016 			  const xmlChar *value,
22017 			  xmlSchemaValPtr *val,
22018 			  int valNeeded)
22019 {
22020     int ret;
22021 
22022     if (vctxt && (vctxt->schema == NULL)) {
22023 	VERROR_INT("xmlSchemaValidateNotation",
22024 	    "a schema is needed on the validation context");
22025 	return (-1);
22026     }
22027     ret = xmlValidateQName(value, 1);
22028     if (ret != 0)
22029 	return (ret);
22030     {
22031 	xmlChar *localName = NULL;
22032 	xmlChar *prefix = NULL;
22033 
22034 	localName = xmlSplitQName2(value, &prefix);
22035 	if (prefix != NULL) {
22036 	    const xmlChar *nsName = NULL;
22037 
22038 	    if (vctxt != NULL)
22039 		nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
22040 	    else if (node != NULL) {
22041 		xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
22042 		if (ns != NULL)
22043 		    nsName = ns->href;
22044 	    } else {
22045 		xmlFree(prefix);
22046 		xmlFree(localName);
22047 		return (1);
22048 	    }
22049 	    if (nsName == NULL) {
22050 		xmlFree(prefix);
22051 		xmlFree(localName);
22052 		return (1);
22053 	    }
22054 	    if (xmlSchemaGetNotation(schema, localName, nsName) != NULL) {
22055 		if ((valNeeded) && (val != NULL)) {
22056 		    (*val) = xmlSchemaNewNOTATIONValue(xmlStrdup(localName),
22057 						       xmlStrdup(nsName));
22058 		    if (*val == NULL)
22059 			ret = -1;
22060 		}
22061 	    } else
22062 		ret = 1;
22063 	    xmlFree(prefix);
22064 	    xmlFree(localName);
22065 	} else {
22066 	    if (xmlSchemaGetNotation(schema, value, NULL) != NULL) {
22067 		if (valNeeded && (val != NULL)) {
22068 		    (*val) = xmlSchemaNewNOTATIONValue(
22069 			BAD_CAST xmlStrdup(value), NULL);
22070 		    if (*val == NULL)
22071 			ret = -1;
22072 		}
22073 	    } else
22074 		return (1);
22075 	}
22076     }
22077     return (ret);
22078 }
22079 
22080 static int
xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,const xmlChar * lname,const xmlChar * nsname)22081 xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,
22082 		       const xmlChar* lname,
22083 		       const xmlChar* nsname)
22084 {
22085     int i;
22086 
22087     lname = xmlDictLookup(vctxt->dict, lname, -1);
22088     if (lname == NULL)
22089 	return(-1);
22090     if (nsname != NULL) {
22091 	nsname = xmlDictLookup(vctxt->dict, nsname, -1);
22092 	if (nsname == NULL)
22093 	    return(-1);
22094     }
22095     for (i = 0; i < vctxt->nodeQNames->nbItems; i += 2) {
22096 	if ((vctxt->nodeQNames->items [i] == lname) &&
22097 	    (vctxt->nodeQNames->items[i +1] == nsname))
22098 	    /* Already there */
22099 	    return(i);
22100     }
22101     /* Add new entry. */
22102     i = vctxt->nodeQNames->nbItems;
22103     xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) lname);
22104     xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) nsname);
22105     return(i);
22106 }
22107 
22108 /************************************************************************
22109  *									*
22110  *  Validation of identity-constraints (IDC)                            *
22111  *									*
22112  ************************************************************************/
22113 
22114 /**
22115  * xmlSchemaAugmentIDC:
22116  * @idcDef: the IDC definition
22117  *
22118  * Creates an augmented IDC definition item.
22119  *
22120  * Returns the item, or NULL on internal errors.
22121  */
22122 static void
xmlSchemaAugmentIDC(void * payload,void * data,const xmlChar * name ATTRIBUTE_UNUSED)22123 xmlSchemaAugmentIDC(void *payload, void *data,
22124                     const xmlChar *name ATTRIBUTE_UNUSED)
22125 {
22126     xmlSchemaIDCPtr idcDef = (xmlSchemaIDCPtr) payload;
22127     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) data;
22128     xmlSchemaIDCAugPtr aidc;
22129 
22130     aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
22131     if (aidc == NULL) {
22132 	xmlSchemaVErrMemory(vctxt,
22133 	    "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
22134 	    NULL);
22135 	return;
22136     }
22137     aidc->keyrefDepth = -1;
22138     aidc->def = idcDef;
22139     aidc->next = NULL;
22140     if (vctxt->aidcs == NULL)
22141 	vctxt->aidcs = aidc;
22142     else {
22143 	aidc->next = vctxt->aidcs;
22144 	vctxt->aidcs = aidc;
22145     }
22146     /*
22147     * Save if we have keyrefs at all.
22148     */
22149     if ((vctxt->hasKeyrefs == 0) &&
22150 	(idcDef->type == XML_SCHEMA_TYPE_IDC_KEYREF))
22151 	vctxt->hasKeyrefs = 1;
22152 }
22153 
22154 /**
22155  * xmlSchemaAugmentImportedIDC:
22156  * @imported: the imported schema
22157  *
22158  * Creates an augmented IDC definition for the imported schema.
22159  */
22160 static void
xmlSchemaAugmentImportedIDC(void * payload,void * data,const xmlChar * name ATTRIBUTE_UNUSED)22161 xmlSchemaAugmentImportedIDC(void *payload, void *data,
22162                             const xmlChar *name ATTRIBUTE_UNUSED) {
22163     xmlSchemaImportPtr imported = (xmlSchemaImportPtr) payload;
22164     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) data;
22165     if (imported->schema->idcDef != NULL) {
22166 	    xmlHashScan(imported->schema->idcDef, xmlSchemaAugmentIDC, vctxt);
22167     }
22168 }
22169 
22170 /**
22171  * xmlSchemaIDCNewBinding:
22172  * @idcDef: the IDC definition of this binding
22173  *
22174  * Creates a new IDC binding.
22175  *
22176  * Returns the new IDC binding, NULL on internal errors.
22177  */
22178 static xmlSchemaPSVIIDCBindingPtr
xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)22179 xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
22180 {
22181     xmlSchemaPSVIIDCBindingPtr ret;
22182 
22183     ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
22184 	    sizeof(xmlSchemaPSVIIDCBinding));
22185     if (ret == NULL) {
22186 	xmlSchemaVErrMemory(NULL,
22187 	    "allocating a PSVI IDC binding item", NULL);
22188 	return (NULL);
22189     }
22190     memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
22191     ret->definition = idcDef;
22192     return (ret);
22193 }
22194 
22195 /**
22196  * xmlSchemaIDCStoreNodeTableItem:
22197  * @vctxt: the WXS validation context
22198  * @item: the IDC node table item
22199  *
22200  * The validation context is used to store IDC node table items.
22201  * They are stored to avoid copying them if IDC node-tables are merged
22202  * with corresponding parent IDC node-tables (bubbling).
22203  *
22204  * Returns 0 if succeeded, -1 on internal errors.
22205  */
22206 static int
xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,xmlSchemaPSVIIDCNodePtr item)22207 xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
22208 			       xmlSchemaPSVIIDCNodePtr item)
22209 {
22210     /*
22211     * Add to global list.
22212     */
22213     if (vctxt->idcNodes == NULL) {
22214 	vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22215 	    xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
22216 	if (vctxt->idcNodes == NULL) {
22217 	    xmlSchemaVErrMemory(vctxt,
22218 		"allocating the IDC node table item list", NULL);
22219 	    return (-1);
22220 	}
22221 	vctxt->sizeIdcNodes = 20;
22222     } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
22223 	vctxt->sizeIdcNodes *= 2;
22224 	vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22225 	    xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
22226 	    sizeof(xmlSchemaPSVIIDCNodePtr));
22227 	if (vctxt->idcNodes == NULL) {
22228 	    xmlSchemaVErrMemory(vctxt,
22229 		"re-allocating the IDC node table item list", NULL);
22230 	    return (-1);
22231 	}
22232     }
22233     vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
22234 
22235     return (0);
22236 }
22237 
22238 /**
22239  * xmlSchemaIDCStoreKey:
22240  * @vctxt: the WXS validation context
22241  * @item: the IDC key
22242  *
22243  * The validation context is used to store an IDC key.
22244  *
22245  * Returns 0 if succeeded, -1 on internal errors.
22246  */
22247 static int
xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,xmlSchemaPSVIIDCKeyPtr key)22248 xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
22249 		     xmlSchemaPSVIIDCKeyPtr key)
22250 {
22251     /*
22252     * Add to global list.
22253     */
22254     if (vctxt->idcKeys == NULL) {
22255 	vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22256 	    xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
22257 	if (vctxt->idcKeys == NULL) {
22258 	    xmlSchemaVErrMemory(vctxt,
22259 		"allocating the IDC key storage list", NULL);
22260 	    return (-1);
22261 	}
22262 	vctxt->sizeIdcKeys = 40;
22263     } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
22264 	vctxt->sizeIdcKeys *= 2;
22265 	vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22266 	    xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
22267 	    sizeof(xmlSchemaPSVIIDCKeyPtr));
22268 	if (vctxt->idcKeys == NULL) {
22269 	    xmlSchemaVErrMemory(vctxt,
22270 		"re-allocating the IDC key storage list", NULL);
22271 	    return (-1);
22272 	}
22273     }
22274     vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
22275 
22276     return (0);
22277 }
22278 
22279 /**
22280  * xmlSchemaIDCAppendNodeTableItem:
22281  * @bind: the IDC binding
22282  * @ntItem: the node-table item
22283  *
22284  * Appends the IDC node-table item to the binding.
22285  *
22286  * Returns 0 on success and -1 on internal errors.
22287  */
22288 static int
xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,xmlSchemaPSVIIDCNodePtr ntItem)22289 xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
22290 				xmlSchemaPSVIIDCNodePtr ntItem)
22291 {
22292     if (bind->nodeTable == NULL) {
22293 	bind->sizeNodes = 10;
22294 	bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22295 	    xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
22296 	if (bind->nodeTable == NULL) {
22297 	    xmlSchemaVErrMemory(NULL,
22298 		"allocating an array of IDC node-table items", NULL);
22299 	    return(-1);
22300 	}
22301     } else if (bind->sizeNodes <= bind->nbNodes) {
22302 	bind->sizeNodes *= 2;
22303 	bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22304 	    xmlRealloc(bind->nodeTable, bind->sizeNodes *
22305 		sizeof(xmlSchemaPSVIIDCNodePtr));
22306 	if (bind->nodeTable == NULL) {
22307 	    xmlSchemaVErrMemory(NULL,
22308 		"re-allocating an array of IDC node-table items", NULL);
22309 	    return(-1);
22310 	}
22311     }
22312     bind->nodeTable[bind->nbNodes++] = ntItem;
22313     return(0);
22314 }
22315 
22316 /**
22317  * xmlSchemaIDCAcquireBinding:
22318  * @vctxt: the WXS validation context
22319  * @matcher: the IDC matcher
22320  *
22321  * Looks up an PSVI IDC binding, for the IDC definition and
22322  * of the given matcher. If none found, a new one is created
22323  * and added to the IDC table.
22324  *
22325  * Returns an IDC binding or NULL on internal errors.
22326  */
22327 static xmlSchemaPSVIIDCBindingPtr
xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,xmlSchemaIDCMatcherPtr matcher)22328 xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,
22329 			  xmlSchemaIDCMatcherPtr matcher)
22330 {
22331     xmlSchemaNodeInfoPtr ielem;
22332 
22333     ielem = vctxt->elemInfos[matcher->depth];
22334 
22335     if (ielem->idcTable == NULL) {
22336 	ielem->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
22337 	if (ielem->idcTable == NULL)
22338 	    return (NULL);
22339 	return(ielem->idcTable);
22340     } else {
22341 	xmlSchemaPSVIIDCBindingPtr bind = NULL;
22342 
22343 	bind = ielem->idcTable;
22344 	do {
22345 	    if (bind->definition == matcher->aidc->def)
22346 		return(bind);
22347 	    if (bind->next == NULL) {
22348 		bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
22349 		if (bind->next == NULL)
22350 		    return (NULL);
22351 		return(bind->next);
22352 	    }
22353 	    bind = bind->next;
22354 	} while (bind != NULL);
22355     }
22356     return (NULL);
22357 }
22358 
22359 static xmlSchemaItemListPtr
xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,xmlSchemaIDCMatcherPtr matcher)22360 xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
22361 			     xmlSchemaIDCMatcherPtr matcher)
22362 {
22363     if (matcher->targets == NULL)
22364 	matcher->targets = xmlSchemaItemListCreate();
22365     return(matcher->targets);
22366 }
22367 
22368 /**
22369  * xmlSchemaIDCFreeKey:
22370  * @key: the IDC key
22371  *
22372  * Frees an IDC key together with its compiled value.
22373  */
22374 static void
xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)22375 xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
22376 {
22377     if (key->val != NULL)
22378 	xmlSchemaFreeValue(key->val);
22379     xmlFree(key);
22380 }
22381 
22382 /**
22383  * xmlSchemaIDCFreeBinding:
22384  *
22385  * Frees an IDC binding. Note that the node table-items
22386  * are not freed.
22387  */
22388 static void
xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)22389 xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
22390 {
22391     if (bind->nodeTable != NULL)
22392 	xmlFree(bind->nodeTable);
22393     if (bind->dupls != NULL)
22394 	xmlSchemaItemListFree(bind->dupls);
22395     xmlFree(bind);
22396 }
22397 
22398 /**
22399  * xmlSchemaIDCFreeIDCTable:
22400  * @bind: the first IDC binding in the list
22401  *
22402  * Frees an IDC table, i.e. all the IDC bindings in the list.
22403  */
22404 static void
xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)22405 xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
22406 {
22407     xmlSchemaPSVIIDCBindingPtr prev;
22408 
22409     while (bind != NULL) {
22410 	prev = bind;
22411 	bind = bind->next;
22412 	xmlSchemaIDCFreeBinding(prev);
22413     }
22414 }
22415 
22416 static void
xmlFreeIDCHashEntry(void * payload,const xmlChar * name ATTRIBUTE_UNUSED)22417 xmlFreeIDCHashEntry (void *payload, const xmlChar *name ATTRIBUTE_UNUSED)
22418 {
22419     xmlIDCHashEntryPtr e = payload, n;
22420     while (e) {
22421 	n = e->next;
22422 	xmlFree(e);
22423 	e = n;
22424     }
22425 }
22426 
22427 /**
22428  * xmlSchemaIDCFreeMatcherList:
22429  * @matcher: the first IDC matcher in the list
22430  *
22431  * Frees a list of IDC matchers.
22432  */
22433 static void
xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)22434 xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
22435 {
22436     xmlSchemaIDCMatcherPtr next;
22437 
22438     while (matcher != NULL) {
22439 	next = matcher->next;
22440 	if (matcher->keySeqs != NULL) {
22441 	    int i;
22442 	    for (i = 0; i < matcher->sizeKeySeqs; i++)
22443 		if (matcher->keySeqs[i] != NULL)
22444 		    xmlFree(matcher->keySeqs[i]);
22445 	    xmlFree(matcher->keySeqs);
22446 	}
22447 	if (matcher->targets != NULL) {
22448 	    if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22449 		int i;
22450 		xmlSchemaPSVIIDCNodePtr idcNode;
22451 		/*
22452 		* Node-table items for keyrefs are not stored globally
22453 		* to the validation context, since they are not bubbled.
22454 		* We need to free them here.
22455 		*/
22456 		for (i = 0; i < matcher->targets->nbItems; i++) {
22457 		    idcNode =
22458 			(xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22459 		    xmlFree(idcNode->keys);
22460 		    xmlFree(idcNode);
22461 		}
22462 	    }
22463 	    xmlSchemaItemListFree(matcher->targets);
22464 	}
22465 	if (matcher->htab != NULL)
22466 	  xmlHashFree(matcher->htab, xmlFreeIDCHashEntry);
22467 	xmlFree(matcher);
22468 	matcher = next;
22469     }
22470 }
22471 
22472 /**
22473  * xmlSchemaIDCReleaseMatcherList:
22474  * @vctxt: the WXS validation context
22475  * @matcher: the first IDC matcher in the list
22476  *
22477  * Caches a list of IDC matchers for reuse.
22478  */
22479 static void
xmlSchemaIDCReleaseMatcherList(xmlSchemaValidCtxtPtr vctxt,xmlSchemaIDCMatcherPtr matcher)22480 xmlSchemaIDCReleaseMatcherList(xmlSchemaValidCtxtPtr vctxt,
22481 			       xmlSchemaIDCMatcherPtr matcher)
22482 {
22483     xmlSchemaIDCMatcherPtr next;
22484 
22485     while (matcher != NULL) {
22486 	next = matcher->next;
22487 	if (matcher->keySeqs != NULL) {
22488 	    int i;
22489 	    /*
22490 	    * Don't free the array, but only the content.
22491 	    */
22492 	    for (i = 0; i < matcher->sizeKeySeqs; i++)
22493 		if (matcher->keySeqs[i] != NULL) {
22494 		    xmlFree(matcher->keySeqs[i]);
22495 		    matcher->keySeqs[i] = NULL;
22496 		}
22497 	}
22498 	if (matcher->targets) {
22499 	    if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22500 		int i;
22501 		xmlSchemaPSVIIDCNodePtr idcNode;
22502 		/*
22503 		* Node-table items for keyrefs are not stored globally
22504 		* to the validation context, since they are not bubbled.
22505 		* We need to free them here.
22506 		*/
22507 		for (i = 0; i < matcher->targets->nbItems; i++) {
22508 		    idcNode =
22509 			(xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22510 		    xmlFree(idcNode->keys);
22511 		    xmlFree(idcNode);
22512 		}
22513 	    }
22514 	    xmlSchemaItemListFree(matcher->targets);
22515 	    matcher->targets = NULL;
22516 	}
22517 	if (matcher->htab != NULL) {
22518 	    xmlHashFree(matcher->htab, xmlFreeIDCHashEntry);
22519 	    matcher->htab = NULL;
22520 	}
22521 	matcher->next = NULL;
22522 	/*
22523 	* Cache the matcher.
22524 	*/
22525 	if (vctxt->idcMatcherCache != NULL)
22526 	    matcher->nextCached = vctxt->idcMatcherCache;
22527 	vctxt->idcMatcherCache = matcher;
22528 
22529 	matcher = next;
22530     }
22531 }
22532 
22533 /**
22534  * xmlSchemaIDCAddStateObject:
22535  * @vctxt: the WXS validation context
22536  * @matcher: the IDC matcher
22537  * @sel: the XPath information
22538  * @parent: the parent "selector" state object if any
22539  * @type: "selector" or "field"
22540  *
22541  * Creates/reuses and activates state objects for the given
22542  * XPath information; if the XPath expression consists of unions,
22543  * multiple state objects are created for every unioned expression.
22544  *
22545  * Returns 0 on success and -1 on internal errors.
22546  */
22547 static int
xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,xmlSchemaIDCMatcherPtr matcher,xmlSchemaIDCSelectPtr sel,int type)22548 xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
22549 			xmlSchemaIDCMatcherPtr matcher,
22550 			xmlSchemaIDCSelectPtr sel,
22551 			int type)
22552 {
22553     xmlSchemaIDCStateObjPtr sto;
22554 
22555     /*
22556     * Reuse the state objects from the pool.
22557     */
22558     if (vctxt->xpathStatePool != NULL) {
22559 	sto = vctxt->xpathStatePool;
22560 	vctxt->xpathStatePool = sto->next;
22561 	sto->next = NULL;
22562     } else {
22563 	/*
22564 	* Create a new state object.
22565 	*/
22566 	sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
22567 	if (sto == NULL) {
22568 	    xmlSchemaVErrMemory(NULL,
22569 		"allocating an IDC state object", NULL);
22570 	    return (-1);
22571 	}
22572 	memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
22573     }
22574     /*
22575     * Add to global list.
22576     */
22577     if (vctxt->xpathStates != NULL)
22578 	sto->next = vctxt->xpathStates;
22579     vctxt->xpathStates = sto;
22580 
22581     /*
22582     * Free the old xpath validation context.
22583     */
22584     if (sto->xpathCtxt != NULL)
22585 	xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
22586 
22587     /*
22588     * Create a new XPath (pattern) validation context.
22589     */
22590     sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
22591 	(xmlPatternPtr) sel->xpathComp);
22592     if (sto->xpathCtxt == NULL) {
22593 	VERROR_INT("xmlSchemaIDCAddStateObject",
22594 	    "failed to create an XPath validation context");
22595 	return (-1);
22596     }
22597     sto->type = type;
22598     sto->depth = vctxt->depth;
22599     sto->matcher = matcher;
22600     sto->sel = sel;
22601     sto->nbHistory = 0;
22602 
22603 #ifdef DEBUG_IDC
22604     xmlGenericError(xmlGenericErrorContext, "IDC:   STO push '%s'\n",
22605 	sto->sel->xpath);
22606 #endif
22607     return (0);
22608 }
22609 
22610 /**
22611  * xmlSchemaXPathEvaluate:
22612  * @vctxt: the WXS validation context
22613  * @nodeType: the nodeType of the current node
22614  *
22615  * Evaluates all active XPath state objects.
22616  *
22617  * Returns the number of IC "field" state objects which resolved to
22618  * this node, 0 if none resolved and -1 on internal errors.
22619  */
22620 static int
xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,xmlElementType nodeType)22621 xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
22622 		       xmlElementType nodeType)
22623 {
22624     xmlSchemaIDCStateObjPtr sto, head = NULL, first;
22625     int res, resolved = 0, depth = vctxt->depth;
22626 
22627     if (vctxt->xpathStates == NULL)
22628 	return (0);
22629 
22630     if (nodeType == XML_ATTRIBUTE_NODE)
22631 	depth++;
22632 #ifdef DEBUG_IDC
22633     {
22634 	xmlChar *str = NULL;
22635 	xmlGenericError(xmlGenericErrorContext,
22636 	    "IDC: EVAL on %s, depth %d, type %d\n",
22637 	    xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22638 		vctxt->inode->localName), depth, nodeType);
22639 	FREE_AND_NULL(str)
22640     }
22641 #endif
22642     /*
22643     * Process all active XPath state objects.
22644     */
22645     first = vctxt->xpathStates;
22646     sto = first;
22647     while (sto != head) {
22648 #ifdef DEBUG_IDC
22649 	if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
22650 	    xmlGenericError(xmlGenericErrorContext, "IDC:   ['%s'] selector '%s'\n",
22651 		sto->matcher->aidc->def->name, sto->sel->xpath);
22652 	else
22653 	    xmlGenericError(xmlGenericErrorContext, "IDC:   ['%s'] field '%s'\n",
22654 		sto->matcher->aidc->def->name, sto->sel->xpath);
22655 #endif
22656 	if (nodeType == XML_ELEMENT_NODE)
22657 	    res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
22658 		vctxt->inode->localName, vctxt->inode->nsName);
22659 	else
22660 	    res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
22661 		vctxt->inode->localName, vctxt->inode->nsName);
22662 
22663 	if (res == -1) {
22664 	    VERROR_INT("xmlSchemaXPathEvaluate",
22665 		"calling xmlStreamPush()");
22666 	    return (-1);
22667 	}
22668 	if (res == 0)
22669 	    goto next_sto;
22670 	/*
22671 	* Full match.
22672 	*/
22673 #ifdef DEBUG_IDC
22674 	xmlGenericError(xmlGenericErrorContext, "IDC:     "
22675 	    "MATCH\n");
22676 #endif
22677 	/*
22678 	* Register a match in the state object history.
22679 	*/
22680 	if (sto->history == NULL) {
22681 	    sto->history = (int *) xmlMalloc(5 * sizeof(int));
22682 	    if (sto->history == NULL) {
22683 		xmlSchemaVErrMemory(NULL,
22684 		    "allocating the state object history", NULL);
22685 		return(-1);
22686 	    }
22687 	    sto->sizeHistory = 5;
22688 	} else if (sto->sizeHistory <= sto->nbHistory) {
22689 	    sto->sizeHistory *= 2;
22690 	    sto->history = (int *) xmlRealloc(sto->history,
22691 		sto->sizeHistory * sizeof(int));
22692 	    if (sto->history == NULL) {
22693 		xmlSchemaVErrMemory(NULL,
22694 		    "re-allocating the state object history", NULL);
22695 		return(-1);
22696 	    }
22697 	}
22698 	sto->history[sto->nbHistory++] = depth;
22699 
22700 #ifdef DEBUG_IDC
22701 	xmlGenericError(xmlGenericErrorContext, "IDC:       push match '%d'\n",
22702 	    vctxt->depth);
22703 #endif
22704 
22705 	if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22706 	    xmlSchemaIDCSelectPtr sel;
22707 	    /*
22708 	    * Activate state objects for the IDC fields of
22709 	    * the IDC selector.
22710 	    */
22711 #ifdef DEBUG_IDC
22712 	    xmlGenericError(xmlGenericErrorContext, "IDC:     "
22713 		"activating field states\n");
22714 #endif
22715 	    sel = sto->matcher->aidc->def->fields;
22716 	    while (sel != NULL) {
22717 		if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
22718 		    sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
22719 		    return (-1);
22720 		sel = sel->next;
22721 	    }
22722 	} else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22723 	    /*
22724 	    * An IDC key node was found by the IDC field.
22725 	    */
22726 #ifdef DEBUG_IDC
22727 	    xmlGenericError(xmlGenericErrorContext,
22728 		"IDC:     key found\n");
22729 #endif
22730 	    /*
22731 	    * Notify that the character value of this node is
22732 	    * needed.
22733 	    */
22734 	    if (resolved == 0) {
22735 		if ((vctxt->inode->flags &
22736 		    XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
22737 		vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
22738 	    }
22739 	    resolved++;
22740 	}
22741 next_sto:
22742 	if (sto->next == NULL) {
22743 	    /*
22744 	    * Evaluate field state objects created on this node as well.
22745 	    */
22746 	    head = first;
22747 	    sto = vctxt->xpathStates;
22748 	} else
22749 	    sto = sto->next;
22750     }
22751     return (resolved);
22752 }
22753 
22754 static const xmlChar *
xmlSchemaFormatIDCKeySequence_1(xmlSchemaValidCtxtPtr vctxt,xmlChar ** buf,xmlSchemaPSVIIDCKeyPtr * seq,int count,int for_hash)22755 xmlSchemaFormatIDCKeySequence_1(xmlSchemaValidCtxtPtr vctxt,
22756 				xmlChar **buf,
22757 				xmlSchemaPSVIIDCKeyPtr *seq,
22758 				int count, int for_hash)
22759 {
22760     int i, res;
22761     xmlChar *value = NULL;
22762 
22763     *buf = xmlStrdup(BAD_CAST "[");
22764     for (i = 0; i < count; i++) {
22765 	*buf = xmlStrcat(*buf, BAD_CAST "'");
22766 	if (!for_hash)
22767 	    res = xmlSchemaGetCanonValueWhtspExt(seq[i]->val,
22768 		    xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type),
22769 		    &value);
22770 	else {
22771 	    res = xmlSchemaGetCanonValueHash(seq[i]->val, &value);
22772 	}
22773 	if (res == 0)
22774 	    *buf = xmlStrcat(*buf, BAD_CAST value);
22775 	else {
22776 	    VERROR_INT("xmlSchemaFormatIDCKeySequence",
22777 		"failed to compute a canonical value");
22778 	    *buf = xmlStrcat(*buf, BAD_CAST "???");
22779 	}
22780 	if (i < count -1)
22781 	    *buf = xmlStrcat(*buf, BAD_CAST "', ");
22782 	else
22783 	    *buf = xmlStrcat(*buf, BAD_CAST "'");
22784 	if (value != NULL) {
22785 	    xmlFree(value);
22786 	    value = NULL;
22787 	}
22788     }
22789     *buf = xmlStrcat(*buf, BAD_CAST "]");
22790 
22791     return (BAD_CAST *buf);
22792 }
22793 
22794 static const xmlChar *
xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,xmlChar ** buf,xmlSchemaPSVIIDCKeyPtr * seq,int count)22795 xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
22796 			      xmlChar **buf,
22797 			      xmlSchemaPSVIIDCKeyPtr *seq,
22798 			      int count)
22799 {
22800     return xmlSchemaFormatIDCKeySequence_1(vctxt, buf, seq, count, 0);
22801 }
22802 
22803 static const xmlChar *
xmlSchemaHashKeySequence(xmlSchemaValidCtxtPtr vctxt,xmlChar ** buf,xmlSchemaPSVIIDCKeyPtr * seq,int count)22804 xmlSchemaHashKeySequence(xmlSchemaValidCtxtPtr vctxt,
22805 			 xmlChar **buf,
22806 			 xmlSchemaPSVIIDCKeyPtr *seq,
22807 			 int count)
22808 {
22809     return xmlSchemaFormatIDCKeySequence_1(vctxt, buf, seq, count, 1);
22810 }
22811 
22812 /**
22813  * xmlSchemaXPathPop:
22814  * @vctxt: the WXS validation context
22815  *
22816  * Pops all XPath states.
22817  *
22818  * Returns 0 on success and -1 on internal errors.
22819  */
22820 static int
xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)22821 xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)
22822 {
22823     xmlSchemaIDCStateObjPtr sto;
22824     int res;
22825 
22826     if (vctxt->xpathStates == NULL)
22827 	return(0);
22828     sto = vctxt->xpathStates;
22829     do {
22830 	res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22831 	if (res == -1)
22832 	    return (-1);
22833 	sto = sto->next;
22834     } while (sto != NULL);
22835     return(0);
22836 }
22837 
22838 /**
22839  * xmlSchemaXPathProcessHistory:
22840  * @vctxt: the WXS validation context
22841  * @type: the simple/complex type of the current node if any at all
22842  * @val: the precompiled value
22843  *
22844  * Processes and pops the history items of the IDC state objects.
22845  * IDC key-sequences are validated/created on IDC bindings.
22846  *
22847  * Returns 0 on success and -1 on internal errors.
22848  */
22849 static int
xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,int depth)22850 xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
22851 			     int depth)
22852 {
22853     xmlSchemaIDCStateObjPtr sto, nextsto;
22854     int res, matchDepth;
22855     xmlSchemaPSVIIDCKeyPtr key = NULL;
22856     xmlSchemaTypePtr type = vctxt->inode->typeDef, simpleType = NULL;
22857 
22858     if (vctxt->xpathStates == NULL)
22859 	return (0);
22860     sto = vctxt->xpathStates;
22861 
22862 #ifdef DEBUG_IDC
22863     {
22864 	xmlChar *str = NULL;
22865 	xmlGenericError(xmlGenericErrorContext,
22866 	    "IDC: BACK on %s, depth %d\n",
22867 	    xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22868 		vctxt->inode->localName), vctxt->depth);
22869 	FREE_AND_NULL(str)
22870     }
22871 #endif
22872     /*
22873     * Evaluate the state objects.
22874     */
22875     while (sto != NULL) {
22876 	res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22877 	if (res == -1) {
22878 	    VERROR_INT("xmlSchemaXPathProcessHistory",
22879 		"calling xmlStreamPop()");
22880 	    return (-1);
22881 	}
22882 #ifdef DEBUG_IDC
22883 	xmlGenericError(xmlGenericErrorContext, "IDC:   stream pop '%s'\n",
22884 	    sto->sel->xpath);
22885 #endif
22886 	if (sto->nbHistory == 0)
22887 	    goto deregister_check;
22888 
22889 	matchDepth = sto->history[sto->nbHistory -1];
22890 
22891 	/*
22892 	* Only matches at the current depth are of interest.
22893 	*/
22894 	if (matchDepth != depth) {
22895 	    sto = sto->next;
22896 	    continue;
22897 	}
22898 	if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22899 	    /*
22900 	    * NOTE: According to
22901 	    *   http://www.w3.org/Bugs/Public/show_bug.cgi?id=2198
22902 	    *   ... the simple-content of complex types is also allowed.
22903 	    */
22904 
22905 	    if (WXS_IS_COMPLEX(type)) {
22906 		if (WXS_HAS_SIMPLE_CONTENT(type)) {
22907 		    /*
22908 		    * Sanity check for complex types with simple content.
22909 		    */
22910 		    simpleType = type->contentTypeDef;
22911 		    if (simpleType == NULL) {
22912 			VERROR_INT("xmlSchemaXPathProcessHistory",
22913 			    "field resolves to a CT with simple content "
22914 			    "but the CT is missing the ST definition");
22915 			return (-1);
22916 		    }
22917 		} else
22918 		    simpleType = NULL;
22919 	    } else
22920 		simpleType = type;
22921 	    if (simpleType == NULL) {
22922 		xmlChar *str = NULL;
22923 
22924 		/*
22925 		* Not qualified if the field resolves to a node of non
22926 		* simple type.
22927 		*/
22928 		xmlSchemaCustomErr(ACTXT_CAST vctxt,
22929 		    XML_SCHEMAV_CVC_IDC, NULL,
22930 		    WXS_BASIC_CAST sto->matcher->aidc->def,
22931 		    "The XPath '%s' of a field of %s does evaluate to a node of "
22932 		    "non-simple type",
22933 		    sto->sel->xpath,
22934 		    xmlSchemaGetIDCDesignation(&str, sto->matcher->aidc->def));
22935 		FREE_AND_NULL(str);
22936 		sto->nbHistory--;
22937 		goto deregister_check;
22938 	    }
22939 
22940 	    if ((key == NULL) && (vctxt->inode->val == NULL)) {
22941 		/*
22942 		* Failed to provide the normalized value; maybe
22943 		* the value was invalid.
22944 		*/
22945 		VERROR(XML_SCHEMAV_CVC_IDC,
22946 		    WXS_BASIC_CAST sto->matcher->aidc->def,
22947 		    "Warning: No precomputed value available, the value "
22948 		    "was either invalid or something strange happened");
22949 		sto->nbHistory--;
22950 		goto deregister_check;
22951 	    } else {
22952 		xmlSchemaIDCMatcherPtr matcher = sto->matcher;
22953 		xmlSchemaPSVIIDCKeyPtr *keySeq;
22954 		int pos, idx;
22955 
22956 		/*
22957 		* The key will be anchored on the matcher's list of
22958 		* key-sequences. The position in this list is determined
22959 		* by the target node's depth relative to the matcher's
22960 		* depth of creation (i.e. the depth of the scope element).
22961 		*
22962 		* Element        Depth    Pos   List-entries
22963 		* <scope>          0              NULL
22964 		*   <bar>          1              NULL
22965 		*     <target/>    2       2      target
22966 		*   <bar>
22967                 * </scope>
22968 		*
22969 		* The size of the list is only dependent on the depth of
22970 		* the tree.
22971 		* An entry will be NULLed in selector_leave, i.e. when
22972 		* we hit the target's
22973 		*/
22974 		pos = sto->depth - matcher->depth;
22975 		idx = sto->sel->index;
22976 
22977 		/*
22978 		* Create/grow the array of key-sequences.
22979 		*/
22980 		if (matcher->keySeqs == NULL) {
22981 		    if (pos > 9)
22982 			matcher->sizeKeySeqs = pos * 2;
22983 		    else
22984 			matcher->sizeKeySeqs = 10;
22985 		    matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22986 			xmlMalloc(matcher->sizeKeySeqs *
22987 			sizeof(xmlSchemaPSVIIDCKeyPtr *));
22988 		    if (matcher->keySeqs == NULL) {
22989 			xmlSchemaVErrMemory(NULL,
22990 			    "allocating an array of key-sequences",
22991 			    NULL);
22992 			return(-1);
22993 		    }
22994 		    memset(matcher->keySeqs, 0,
22995 			matcher->sizeKeySeqs *
22996 			sizeof(xmlSchemaPSVIIDCKeyPtr *));
22997 		} else if (pos >= matcher->sizeKeySeqs) {
22998 		    int i = matcher->sizeKeySeqs;
22999 
23000 		    matcher->sizeKeySeqs *= 2;
23001 		    matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
23002 			xmlRealloc(matcher->keySeqs,
23003 			matcher->sizeKeySeqs *
23004 			sizeof(xmlSchemaPSVIIDCKeyPtr *));
23005 		    if (matcher->keySeqs == NULL) {
23006 			xmlSchemaVErrMemory(NULL,
23007 			    "reallocating an array of key-sequences",
23008 			    NULL);
23009 			return (-1);
23010 		    }
23011 		    /*
23012 		    * The array needs to be NULLed.
23013 		    * TODO: Use memset?
23014 		    */
23015 		    for (; i < matcher->sizeKeySeqs; i++)
23016 			matcher->keySeqs[i] = NULL;
23017 		}
23018 
23019 		/*
23020 		* Get/create the key-sequence.
23021 		*/
23022 		keySeq = matcher->keySeqs[pos];
23023 		if (keySeq == NULL) {
23024 		    goto create_sequence;
23025 		} else if (keySeq[idx] != NULL) {
23026 		    xmlChar *str = NULL;
23027 		    /*
23028 		    * cvc-identity-constraint:
23029 		    * 3 For each node in the `target node set` all
23030 		    * of the {fields}, with that node as the context
23031 		    * node, evaluate to either an empty node-set or
23032 		    * a node-set with exactly one member, which must
23033 		    * have a simple type.
23034 		    *
23035 		    * The key was already set; report an error.
23036 		    */
23037 		    xmlSchemaCustomErr(ACTXT_CAST vctxt,
23038 			XML_SCHEMAV_CVC_IDC, NULL,
23039 			WXS_BASIC_CAST matcher->aidc->def,
23040 			"The XPath '%s' of a field of %s evaluates to a "
23041 			"node-set with more than one member",
23042 			sto->sel->xpath,
23043 			xmlSchemaGetIDCDesignation(&str, matcher->aidc->def));
23044 		    FREE_AND_NULL(str);
23045 		    sto->nbHistory--;
23046 		    goto deregister_check;
23047 		} else
23048 		    goto create_key;
23049 
23050 create_sequence:
23051 		/*
23052 		* Create a key-sequence.
23053 		*/
23054 		keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
23055 		    matcher->aidc->def->nbFields *
23056 		    sizeof(xmlSchemaPSVIIDCKeyPtr));
23057 		if (keySeq == NULL) {
23058 		    xmlSchemaVErrMemory(NULL,
23059 			"allocating an IDC key-sequence", NULL);
23060 		    return(-1);
23061 		}
23062 		memset(keySeq, 0, matcher->aidc->def->nbFields *
23063 		    sizeof(xmlSchemaPSVIIDCKeyPtr));
23064 		matcher->keySeqs[pos] = keySeq;
23065 create_key:
23066 		/*
23067 		* Create a key once per node only.
23068 		*/
23069 		if (key == NULL) {
23070 		    key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
23071 			sizeof(xmlSchemaPSVIIDCKey));
23072 		    if (key == NULL) {
23073 			xmlSchemaVErrMemory(NULL,
23074 			    "allocating a IDC key", NULL);
23075 			xmlFree(keySeq);
23076 			matcher->keySeqs[pos] = NULL;
23077 			return(-1);
23078 		    }
23079 		    /*
23080 		    * Consume the compiled value.
23081 		    */
23082 		    key->type = simpleType;
23083 		    key->val = vctxt->inode->val;
23084 		    vctxt->inode->val = NULL;
23085 		    /*
23086 		    * Store the key in a global list.
23087 		    */
23088 		    if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
23089 			xmlSchemaIDCFreeKey(key);
23090 			return (-1);
23091 		    }
23092 		}
23093 		keySeq[idx] = key;
23094 	    }
23095 	} else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
23096 
23097 	    xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
23098 	    /* xmlSchemaPSVIIDCBindingPtr bind; */
23099 	    xmlSchemaPSVIIDCNodePtr ntItem;
23100 	    xmlSchemaIDCMatcherPtr matcher;
23101 	    xmlSchemaIDCPtr idc;
23102 	    xmlSchemaItemListPtr targets;
23103 	    int pos, i, j, nbKeys;
23104 	    /*
23105 	    * Here we have the following scenario:
23106 	    * An IDC 'selector' state object resolved to a target node,
23107 	    * during the time this target node was in the
23108 	    * ancestor-or-self axis, the 'field' state object(s) looked
23109 	    * out for matching nodes to create a key-sequence for this
23110 	    * target node. Now we are back to this target node and need
23111 	    * to put the key-sequence, together with the target node
23112 	    * itself, into the node-table of the corresponding IDC
23113 	    * binding.
23114 	    */
23115 	    matcher = sto->matcher;
23116 	    idc = matcher->aidc->def;
23117 	    nbKeys = idc->nbFields;
23118 	    pos = depth - matcher->depth;
23119 	    /*
23120 	    * Check if the matcher has any key-sequences at all, plus
23121 	    * if it has a key-sequence for the current target node.
23122 	    */
23123 	    if ((matcher->keySeqs == NULL) ||
23124 		(matcher->sizeKeySeqs <= pos)) {
23125 		if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
23126 		    goto selector_key_error;
23127 		else
23128 		    goto selector_leave;
23129 	    }
23130 
23131 	    keySeq = &(matcher->keySeqs[pos]);
23132 	    if (*keySeq == NULL) {
23133 		if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
23134 		    goto selector_key_error;
23135 		else
23136 		    goto selector_leave;
23137 	    }
23138 
23139 	    for (i = 0; i < nbKeys; i++) {
23140 		if ((*keySeq)[i] == NULL) {
23141 		    /*
23142 		    * Not qualified, if not all fields did resolve.
23143 		    */
23144 		    if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
23145 			/*
23146 			* All fields of a "key" IDC must resolve.
23147 			*/
23148 			goto selector_key_error;
23149 		    }
23150 		    goto selector_leave;
23151 		}
23152 	    }
23153 	    /*
23154 	    * All fields did resolve.
23155 	    */
23156 
23157 	    /*
23158 	    * 4.1 If the {identity-constraint category} is unique(/key),
23159 	    * then no two members of the `qualified node set` have
23160 	    * `key-sequences` whose members are pairwise equal, as
23161 	    * defined by Equal in [XML Schemas: Datatypes].
23162 	    *
23163 	    * Get the IDC binding from the matcher and check for
23164 	    * duplicate key-sequences.
23165 	    */
23166 #if 0
23167 	    bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
23168 #endif
23169 	    targets = xmlSchemaIDCAcquireTargetList(vctxt, matcher);
23170 	    if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
23171 		(targets->nbItems != 0)) {
23172 		xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
23173 		xmlIDCHashEntryPtr e;
23174 
23175 		res = 0;
23176 
23177 		if (!matcher->htab)
23178 		    e = NULL;
23179 		else {
23180 		    xmlChar *value = NULL;
23181 		    xmlSchemaHashKeySequence(vctxt, &value, *keySeq, nbKeys);
23182 		    e = xmlHashLookup(matcher->htab, value);
23183 		    FREE_AND_NULL(value);
23184 		}
23185 
23186 		/*
23187 		* Compare the key-sequences, key by key.
23188 		*/
23189 		for (;e; e = e->next) {
23190 		    bkeySeq =
23191 			((xmlSchemaPSVIIDCNodePtr) targets->items[e->index])->keys;
23192 		    for (j = 0; j < nbKeys; j++) {
23193 			ckey = (*keySeq)[j];
23194 			bkey = bkeySeq[j];
23195 			res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
23196 			if (res == -1) {
23197 			    return (-1);
23198 			} else if (res == 0) {
23199 			    /*
23200 			    * One of the keys differs, so the key-sequence
23201 			    * won't be equal; get out.
23202 			    */
23203 			    break;
23204 			}
23205 		    }
23206 		    if (res == 1) {
23207 			/*
23208 			* Duplicate key-sequence found.
23209 			*/
23210 			break;
23211 		    }
23212 		}
23213 		if (e) {
23214 		    xmlChar *str = NULL, *strB = NULL;
23215 		    /*
23216 		    * TODO: Try to report the key-sequence.
23217 		    */
23218 		    xmlSchemaCustomErr(ACTXT_CAST vctxt,
23219 			XML_SCHEMAV_CVC_IDC, NULL,
23220 			WXS_BASIC_CAST idc,
23221 			"Duplicate key-sequence %s in %s",
23222 			xmlSchemaFormatIDCKeySequence(vctxt, &str,
23223 			    (*keySeq), nbKeys),
23224 			xmlSchemaGetIDCDesignation(&strB, idc));
23225 		    FREE_AND_NULL(str);
23226 		    FREE_AND_NULL(strB);
23227 		    goto selector_leave;
23228 		}
23229 	    }
23230 	    /*
23231 	    * Add a node-table item to the IDC binding.
23232 	    */
23233 	    ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
23234 		sizeof(xmlSchemaPSVIIDCNode));
23235 	    if (ntItem == NULL) {
23236 		xmlSchemaVErrMemory(NULL,
23237 		    "allocating an IDC node-table item", NULL);
23238 		xmlFree(*keySeq);
23239 		*keySeq = NULL;
23240 		return(-1);
23241 	    }
23242 	    memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
23243 
23244 	    /*
23245 	    * Store the node-table item in a global list.
23246 	    */
23247 	    if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
23248 		if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
23249 		    xmlFree(ntItem);
23250 		    xmlFree(*keySeq);
23251 		    *keySeq = NULL;
23252 		    return (-1);
23253 		}
23254 		ntItem->nodeQNameID = -1;
23255 	    } else {
23256 		/*
23257 		* Save a cached QName for this node on the IDC node, to be
23258 		* able to report it, even if the node is not saved.
23259 		*/
23260 		ntItem->nodeQNameID = xmlSchemaVAddNodeQName(vctxt,
23261 		    vctxt->inode->localName, vctxt->inode->nsName);
23262 		if (ntItem->nodeQNameID == -1) {
23263 		    xmlFree(ntItem);
23264 		    xmlFree(*keySeq);
23265 		    *keySeq = NULL;
23266 		    return (-1);
23267 		}
23268 	    }
23269 	    /*
23270 	    * Init the node-table item: Save the node, position and
23271 	    * consume the key-sequence.
23272 	    */
23273 	    ntItem->node = vctxt->node;
23274 	    ntItem->nodeLine = vctxt->inode->nodeLine;
23275 	    ntItem->keys = *keySeq;
23276 	    *keySeq = NULL;
23277 #if 0
23278 	    if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1)
23279 #endif
23280 	    if (xmlSchemaItemListAdd(targets, ntItem) == -1) {
23281 		if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23282 		    /*
23283 		    * Free the item, since keyref items won't be
23284 		    * put on a global list.
23285 		    */
23286 		    xmlFree(ntItem->keys);
23287 		    xmlFree(ntItem);
23288 		}
23289 		return (-1);
23290 	    }
23291 	    if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
23292 		xmlChar *value = NULL;
23293 		xmlIDCHashEntryPtr r, e;
23294 		if (!matcher->htab)
23295 		  matcher->htab = xmlHashCreate(4);
23296 		xmlSchemaHashKeySequence(vctxt, &value, ntItem->keys, nbKeys);
23297 		e = xmlMalloc(sizeof *e);
23298 		e->index = targets->nbItems - 1;
23299 		r = xmlHashLookup(matcher->htab, value);
23300 		if (r) {
23301 		    e->next = r->next;
23302 		    r->next = e;
23303 		} else {
23304 		    e->next = NULL;
23305 		    xmlHashAddEntry(matcher->htab, value, e);
23306 		}
23307 		FREE_AND_NULL(value);
23308 	    }
23309 
23310 	    goto selector_leave;
23311 selector_key_error:
23312 	    {
23313 		xmlChar *str = NULL;
23314 		/*
23315 		* 4.2.1 (KEY) The `target node set` and the
23316 		* `qualified node set` are equal, that is, every
23317 		* member of the `target node set` is also a member
23318 		* of the `qualified node set` and vice versa.
23319 		*/
23320 		xmlSchemaCustomErr(ACTXT_CAST vctxt,
23321 		    XML_SCHEMAV_CVC_IDC, NULL,
23322 		    WXS_BASIC_CAST idc,
23323 		    "Not all fields of %s evaluate to a node",
23324 		    xmlSchemaGetIDCDesignation(&str, idc), NULL);
23325 		FREE_AND_NULL(str);
23326 	    }
23327 selector_leave:
23328 	    /*
23329 	    * Free the key-sequence if not added to the IDC table.
23330 	    */
23331 	    if ((keySeq != NULL) && (*keySeq != NULL)) {
23332 		xmlFree(*keySeq);
23333 		*keySeq = NULL;
23334 	    }
23335 	} /* if selector */
23336 
23337 	sto->nbHistory--;
23338 
23339 deregister_check:
23340 	/*
23341 	* Deregister state objects if they reach the depth of creation.
23342 	*/
23343 	if ((sto->nbHistory == 0) && (sto->depth == depth)) {
23344 #ifdef DEBUG_IDC
23345 	    xmlGenericError(xmlGenericErrorContext, "IDC:   STO pop '%s'\n",
23346 		sto->sel->xpath);
23347 #endif
23348 	    if (vctxt->xpathStates != sto) {
23349 		VERROR_INT("xmlSchemaXPathProcessHistory",
23350 		    "The state object to be removed is not the first "
23351 		    "in the list");
23352 	    }
23353 	    nextsto = sto->next;
23354 	    /*
23355 	    * Unlink from the list of active XPath state objects.
23356 	    */
23357 	    vctxt->xpathStates = sto->next;
23358 	    sto->next = vctxt->xpathStatePool;
23359 	    /*
23360 	    * Link it to the pool of reusable state objects.
23361 	    */
23362 	    vctxt->xpathStatePool = sto;
23363 	    sto = nextsto;
23364 	} else
23365 	    sto = sto->next;
23366     } /* while (sto != NULL) */
23367     return (0);
23368 }
23369 
23370 /**
23371  * xmlSchemaIDCRegisterMatchers:
23372  * @vctxt: the WXS validation context
23373  * @elemDecl: the element declaration
23374  *
23375  * Creates helper objects to evaluate IDC selectors/fields
23376  * successively.
23377  *
23378  * Returns 0 if OK and -1 on internal errors.
23379  */
23380 static int
xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,xmlSchemaElementPtr elemDecl)23381 xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
23382 			     xmlSchemaElementPtr elemDecl)
23383 {
23384     xmlSchemaIDCMatcherPtr matcher, last = NULL;
23385     xmlSchemaIDCPtr idc, refIdc;
23386     xmlSchemaIDCAugPtr aidc;
23387 
23388     idc = (xmlSchemaIDCPtr) elemDecl->idcs;
23389     if (idc == NULL)
23390 	return (0);
23391 
23392 #ifdef DEBUG_IDC
23393     {
23394 	xmlChar *str = NULL;
23395 	xmlGenericError(xmlGenericErrorContext,
23396 	    "IDC: REGISTER on %s, depth %d\n",
23397 	    (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
23398 		vctxt->inode->localName), vctxt->depth);
23399 	FREE_AND_NULL(str)
23400     }
23401 #endif
23402     if (vctxt->inode->idcMatchers != NULL) {
23403 	VERROR_INT("xmlSchemaIDCRegisterMatchers",
23404 	    "The chain of IDC matchers is expected to be empty");
23405 	return (-1);
23406     }
23407     do {
23408 	if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23409 	    /*
23410 	    * Since IDCs bubbles are expensive we need to know the
23411 	    * depth at which the bubbles should stop; this will be
23412 	    * the depth of the top-most keyref IDC. If no keyref
23413 	    * references a key/unique IDC, the keyrefDepth will
23414 	    * be -1, indicating that no bubbles are needed.
23415 	    */
23416 	    refIdc = (xmlSchemaIDCPtr) idc->ref->item;
23417 	    if (refIdc != NULL) {
23418 		/*
23419 		* Remember that we have keyrefs on this node.
23420 		*/
23421 		vctxt->inode->hasKeyrefs = 1;
23422 		/*
23423 		* Lookup the referenced augmented IDC info.
23424 		*/
23425 		aidc = vctxt->aidcs;
23426 		while (aidc != NULL) {
23427 		    if (aidc->def == refIdc)
23428 			break;
23429 		    aidc = aidc->next;
23430 		}
23431 		if (aidc == NULL) {
23432 		    VERROR_INT("xmlSchemaIDCRegisterMatchers",
23433 			"Could not find an augmented IDC item for an IDC "
23434 			"definition");
23435 		    return (-1);
23436 		}
23437 		if ((aidc->keyrefDepth == -1) ||
23438 		    (vctxt->depth < aidc->keyrefDepth))
23439 		    aidc->keyrefDepth = vctxt->depth;
23440 	    }
23441 	}
23442 	/*
23443 	* Lookup the augmented IDC item for the IDC definition.
23444 	*/
23445 	aidc = vctxt->aidcs;
23446 	while (aidc != NULL) {
23447 	    if (aidc->def == idc)
23448 		break;
23449 	    aidc = aidc->next;
23450 	}
23451 	if (aidc == NULL) {
23452 	    VERROR_INT("xmlSchemaIDCRegisterMatchers",
23453 		"Could not find an augmented IDC item for an IDC definition");
23454 	    return (-1);
23455 	}
23456 	/*
23457 	* Create an IDC matcher for every IDC definition.
23458 	*/
23459 	if (vctxt->idcMatcherCache != NULL) {
23460 	    /*
23461 	    * Reuse a cached matcher.
23462 	    */
23463 	    matcher = vctxt->idcMatcherCache;
23464 	    vctxt->idcMatcherCache = matcher->nextCached;
23465 	    matcher->nextCached = NULL;
23466 	} else {
23467 	    matcher = (xmlSchemaIDCMatcherPtr)
23468 		xmlMalloc(sizeof(xmlSchemaIDCMatcher));
23469 	    if (matcher == NULL) {
23470 		xmlSchemaVErrMemory(vctxt,
23471 		    "allocating an IDC matcher", NULL);
23472 		return (-1);
23473 	    }
23474 	    memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
23475 	}
23476 	if (last == NULL)
23477 	    vctxt->inode->idcMatchers = matcher;
23478 	else
23479 	    last->next = matcher;
23480 	last = matcher;
23481 
23482 	matcher->type = IDC_MATCHER;
23483 	matcher->depth = vctxt->depth;
23484 	matcher->aidc = aidc;
23485 	matcher->idcType = aidc->def->type;
23486 #ifdef DEBUG_IDC
23487 	xmlGenericError(xmlGenericErrorContext, "IDC:   register matcher\n");
23488 #endif
23489 	/*
23490 	* Init the automaton state object.
23491 	*/
23492 	if (xmlSchemaIDCAddStateObject(vctxt, matcher,
23493 	    idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
23494 	    return (-1);
23495 
23496 	idc = idc->next;
23497     } while (idc != NULL);
23498     return (0);
23499 }
23500 
23501 static int
xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,xmlSchemaNodeInfoPtr ielem)23502 xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,
23503 			   xmlSchemaNodeInfoPtr ielem)
23504 {
23505     xmlSchemaPSVIIDCBindingPtr bind;
23506     int res, i, j, k, nbTargets, nbFields, nbDupls, nbNodeTable;
23507     xmlSchemaPSVIIDCKeyPtr *keys, *ntkeys;
23508     xmlSchemaPSVIIDCNodePtr *targets, *dupls;
23509 
23510     xmlSchemaIDCMatcherPtr matcher = ielem->idcMatchers;
23511     /* vctxt->createIDCNodeTables */
23512     while (matcher != NULL) {
23513 	/*
23514 	* Skip keyref IDCs and empty IDC target-lists.
23515 	*/
23516 	if ((matcher->aidc->def->type == XML_SCHEMA_TYPE_IDC_KEYREF) ||
23517 	    WXS_ILIST_IS_EMPTY(matcher->targets))
23518 	{
23519 	    matcher = matcher->next;
23520 	    continue;
23521 	}
23522 	/*
23523 	* If we _want_ the IDC node-table to be created in any case
23524 	* then do so. Otherwise create them only if keyrefs need them.
23525 	*/
23526 	if ((! vctxt->createIDCNodeTables) &&
23527 	    ((matcher->aidc->keyrefDepth == -1) ||
23528 	     (matcher->aidc->keyrefDepth > vctxt->depth)))
23529 	{
23530 	    matcher = matcher->next;
23531 	    continue;
23532 	}
23533 	/*
23534 	* Get/create the IDC binding on this element for the IDC definition.
23535 	*/
23536 	bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
23537 	if (bind == NULL)
23538 	   goto internal_error;
23539 
23540 	if (! WXS_ILIST_IS_EMPTY(bind->dupls)) {
23541 	    dupls = (xmlSchemaPSVIIDCNodePtr *) bind->dupls->items;
23542 	    nbDupls = bind->dupls->nbItems;
23543 	} else {
23544 	    dupls = NULL;
23545 	    nbDupls = 0;
23546 	}
23547 	if (bind->nodeTable != NULL) {
23548 	    nbNodeTable = bind->nbNodes;
23549 	} else {
23550 	    nbNodeTable = 0;
23551 	}
23552 
23553 	if ((nbNodeTable == 0) && (nbDupls == 0)) {
23554 	    /*
23555 	    * Transfer all IDC target-nodes to the IDC node-table.
23556 	    */
23557 	    bind->nodeTable =
23558 		(xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23559 	    bind->sizeNodes = matcher->targets->sizeItems;
23560 	    bind->nbNodes = matcher->targets->nbItems;
23561 
23562 	    matcher->targets->items = NULL;
23563 	    matcher->targets->sizeItems = 0;
23564 	    matcher->targets->nbItems = 0;
23565 	    if (matcher->htab) {
23566 		xmlHashFree(matcher->htab, xmlFreeIDCHashEntry);
23567 		matcher->htab = NULL;
23568 	    }
23569 	} else {
23570 	    /*
23571 	    * Compare the key-sequences and add to the IDC node-table.
23572 	    */
23573 	    nbTargets = matcher->targets->nbItems;
23574 	    targets = (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23575 	    nbFields = matcher->aidc->def->nbFields;
23576 	    i = 0;
23577 	    do {
23578 		keys = targets[i]->keys;
23579 		if (nbDupls) {
23580 		    /*
23581 		    * Search in already found duplicates first.
23582 		    */
23583 		    j = 0;
23584 		    do {
23585 			if (nbFields == 1) {
23586 			    res = xmlSchemaAreValuesEqual(keys[0]->val,
23587 				dupls[j]->keys[0]->val);
23588 			    if (res == -1)
23589 				goto internal_error;
23590 			    if (res == 1) {
23591 				/*
23592 				* Equal key-sequence.
23593 				*/
23594 				goto next_target;
23595 			    }
23596 			} else {
23597 			    res = 0;
23598 			    ntkeys = dupls[j]->keys;
23599 			    for (k = 0; k < nbFields; k++) {
23600 				res = xmlSchemaAreValuesEqual(keys[k]->val,
23601 				    ntkeys[k]->val);
23602 				if (res == -1)
23603 				    goto internal_error;
23604 				if (res == 0) {
23605 				    /*
23606 				    * One of the keys differs.
23607 				    */
23608 				    break;
23609 				}
23610 			    }
23611 			    if (res == 1) {
23612 				/*
23613 				* Equal key-sequence found.
23614 				*/
23615 				goto next_target;
23616 			    }
23617 			}
23618 			j++;
23619 		    } while (j < nbDupls);
23620 		}
23621 		if (nbNodeTable) {
23622 		    j = 0;
23623 		    do {
23624 			if (nbFields == 1) {
23625 			    res = xmlSchemaAreValuesEqual(keys[0]->val,
23626 				bind->nodeTable[j]->keys[0]->val);
23627 			    if (res == -1)
23628 				goto internal_error;
23629 			    if (res == 0) {
23630 				/*
23631 				* The key-sequence differs.
23632 				*/
23633 				goto next_node_table_entry;
23634 			    }
23635 			} else {
23636 			    res = 0;
23637 			    ntkeys = bind->nodeTable[j]->keys;
23638 			    for (k = 0; k < nbFields; k++) {
23639 				res = xmlSchemaAreValuesEqual(keys[k]->val,
23640 				    ntkeys[k]->val);
23641 				if (res == -1)
23642 				    goto internal_error;
23643 				if (res == 0) {
23644 				    /*
23645 				    * One of the keys differs.
23646 				    */
23647 				    goto next_node_table_entry;
23648 				}
23649 			    }
23650 			}
23651 			/*
23652 			* Add the duplicate to the list of duplicates.
23653 			*/
23654 			if (bind->dupls == NULL) {
23655 			    bind->dupls = xmlSchemaItemListCreate();
23656 			    if (bind->dupls == NULL)
23657 				goto internal_error;
23658 			}
23659 			if (xmlSchemaItemListAdd(bind->dupls, bind->nodeTable[j]) == -1)
23660 			    goto internal_error;
23661 			/*
23662 			* Remove the duplicate entry from the IDC node-table.
23663 			*/
23664 			bind->nodeTable[j] = bind->nodeTable[bind->nbNodes -1];
23665 			bind->nbNodes--;
23666 
23667 			goto next_target;
23668 
23669 next_node_table_entry:
23670 			j++;
23671 		    } while (j < nbNodeTable);
23672 		}
23673 		/*
23674 		* If everything is fine, then add the IDC target-node to
23675 		* the IDC node-table.
23676 		*/
23677 		if (xmlSchemaIDCAppendNodeTableItem(bind, targets[i]) == -1)
23678 		    goto internal_error;
23679 
23680 next_target:
23681 		i++;
23682 	    } while (i < nbTargets);
23683 	}
23684 	matcher = matcher->next;
23685     }
23686     return(0);
23687 
23688 internal_error:
23689     return(-1);
23690 }
23691 
23692 /**
23693  * xmlSchemaBubbleIDCNodeTables:
23694  * @depth: the current tree depth
23695  *
23696  * Merges IDC bindings of an element at @depth into the corresponding IDC
23697  * bindings of its parent element. If a duplicate note-table entry is found,
23698  * both, the parent node-table entry and child entry are discarded from the
23699  * node-table of the parent.
23700  *
23701  * Returns 0 if OK and -1 on internal errors.
23702  */
23703 static int
xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)23704 xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
23705 {
23706     xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
23707     xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL; /* parent IDC bindings. */
23708     xmlSchemaPSVIIDCNodePtr node, parNode = NULL, *dupls, *parNodes; /* node-table entries. */
23709     xmlSchemaIDCAugPtr aidc;
23710     int i, j, k, ret = 0, nbFields, oldNum, oldDupls;
23711 
23712     bind = vctxt->inode->idcTable;
23713     if (bind == NULL) {
23714 	/* Fine, no table, no bubbles. */
23715 	return (0);
23716     }
23717 
23718     parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
23719     /*
23720     * Walk all bindings; create new or add to existing bindings.
23721     * Remove duplicate key-sequences.
23722     */
23723     while (bind != NULL) {
23724 
23725 	if ((bind->nbNodes == 0) && WXS_ILIST_IS_EMPTY(bind->dupls))
23726 	    goto next_binding;
23727 	/*
23728 	* Check if the key/unique IDC table needs to be bubbled.
23729 	*/
23730 	if (! vctxt->createIDCNodeTables) {
23731 	    aidc = vctxt->aidcs;
23732 	    do {
23733 		if (aidc->def == bind->definition) {
23734 		    if ((aidc->keyrefDepth == -1) ||
23735 			(aidc->keyrefDepth >= vctxt->depth)) {
23736 			goto next_binding;
23737 		    }
23738 		    break;
23739 		}
23740 		aidc = aidc->next;
23741 	    } while (aidc != NULL);
23742 	}
23743 
23744 	if (parTable != NULL)
23745 	    parBind = *parTable;
23746 	/*
23747 	* Search a matching parent binding for the
23748 	* IDC definition.
23749 	*/
23750 	while (parBind != NULL) {
23751 	    if (parBind->definition == bind->definition)
23752 		break;
23753 	    parBind = parBind->next;
23754 	}
23755 
23756 	if (parBind != NULL) {
23757 	    /*
23758 	    * Compare every node-table entry of the child node,
23759 	    * i.e. the key-sequence within, ...
23760 	    */
23761 	    oldNum = parBind->nbNodes; /* Skip newly added items. */
23762 
23763 	    if (! WXS_ILIST_IS_EMPTY(parBind->dupls)) {
23764 		oldDupls = parBind->dupls->nbItems;
23765 		dupls = (xmlSchemaPSVIIDCNodePtr *) parBind->dupls->items;
23766 	    } else {
23767 		dupls = NULL;
23768 		oldDupls = 0;
23769 	    }
23770 
23771 	    parNodes = parBind->nodeTable;
23772 	    nbFields = bind->definition->nbFields;
23773 
23774 	    for (i = 0; i < bind->nbNodes; i++) {
23775 		node = bind->nodeTable[i];
23776 		if (node == NULL)
23777 		    continue;
23778 		/*
23779 		* ...with every key-sequence of the parent node, already
23780 		* evaluated to be a duplicate key-sequence.
23781 		*/
23782 		if (oldDupls) {
23783 		    j = 0;
23784 		    while (j < oldDupls) {
23785 			if (nbFields == 1) {
23786 			    ret = xmlSchemaAreValuesEqual(
23787 				node->keys[0]->val,
23788 				dupls[j]->keys[0]->val);
23789 			    if (ret == -1)
23790 				goto internal_error;
23791 			    if (ret == 0) {
23792 				j++;
23793 				continue;
23794 			    }
23795 			} else {
23796 			    parNode = dupls[j];
23797 			    for (k = 0; k < nbFields; k++) {
23798 				ret = xmlSchemaAreValuesEqual(
23799 				    node->keys[k]->val,
23800 				    parNode->keys[k]->val);
23801 				if (ret == -1)
23802 				    goto internal_error;
23803 				if (ret == 0)
23804 				    break;
23805 			    }
23806 			}
23807 			if (ret == 1)
23808 			    /* Duplicate found. */
23809 			    break;
23810 			j++;
23811 		    }
23812 		    if (j != oldDupls) {
23813 			/* Duplicate found. Skip this entry. */
23814 			continue;
23815 		    }
23816 		}
23817 		/*
23818 		* ... and with every key-sequence of the parent node.
23819 		*/
23820 		if (oldNum) {
23821 		    j = 0;
23822 		    while (j < oldNum) {
23823 			parNode = parNodes[j];
23824 			if (nbFields == 1) {
23825 			    ret = xmlSchemaAreValuesEqual(
23826 				node->keys[0]->val,
23827 				parNode->keys[0]->val);
23828 			    if (ret == -1)
23829 				goto internal_error;
23830 			    if (ret == 0) {
23831 				j++;
23832 				continue;
23833 			    }
23834 			} else {
23835 			    for (k = 0; k < nbFields; k++) {
23836 				ret = xmlSchemaAreValuesEqual(
23837 				    node->keys[k]->val,
23838 				    parNode->keys[k]->val);
23839 				if (ret == -1)
23840 				    goto internal_error;
23841 				if (ret == 0)
23842 				    break;
23843 			    }
23844 			}
23845 			if (ret == 1)
23846 			    /* Duplicate found. */
23847 			    break;
23848 			j++;
23849 		    }
23850 		    if (j != oldNum) {
23851 			/*
23852 			* Handle duplicates. Move the duplicate in
23853 			* the parent's node-table to the list of
23854 			* duplicates.
23855 			*/
23856 			oldNum--;
23857 			parBind->nbNodes--;
23858 			/*
23859 			* Move last old item to pos of duplicate.
23860 			*/
23861 			parNodes[j] = parNodes[oldNum];
23862 
23863 			if (parBind->nbNodes != oldNum) {
23864 			    /*
23865 			    * If new items exist, move last new item to
23866 			    * last of old items.
23867 			    */
23868 			    parNodes[oldNum] =
23869 				parNodes[parBind->nbNodes];
23870 			}
23871 			if (parBind->dupls == NULL) {
23872 			    parBind->dupls = xmlSchemaItemListCreate();
23873 			    if (parBind->dupls == NULL)
23874 				goto internal_error;
23875 			}
23876 			xmlSchemaItemListAdd(parBind->dupls, parNode);
23877 		    } else {
23878 			/*
23879 			* Add the node-table entry (node and key-sequence) of
23880 			* the child node to the node table of the parent node.
23881 			*/
23882 			if (parBind->nodeTable == NULL) {
23883 			    parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23884 				xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
23885 			    if (parBind->nodeTable == NULL) {
23886 				xmlSchemaVErrMemory(NULL,
23887 				    "allocating IDC list of node-table items", NULL);
23888 				goto internal_error;
23889 			    }
23890 			    parBind->sizeNodes = 1;
23891 			} else if (parBind->nbNodes >= parBind->sizeNodes) {
23892 			    parBind->sizeNodes *= 2;
23893 			    parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23894 				xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
23895 				sizeof(xmlSchemaPSVIIDCNodePtr));
23896 			    if (parBind->nodeTable == NULL) {
23897 				xmlSchemaVErrMemory(NULL,
23898 				    "re-allocating IDC list of node-table items", NULL);
23899 				goto internal_error;
23900 			    }
23901 			}
23902 			parNodes = parBind->nodeTable;
23903 			/*
23904 			* Append the new node-table entry to the 'new node-table
23905 			* entries' section.
23906 			*/
23907 			parNodes[parBind->nbNodes++] = node;
23908 		    }
23909 
23910 		}
23911 
23912 	    }
23913 	} else {
23914 	    /*
23915 	    * No binding for the IDC was found: create a new one and
23916 	    * copy all node-tables.
23917 	    */
23918 	    parBind = xmlSchemaIDCNewBinding(bind->definition);
23919 	    if (parBind == NULL)
23920 		goto internal_error;
23921 
23922 	    /*
23923 	    * TODO: Hmm, how to optimize the initial number of
23924 	    * allocated entries?
23925 	    */
23926 	    if (bind->nbNodes != 0) {
23927 		/*
23928 		* Add all IDC node-table entries.
23929 		*/
23930 		if (! vctxt->psviExposeIDCNodeTables) {
23931 		    /*
23932 		    * Just move the entries.
23933 		    * NOTE: this is quite save here, since
23934 		    * all the keyref lookups have already been
23935 		    * performed.
23936 		    */
23937 		    parBind->nodeTable = bind->nodeTable;
23938 		    bind->nodeTable = NULL;
23939 		    parBind->sizeNodes = bind->sizeNodes;
23940 		    bind->sizeNodes = 0;
23941 		    parBind->nbNodes = bind->nbNodes;
23942 		    bind->nbNodes = 0;
23943 		} else {
23944 		    /*
23945 		    * Copy the entries.
23946 		    */
23947 		    parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23948 			xmlMalloc(bind->nbNodes *
23949 			sizeof(xmlSchemaPSVIIDCNodePtr));
23950 		    if (parBind->nodeTable == NULL) {
23951 			xmlSchemaVErrMemory(NULL,
23952 			    "allocating an array of IDC node-table "
23953 			    "items", NULL);
23954 			xmlSchemaIDCFreeBinding(parBind);
23955 			goto internal_error;
23956 		    }
23957 		    parBind->sizeNodes = bind->nbNodes;
23958 		    parBind->nbNodes = bind->nbNodes;
23959 		    memcpy(parBind->nodeTable, bind->nodeTable,
23960 			bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
23961 		}
23962 	    }
23963 	    if (bind->dupls) {
23964 		/*
23965 		* Move the duplicates.
23966 		*/
23967 		if (parBind->dupls != NULL)
23968 		    xmlSchemaItemListFree(parBind->dupls);
23969 		parBind->dupls = bind->dupls;
23970 		bind->dupls = NULL;
23971 	    }
23972             if (parTable != NULL) {
23973                 if (*parTable == NULL)
23974                     *parTable = parBind;
23975                 else {
23976                     parBind->next = *parTable;
23977                     *parTable = parBind;
23978                 }
23979             }
23980 	}
23981 
23982 next_binding:
23983 	bind = bind->next;
23984     }
23985     return (0);
23986 
23987 internal_error:
23988     return(-1);
23989 }
23990 
23991 /**
23992  * xmlSchemaCheckCVCIDCKeyRef:
23993  * @vctxt: the WXS validation context
23994  * @elemDecl: the element declaration
23995  *
23996  * Check the cvc-idc-keyref constraints.
23997  */
23998 static int
xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)23999 xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
24000 {
24001     xmlSchemaIDCMatcherPtr matcher;
24002     xmlSchemaPSVIIDCBindingPtr bind;
24003 
24004     matcher = vctxt->inode->idcMatchers;
24005     /*
24006     * Find a keyref.
24007     */
24008     while (matcher != NULL) {
24009 	if ((matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) &&
24010 	    matcher->targets &&
24011 	    matcher->targets->nbItems)
24012 	{
24013 	    int i, j, k, res, nbFields, hasDupls;
24014 	    xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
24015 	    xmlSchemaPSVIIDCNodePtr refNode = NULL;
24016 	    xmlHashTablePtr table = NULL;
24017 
24018 	    nbFields = matcher->aidc->def->nbFields;
24019 
24020 	    /*
24021 	    * Find the IDC node-table for the referenced IDC key/unique.
24022 	    */
24023 	    bind = vctxt->inode->idcTable;
24024 	    while (bind != NULL) {
24025 		if ((xmlSchemaIDCPtr) matcher->aidc->def->ref->item ==
24026 		    bind->definition)
24027 		    break;
24028 		bind = bind->next;
24029 	    }
24030 	    hasDupls = (bind && bind->dupls && bind->dupls->nbItems) ? 1 : 0;
24031 	    /*
24032 	    * Search for a matching key-sequences.
24033 	    */
24034 	    if (bind) {
24035 		table = xmlHashCreate(bind->nbNodes * 2);
24036 		for (j = 0; j < bind->nbNodes; j++) {
24037 		    xmlChar *value;
24038 		    xmlIDCHashEntryPtr r, e;
24039 		    keys = bind->nodeTable[j]->keys;
24040 		    xmlSchemaHashKeySequence(vctxt, &value, keys, nbFields);
24041 		    e = xmlMalloc(sizeof *e);
24042 		    e->index = j;
24043 		    r = xmlHashLookup(table, value);
24044 		    if (r) {
24045 			e->next = r->next;
24046 			r->next = e;
24047 		    } else {
24048 			e->next = NULL;
24049 			xmlHashAddEntry(table, value, e);
24050 		    }
24051 		    FREE_AND_NULL(value);
24052 		}
24053 	    }
24054 	    for (i = 0; i < matcher->targets->nbItems; i++) {
24055 		res = 0;
24056 		refNode = matcher->targets->items[i];
24057 		if (bind != NULL) {
24058 		    xmlChar *value;
24059 		    xmlIDCHashEntryPtr e;
24060 		    refKeys = refNode->keys;
24061 		    xmlSchemaHashKeySequence(vctxt, &value, refKeys, nbFields);
24062 		    e = xmlHashLookup(table, value);
24063 		    FREE_AND_NULL(value);
24064 		    res = 0;
24065 		    for (;e; e = e->next) {
24066 			keys = bind->nodeTable[e->index]->keys;
24067 			for (k = 0; k < nbFields; k++) {
24068 			    res = xmlSchemaAreValuesEqual(keys[k]->val,
24069 							  refKeys[k]->val);
24070 			    if (res == 0)
24071 			        break;
24072 			    else if (res == -1) {
24073 				return (-1);
24074 			    }
24075 			}
24076 			if (res == 1) {
24077 			    /*
24078 			     * Match found.
24079 			     */
24080 			    break;
24081 			}
24082 		    }
24083 		    if ((res == 0) && hasDupls) {
24084 			/*
24085 			* Search in duplicates
24086 			*/
24087 			for (j = 0; j < bind->dupls->nbItems; j++) {
24088 			    keys = ((xmlSchemaPSVIIDCNodePtr)
24089 				bind->dupls->items[j])->keys;
24090 			    for (k = 0; k < nbFields; k++) {
24091 				res = xmlSchemaAreValuesEqual(keys[k]->val,
24092 				    refKeys[k]->val);
24093 				if (res == 0)
24094 				    break;
24095 				else if (res == -1) {
24096 				    return (-1);
24097 				}
24098 			    }
24099 			    if (res == 1) {
24100 				/*
24101 				* Match in duplicates found.
24102 				*/
24103 				xmlChar *str = NULL, *strB = NULL;
24104 				xmlSchemaKeyrefErr(vctxt,
24105 				    XML_SCHEMAV_CVC_IDC, refNode,
24106 				    (xmlSchemaTypePtr) matcher->aidc->def,
24107 				    "More than one match found for "
24108 				    "key-sequence %s of keyref '%s'",
24109 				    xmlSchemaFormatIDCKeySequence(vctxt, &str,
24110 					refNode->keys, nbFields),
24111 				    xmlSchemaGetComponentQName(&strB,
24112 					matcher->aidc->def));
24113 				FREE_AND_NULL(str);
24114 				FREE_AND_NULL(strB);
24115 				break;
24116 			    }
24117 			}
24118 		    }
24119 		}
24120 
24121 		if (res == 0) {
24122 		    xmlChar *str = NULL, *strB = NULL;
24123 		    xmlSchemaKeyrefErr(vctxt,
24124 			XML_SCHEMAV_CVC_IDC, refNode,
24125 			(xmlSchemaTypePtr) matcher->aidc->def,
24126 			"No match found for key-sequence %s of keyref '%s'",
24127 			xmlSchemaFormatIDCKeySequence(vctxt, &str,
24128 			    refNode->keys, nbFields),
24129 			xmlSchemaGetComponentQName(&strB, matcher->aidc->def));
24130 		    FREE_AND_NULL(str);
24131 		    FREE_AND_NULL(strB);
24132 		}
24133 	    }
24134 	    if (table) {
24135 		xmlHashFree(table, xmlFreeIDCHashEntry);
24136 	    }
24137 	}
24138 	matcher = matcher->next;
24139     }
24140     /* TODO: Return an error if any error encountered. */
24141     return (0);
24142 }
24143 
24144 /************************************************************************
24145  *									*
24146  *			XML Reader validation code                      *
24147  *									*
24148  ************************************************************************/
24149 
24150 static xmlSchemaAttrInfoPtr
xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)24151 xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
24152 {
24153     xmlSchemaAttrInfoPtr iattr;
24154     /*
24155     * Grow/create list of attribute infos.
24156     */
24157     if (vctxt->attrInfos == NULL) {
24158 	vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
24159 	    xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
24160 	vctxt->sizeAttrInfos = 1;
24161 	if (vctxt->attrInfos == NULL) {
24162 	    xmlSchemaVErrMemory(vctxt,
24163 		"allocating attribute info list", NULL);
24164 	    return (NULL);
24165 	}
24166     } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
24167 	vctxt->sizeAttrInfos++;
24168 	vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
24169 	    xmlRealloc(vctxt->attrInfos,
24170 		vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
24171 	if (vctxt->attrInfos == NULL) {
24172 	    xmlSchemaVErrMemory(vctxt,
24173 		"re-allocating attribute info list", NULL);
24174 	    return (NULL);
24175 	}
24176     } else {
24177 	iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
24178 	if (iattr->localName != NULL) {
24179 	    VERROR_INT("xmlSchemaGetFreshAttrInfo",
24180 		"attr info not cleared");
24181 	    return (NULL);
24182 	}
24183 	iattr->nodeType = XML_ATTRIBUTE_NODE;
24184 	return (iattr);
24185     }
24186     /*
24187     * Create an attribute info.
24188     */
24189     iattr = (xmlSchemaAttrInfoPtr)
24190 	xmlMalloc(sizeof(xmlSchemaAttrInfo));
24191     if (iattr == NULL) {
24192 	xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
24193 	return (NULL);
24194     }
24195     memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
24196     iattr->nodeType = XML_ATTRIBUTE_NODE;
24197     vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
24198 
24199     return (iattr);
24200 }
24201 
24202 static int
xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,xmlNodePtr attrNode,int nodeLine,const xmlChar * localName,const xmlChar * nsName,int ownedNames,xmlChar * value,int ownedValue)24203 xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
24204 			xmlNodePtr attrNode,
24205 			int nodeLine,
24206 			const xmlChar *localName,
24207 			const xmlChar *nsName,
24208 			int ownedNames,
24209 			xmlChar *value,
24210 			int ownedValue)
24211 {
24212     xmlSchemaAttrInfoPtr attr;
24213 
24214     attr = xmlSchemaGetFreshAttrInfo(vctxt);
24215     if (attr == NULL) {
24216 	VERROR_INT("xmlSchemaPushAttribute",
24217 	    "calling xmlSchemaGetFreshAttrInfo()");
24218 	return (-1);
24219     }
24220     attr->node = attrNode;
24221     attr->nodeLine = nodeLine;
24222     attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
24223     attr->localName = localName;
24224     attr->nsName = nsName;
24225     if (ownedNames)
24226 	attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
24227     /*
24228     * Evaluate if it's an XSI attribute.
24229     */
24230     if (nsName != NULL) {
24231 	if (xmlStrEqual(localName, BAD_CAST "nil")) {
24232 	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
24233 		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
24234 	    }
24235 	} else if (xmlStrEqual(localName, BAD_CAST "type")) {
24236 	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
24237 		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
24238 	    }
24239 	} else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
24240 	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
24241 		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
24242 	    }
24243 	} else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
24244 	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
24245 		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
24246 	    }
24247 	} else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
24248 	    attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
24249 	}
24250     }
24251     attr->value = value;
24252     if (ownedValue)
24253 	attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
24254     if (attr->metaType != 0)
24255 	attr->state = XML_SCHEMAS_ATTR_META;
24256     return (0);
24257 }
24258 
24259 /**
24260  * xmlSchemaClearElemInfo:
24261  * @vctxt: the WXS validation context
24262  * @ielem: the element information item
24263  */
24264 static void
xmlSchemaClearElemInfo(xmlSchemaValidCtxtPtr vctxt,xmlSchemaNodeInfoPtr ielem)24265 xmlSchemaClearElemInfo(xmlSchemaValidCtxtPtr vctxt,
24266 		       xmlSchemaNodeInfoPtr ielem)
24267 {
24268     ielem->hasKeyrefs = 0;
24269     ielem->appliedXPath = 0;
24270     if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
24271 	FREE_AND_NULL(ielem->localName);
24272 	FREE_AND_NULL(ielem->nsName);
24273     } else {
24274 	ielem->localName = NULL;
24275 	ielem->nsName = NULL;
24276     }
24277     if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
24278 	FREE_AND_NULL(ielem->value);
24279     } else {
24280 	ielem->value = NULL;
24281     }
24282     if (ielem->val != NULL) {
24283 	/*
24284 	* PSVI TODO: Be careful not to free it when the value is
24285 	* exposed via PSVI.
24286 	*/
24287 	xmlSchemaFreeValue(ielem->val);
24288 	ielem->val = NULL;
24289     }
24290     if (ielem->idcMatchers != NULL) {
24291 	/*
24292 	* REVISIT OPTIMIZE TODO: Use a pool of IDC matchers.
24293 	*   Does it work?
24294 	*/
24295 	xmlSchemaIDCReleaseMatcherList(vctxt, ielem->idcMatchers);
24296 #if 0
24297 	xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
24298 #endif
24299 	ielem->idcMatchers = NULL;
24300     }
24301     if (ielem->idcTable != NULL) {
24302 	/*
24303 	* OPTIMIZE TODO: Use a pool of IDC tables??.
24304 	*/
24305 	xmlSchemaIDCFreeIDCTable(ielem->idcTable);
24306 	ielem->idcTable = NULL;
24307     }
24308     if (ielem->regexCtxt != NULL) {
24309 	xmlRegFreeExecCtxt(ielem->regexCtxt);
24310 	ielem->regexCtxt = NULL;
24311     }
24312     if (ielem->nsBindings != NULL) {
24313 	xmlFree((xmlChar **)ielem->nsBindings);
24314 	ielem->nsBindings = NULL;
24315 	ielem->nbNsBindings = 0;
24316 	ielem->sizeNsBindings = 0;
24317     }
24318 }
24319 
24320 /**
24321  * xmlSchemaGetFreshElemInfo:
24322  * @vctxt: the schema validation context
24323  *
24324  * Creates/reuses and initializes the element info item for
24325  * the current tree depth.
24326  *
24327  * Returns the element info item or NULL on API or internal errors.
24328  */
24329 static xmlSchemaNodeInfoPtr
xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)24330 xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
24331 {
24332     xmlSchemaNodeInfoPtr info = NULL;
24333 
24334     if (vctxt->depth > vctxt->sizeElemInfos) {
24335 	VERROR_INT("xmlSchemaGetFreshElemInfo",
24336 	    "inconsistent depth encountered");
24337 	return (NULL);
24338     }
24339     if (vctxt->elemInfos == NULL) {
24340 	vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24341 	    xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
24342 	if (vctxt->elemInfos == NULL) {
24343 	    xmlSchemaVErrMemory(vctxt,
24344 		"allocating the element info array", NULL);
24345 	    return (NULL);
24346 	}
24347 	memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
24348 	vctxt->sizeElemInfos = 10;
24349     } else if (vctxt->sizeElemInfos <= vctxt->depth) {
24350 	int i = vctxt->sizeElemInfos;
24351 
24352 	vctxt->sizeElemInfos *= 2;
24353 	vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24354 	    xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
24355 	    sizeof(xmlSchemaNodeInfoPtr));
24356 	if (vctxt->elemInfos == NULL) {
24357 	    xmlSchemaVErrMemory(vctxt,
24358 		"re-allocating the element info array", NULL);
24359 	    return (NULL);
24360 	}
24361 	/*
24362 	* We need the new memory to be NULLed.
24363 	* TODO: Use memset instead?
24364 	*/
24365 	for (; i < vctxt->sizeElemInfos; i++)
24366 	    vctxt->elemInfos[i] = NULL;
24367     } else
24368 	info = vctxt->elemInfos[vctxt->depth];
24369 
24370     if (info == NULL) {
24371 	info = (xmlSchemaNodeInfoPtr)
24372 	    xmlMalloc(sizeof(xmlSchemaNodeInfo));
24373 	if (info == NULL) {
24374 	    xmlSchemaVErrMemory(vctxt,
24375 		"allocating an element info", NULL);
24376 	    return (NULL);
24377 	}
24378 	vctxt->elemInfos[vctxt->depth] = info;
24379     } else {
24380 	if (info->localName != NULL) {
24381 	    VERROR_INT("xmlSchemaGetFreshElemInfo",
24382 		"elem info has not been cleared");
24383 	    return (NULL);
24384 	}
24385     }
24386     memset(info, 0, sizeof(xmlSchemaNodeInfo));
24387     info->nodeType = XML_ELEMENT_NODE;
24388     info->depth = vctxt->depth;
24389 
24390     return (info);
24391 }
24392 
24393 #define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
24394 #define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
24395 #define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
24396 
24397 static int
xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,xmlNodePtr node,xmlSchemaTypePtr type,xmlSchemaValType valType,const xmlChar * value,xmlSchemaValPtr val,unsigned long length,int fireErrors)24398 xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
24399 			xmlNodePtr node,
24400 			xmlSchemaTypePtr type,
24401 			xmlSchemaValType valType,
24402 			const xmlChar * value,
24403 			xmlSchemaValPtr val,
24404 			unsigned long length,
24405 			int fireErrors)
24406 {
24407     int ret, error = 0, found;
24408 
24409     xmlSchemaTypePtr tmpType;
24410     xmlSchemaFacetLinkPtr facetLink;
24411     xmlSchemaFacetPtr facet;
24412     unsigned long len = 0;
24413     xmlSchemaWhitespaceValueType ws;
24414 
24415     /*
24416     * In Libxml2, derived built-in types have currently no explicit facets.
24417     */
24418     if (type->type == XML_SCHEMA_TYPE_BASIC)
24419 	return (0);
24420 
24421     /*
24422     * NOTE: Do not jump away, if the facetSet of the given type is
24423     * empty: until now, "pattern" and "enumeration" facets of the
24424     * *base types* need to be checked as well.
24425     */
24426     if (type->facetSet == NULL)
24427 	goto pattern_and_enum;
24428 
24429     if (! WXS_IS_ATOMIC(type)) {
24430 	if (WXS_IS_LIST(type))
24431 	    goto WXS_IS_LIST;
24432 	else
24433 	    goto pattern_and_enum;
24434     }
24435 
24436     /*
24437     * Whitespace handling is only of importance for string-based
24438     * types.
24439     */
24440     tmpType = xmlSchemaGetPrimitiveType(type);
24441     if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
24442 	WXS_IS_ANY_SIMPLE_TYPE(tmpType)) {
24443 	ws = xmlSchemaGetWhiteSpaceFacetValue(type);
24444     } else
24445 	ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
24446 
24447     /*
24448     * If the value was not computed (for string or
24449     * anySimpleType based types), then use the provided
24450     * type.
24451     */
24452     if (val != NULL)
24453 	valType = xmlSchemaGetValType(val);
24454 
24455     ret = 0;
24456     for (facetLink = type->facetSet; facetLink != NULL;
24457 	facetLink = facetLink->next) {
24458 	/*
24459 	* Skip the pattern "whiteSpace": it is used to
24460 	* format the character content beforehand.
24461 	*/
24462 	switch (facetLink->facet->type) {
24463 	    case XML_SCHEMA_FACET_WHITESPACE:
24464 	    case XML_SCHEMA_FACET_PATTERN:
24465 	    case XML_SCHEMA_FACET_ENUMERATION:
24466 		continue;
24467 	    case XML_SCHEMA_FACET_LENGTH:
24468 	    case XML_SCHEMA_FACET_MINLENGTH:
24469 	    case XML_SCHEMA_FACET_MAXLENGTH:
24470 		ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
24471 		    valType, value, val, &len, ws);
24472 		break;
24473 	    default:
24474 		ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
24475 		    valType, value, val, ws);
24476 		break;
24477 	}
24478 	if (ret < 0) {
24479 	    AERROR_INT("xmlSchemaValidateFacets",
24480 		"validating against a atomic type facet");
24481 	    return (-1);
24482 	} else if (ret > 0) {
24483 	    if (fireErrors)
24484 		xmlSchemaFacetErr(actxt, ret, node,
24485 		value, len, type, facetLink->facet, NULL, NULL, NULL);
24486 	    else
24487 		return (ret);
24488 	    if (error == 0)
24489 		error = ret;
24490 	}
24491 	ret = 0;
24492     }
24493 
24494 WXS_IS_LIST:
24495     if (! WXS_IS_LIST(type))
24496 	goto pattern_and_enum;
24497     /*
24498     * "length", "minLength" and "maxLength" of list types.
24499     */
24500     ret = 0;
24501     for (facetLink = type->facetSet; facetLink != NULL;
24502 	facetLink = facetLink->next) {
24503 
24504 	switch (facetLink->facet->type) {
24505 	    case XML_SCHEMA_FACET_LENGTH:
24506 	    case XML_SCHEMA_FACET_MINLENGTH:
24507 	    case XML_SCHEMA_FACET_MAXLENGTH:
24508 		ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
24509 		    value, length, NULL);
24510 		break;
24511 	    default:
24512 		continue;
24513 	}
24514 	if (ret < 0) {
24515 	    AERROR_INT("xmlSchemaValidateFacets",
24516 		"validating against a list type facet");
24517 	    return (-1);
24518 	} else if (ret > 0) {
24519 	    if (fireErrors)
24520 		xmlSchemaFacetErr(actxt, ret, node,
24521 		value, length, type, facetLink->facet, NULL, NULL, NULL);
24522 	    else
24523 		return (ret);
24524 	    if (error == 0)
24525 		error = ret;
24526 	}
24527 	ret = 0;
24528     }
24529 
24530 pattern_and_enum:
24531     found = 0;
24532     /*
24533     * Process enumerations. Facet values are in the value space
24534     * of the defining type's base type. This seems to be a bug in the
24535     * XML Schema 1.0 spec. Use the whitespace type of the base type.
24536     * Only the first set of enumerations in the ancestor-or-self axis
24537     * is used for validation.
24538     */
24539     ret = 0;
24540     tmpType = type;
24541     do {
24542         for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
24543             if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
24544                 continue;
24545             found = 1;
24546             ret = xmlSchemaAreValuesEqual(facet->val, val);
24547             if (ret == 1)
24548                 break;
24549             else if (ret < 0) {
24550                 AERROR_INT("xmlSchemaValidateFacets",
24551                     "validating against an enumeration facet");
24552                 return (-1);
24553             }
24554         }
24555         if (ret != 0)
24556             break;
24557         /*
24558         * Break on the first set of enumerations. Any additional
24559         *  enumerations which might be existent on the ancestors
24560         *  of the current type are restricted by this set; thus
24561         *  *must* *not* be taken into account.
24562         */
24563         if (found)
24564             break;
24565         tmpType = tmpType->baseType;
24566     } while ((tmpType != NULL) &&
24567         (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24568     if (found && (ret == 0)) {
24569         ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
24570         if (fireErrors) {
24571             xmlSchemaFacetErr(actxt, ret, node,
24572                 value, 0, type, NULL, NULL, NULL, NULL);
24573         } else
24574             return (ret);
24575         if (error == 0)
24576             error = ret;
24577     }
24578 
24579     /*
24580     * Process patters. Pattern facets are ORed at type level
24581     * and ANDed if derived. Walk the base type axis.
24582     */
24583     tmpType = type;
24584     facet = NULL;
24585     do {
24586         found = 0;
24587         for (facetLink = tmpType->facetSet; facetLink != NULL;
24588             facetLink = facetLink->next) {
24589             if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
24590                 continue;
24591             found = 1;
24592             /*
24593             * NOTE that for patterns, @value needs to be the
24594             * normalized value.
24595             */
24596             ret = xmlRegexpExec(facetLink->facet->regexp, value);
24597             if (ret == 1)
24598                 break;
24599             else if (ret < 0) {
24600                 AERROR_INT("xmlSchemaValidateFacets",
24601                     "validating against a pattern facet");
24602                 return (-1);
24603             } else {
24604                 /*
24605                 * Save the last non-validating facet.
24606                 */
24607                 facet = facetLink->facet;
24608             }
24609         }
24610         if (found && (ret != 1)) {
24611             ret = XML_SCHEMAV_CVC_PATTERN_VALID;
24612             if (fireErrors) {
24613                 xmlSchemaFacetErr(actxt, ret, node,
24614                     value, 0, type, facet, NULL, NULL, NULL);
24615             } else
24616                 return (ret);
24617             if (error == 0)
24618                 error = ret;
24619             break;
24620         }
24621         tmpType = tmpType->baseType;
24622     } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24623 
24624     return (error);
24625 }
24626 
24627 static xmlChar *
xmlSchemaNormalizeValue(xmlSchemaTypePtr type,const xmlChar * value)24628 xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
24629 			const xmlChar *value)
24630 {
24631     switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
24632 	case XML_SCHEMA_WHITESPACE_COLLAPSE:
24633 	    return (xmlSchemaCollapseString(value));
24634 	case XML_SCHEMA_WHITESPACE_REPLACE:
24635 	    return (xmlSchemaWhiteSpaceReplace(value));
24636 	default:
24637 	    return (NULL);
24638     }
24639 }
24640 
24641 static int
xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,const xmlChar * value,xmlSchemaValPtr * val,int valNeeded)24642 xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
24643 		       const xmlChar *value,
24644 		       xmlSchemaValPtr *val,
24645 		       int valNeeded)
24646 {
24647     int ret;
24648     const xmlChar *nsName;
24649     xmlChar *local, *prefix = NULL;
24650 
24651     ret = xmlValidateQName(value, 1);
24652     if (ret != 0) {
24653 	if (ret == -1) {
24654 	    VERROR_INT("xmlSchemaValidateQName",
24655 		"calling xmlValidateQName()");
24656 	    return (-1);
24657 	}
24658 	return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
24659     }
24660     /*
24661     * NOTE: xmlSplitQName2 will always return a duplicated
24662     * strings.
24663     */
24664     local = xmlSplitQName2(value, &prefix);
24665     if (local == NULL)
24666 	local = xmlStrdup(value);
24667     /*
24668     * OPTIMIZE TODO: Use flags for:
24669     *  - is there any namespace binding?
24670     *  - is there a default namespace?
24671     */
24672     nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24673 
24674     if (prefix != NULL) {
24675 	xmlFree(prefix);
24676 	/*
24677 	* A namespace must be found if the prefix is
24678 	* NOT NULL.
24679 	*/
24680 	if (nsName == NULL) {
24681 	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24682 	    xmlSchemaCustomErr(ACTXT_CAST vctxt, ret, NULL,
24683 		WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24684 		"The QName value '%s' has no "
24685 		"corresponding namespace declaration in "
24686 		"scope", value, NULL);
24687 	    if (local != NULL)
24688 		xmlFree(local);
24689 	    return (ret);
24690 	}
24691     }
24692     if (valNeeded && val) {
24693 	if (nsName != NULL)
24694 	    *val = xmlSchemaNewQNameValue(
24695 		BAD_CAST xmlStrdup(nsName), BAD_CAST local);
24696 	else
24697 	    *val = xmlSchemaNewQNameValue(NULL,
24698 		BAD_CAST local);
24699     } else
24700 	xmlFree(local);
24701     return (0);
24702 }
24703 
24704 /*
24705 * cvc-simple-type
24706 */
24707 static int
xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,xmlNodePtr node,xmlSchemaTypePtr type,const xmlChar * value,xmlSchemaValPtr * retVal,int fireErrors,int normalize,int isNormalized)24708 xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
24709 			     xmlNodePtr node,
24710 			     xmlSchemaTypePtr type,
24711 			     const xmlChar *value,
24712 			     xmlSchemaValPtr *retVal,
24713 			     int fireErrors,
24714 			     int normalize,
24715 			     int isNormalized)
24716 {
24717     int ret = 0, valNeeded = (retVal) ? 1 : 0;
24718     xmlSchemaValPtr val = NULL;
24719     /* xmlSchemaWhitespaceValueType ws; */
24720     xmlChar *normValue = NULL;
24721 
24722 #define NORMALIZE(atype) \
24723     if ((! isNormalized) && \
24724     (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
24725 	normValue = xmlSchemaNormalizeValue(atype, value); \
24726 	if (normValue != NULL) \
24727 	    value = normValue; \
24728 	isNormalized = 1; \
24729     }
24730 
24731     if ((retVal != NULL) && (*retVal != NULL)) {
24732 	xmlSchemaFreeValue(*retVal);
24733 	*retVal = NULL;
24734     }
24735     /*
24736     * 3.14.4 Simple Type Definition Validation Rules
24737     * Validation Rule: String Valid
24738     */
24739     /*
24740     * 1 It is schema-valid with respect to that definition as defined
24741     * by Datatype Valid in [XML Schemas: Datatypes].
24742     */
24743     /*
24744     * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
24745     * the empty set, as defined in Type Derivation OK (Simple) ($3.14.6), then
24746     * the string must be a `declared entity name`.
24747     */
24748     /*
24749     * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
24750     * given the empty set, as defined in Type Derivation OK (Simple) ($3.14.6),
24751     * then every whitespace-delimited substring of the string must be a `declared
24752     * entity name`.
24753     */
24754     /*
24755     * 2.3 otherwise no further condition applies.
24756     */
24757     if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
24758 	valNeeded = 1;
24759     if (value == NULL)
24760 	value = BAD_CAST "";
24761     if (WXS_IS_ANY_SIMPLE_TYPE(type) || WXS_IS_ATOMIC(type)) {
24762 	xmlSchemaTypePtr biType; /* The built-in type. */
24763 	/*
24764 	* SPEC (1.2.1) "if {variety} is `atomic` then the string must `match`
24765 	* a literal in the `lexical space` of {base type definition}"
24766 	*/
24767 	/*
24768 	* Whitespace-normalize.
24769 	*/
24770 	NORMALIZE(type);
24771 	if (type->type != XML_SCHEMA_TYPE_BASIC) {
24772 	    /*
24773 	    * Get the built-in type.
24774 	    */
24775 	    biType = type->baseType;
24776 	    while ((biType != NULL) &&
24777 		(biType->type != XML_SCHEMA_TYPE_BASIC))
24778 		biType = biType->baseType;
24779 
24780 	    if (biType == NULL) {
24781 		AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24782 		    "could not get the built-in type");
24783 		goto internal_error;
24784 	    }
24785 	} else
24786 	    biType = type;
24787 	/*
24788 	* NOTATIONs need to be processed here, since they need
24789 	* to lookup in the hashtable of NOTATION declarations of the schema.
24790 	*/
24791 	if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
24792 	    switch (biType->builtInType) {
24793 		case XML_SCHEMAS_NOTATION:
24794 		    ret = xmlSchemaValidateNotation(
24795 			(xmlSchemaValidCtxtPtr) actxt,
24796 			((xmlSchemaValidCtxtPtr) actxt)->schema,
24797 			NULL, value, &val, valNeeded);
24798 		    break;
24799 		case XML_SCHEMAS_QNAME:
24800 		    ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
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 if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
24814 	    switch (biType->builtInType) {
24815 		case XML_SCHEMAS_NOTATION:
24816 		    ret = xmlSchemaValidateNotation(NULL,
24817 			((xmlSchemaParserCtxtPtr) actxt)->schema, node,
24818 			value, &val, valNeeded);
24819 		    break;
24820 		default:
24821 		    /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24822 		    if (valNeeded)
24823 			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24824 			    value, &val, node);
24825 		    else
24826 			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24827 			    value, NULL, node);
24828 		    break;
24829 	    }
24830 	} else {
24831 	    /*
24832 	    * Validation via a public API is not implemented yet.
24833 	    */
24834 	    TODO
24835 	    goto internal_error;
24836 	}
24837 	if (ret != 0) {
24838 	    if (ret < 0) {
24839 		AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24840 		    "validating against a built-in type");
24841 		goto internal_error;
24842 	    }
24843 	    if (WXS_IS_LIST(type))
24844 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24845 	    else
24846 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24847 	}
24848 	if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24849 	    /*
24850 	    * Check facets.
24851 	    */
24852 	    ret = xmlSchemaValidateFacets(actxt, node, type,
24853 		(xmlSchemaValType) biType->builtInType, value, val,
24854 		0, fireErrors);
24855 	    if (ret != 0) {
24856 		if (ret < 0) {
24857 		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24858 			"validating facets of atomic simple type");
24859 		    goto internal_error;
24860 		}
24861 		if (WXS_IS_LIST(type))
24862 		    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24863 		else
24864 		    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24865 	    }
24866 	}
24867 	else if (fireErrors && (ret > 0))
24868 	    xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24869     } else if (WXS_IS_LIST(type)) {
24870 
24871 	xmlSchemaTypePtr itemType;
24872 	const xmlChar *cur, *end;
24873 	xmlChar *tmpValue = NULL;
24874 	unsigned long len = 0;
24875 	xmlSchemaValPtr prevVal = NULL, curVal = NULL;
24876 	/* 1.2.2 if {variety} is `list` then the string must be a sequence
24877 	* of white space separated tokens, each of which `match`es a literal
24878 	* in the `lexical space` of {item type definition}
24879 	*/
24880 	/*
24881 	* Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
24882 	* the list type has an enum or pattern facet.
24883 	*/
24884 	NORMALIZE(type);
24885 	/*
24886 	* VAL TODO: Optimize validation of empty values.
24887 	* VAL TODO: We do not have computed values for lists.
24888 	*/
24889 	itemType = WXS_LIST_ITEMTYPE(type);
24890 	cur = value;
24891 	do {
24892 	    while (IS_BLANK_CH(*cur))
24893 		cur++;
24894 	    end = cur;
24895 	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
24896 		end++;
24897 	    if (end == cur)
24898 		break;
24899 	    tmpValue = xmlStrndup(cur, end - cur);
24900 	    len++;
24901 
24902 	    if (valNeeded)
24903 		ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24904 		    tmpValue, &curVal, fireErrors, 0, 1);
24905 	    else
24906 		ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24907 		    tmpValue, NULL, fireErrors, 0, 1);
24908 	    FREE_AND_NULL(tmpValue);
24909 	    if (curVal != NULL) {
24910 		/*
24911 		* Add to list of computed values.
24912 		*/
24913 		if (val == NULL)
24914 		    val = curVal;
24915 		else
24916 		    xmlSchemaValueAppend(prevVal, curVal);
24917 		prevVal = curVal;
24918 		curVal = NULL;
24919 	    }
24920 	    if (ret != 0) {
24921 		if (ret < 0) {
24922 		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24923 			"validating an item of list simple type");
24924 		    goto internal_error;
24925 		}
24926 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24927 		break;
24928 	    }
24929 	    cur = end;
24930 	} while (*cur != 0);
24931 	FREE_AND_NULL(tmpValue);
24932 	if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24933 	    /*
24934 	    * Apply facets (pattern, enumeration).
24935 	    */
24936 	    ret = xmlSchemaValidateFacets(actxt, node, type,
24937 		XML_SCHEMAS_UNKNOWN, value, val,
24938 		len, fireErrors);
24939 	    if (ret != 0) {
24940 		if (ret < 0) {
24941 		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24942 			"validating facets of list simple type");
24943 		    goto internal_error;
24944 		}
24945 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24946 	    }
24947 	}
24948 	if (fireErrors && (ret > 0)) {
24949 	    /*
24950 	    * Report the normalized value.
24951 	    */
24952 	    normalize = 1;
24953 	    NORMALIZE(type);
24954 	    xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24955 	}
24956     } else if (WXS_IS_UNION(type)) {
24957 	xmlSchemaTypeLinkPtr memberLink;
24958 	/*
24959 	* TODO: For all datatypes `derived` by `union`  whiteSpace does
24960 	* not apply directly; however, the normalization behavior of `union`
24961 	* types is controlled by the value of whiteSpace on that one of the
24962 	* `memberTypes` against which the `union` is successfully validated.
24963 	*
24964 	* This means that the value is normalized by the first validating
24965 	* member type, then the facets of the union type are applied. This
24966 	* needs changing of the value!
24967 	*/
24968 
24969 	/*
24970 	* 1.2.3 if {variety} is `union` then the string must `match` a
24971 	* literal in the `lexical space` of at least one member of
24972 	* {member type definitions}
24973 	*/
24974 	memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
24975 	if (memberLink == NULL) {
24976 	    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24977 		"union simple type has no member types");
24978 	    goto internal_error;
24979 	}
24980 	/*
24981 	* Always normalize union type values, since we currently
24982 	* cannot store the whitespace information with the value
24983 	* itself; otherwise a later value-comparison would be
24984 	* not possible.
24985 	*/
24986 	while (memberLink != NULL) {
24987 	    if (valNeeded)
24988 		ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24989 		    memberLink->type, value, &val, 0, 1, 0);
24990 	    else
24991 		ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24992 		    memberLink->type, value, NULL, 0, 1, 0);
24993 	    if (ret <= 0)
24994 		break;
24995 	    memberLink = memberLink->next;
24996 	}
24997 	if (ret != 0) {
24998 	    if (ret < 0) {
24999 		AERROR_INT("xmlSchemaVCheckCVCSimpleType",
25000 		    "validating members of union simple type");
25001 		goto internal_error;
25002 	    }
25003 	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
25004 	}
25005 	/*
25006 	* Apply facets (pattern, enumeration).
25007 	*/
25008 	if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
25009 	    /*
25010 	    * The normalization behavior of `union` types is controlled by
25011 	    * the value of whiteSpace on that one of the `memberTypes`
25012 	    * against which the `union` is successfully validated.
25013 	    */
25014 	    NORMALIZE(memberLink->type);
25015 	    ret = xmlSchemaValidateFacets(actxt, node, type,
25016 		XML_SCHEMAS_UNKNOWN, value, val,
25017 		0, fireErrors);
25018 	    if (ret != 0) {
25019 		if (ret < 0) {
25020 		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
25021 			"validating facets of union simple type");
25022 		    goto internal_error;
25023 		}
25024 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
25025 	    }
25026 	}
25027 	if (fireErrors && (ret > 0))
25028 	    xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
25029     }
25030 
25031     if (normValue != NULL)
25032 	xmlFree(normValue);
25033     if (ret == 0) {
25034 	if (retVal != NULL)
25035 	    *retVal = val;
25036 	else if (val != NULL)
25037 	    xmlSchemaFreeValue(val);
25038     } else if (val != NULL)
25039 	xmlSchemaFreeValue(val);
25040     return (ret);
25041 internal_error:
25042     if (normValue != NULL)
25043 	xmlFree(normValue);
25044     if (val != NULL)
25045 	xmlSchemaFreeValue(val);
25046     return (-1);
25047 }
25048 
25049 static int
xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,const xmlChar * value,const xmlChar ** nsName,const xmlChar ** localName)25050 xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
25051 			   const xmlChar *value,
25052 			   const xmlChar **nsName,
25053 			   const xmlChar **localName)
25054 {
25055     int ret = 0;
25056 
25057     if ((nsName == NULL) || (localName == NULL))
25058 	return (-1);
25059     *nsName = NULL;
25060     *localName = NULL;
25061 
25062     ret = xmlValidateQName(value, 1);
25063     if (ret == -1)
25064 	return (-1);
25065     if (ret > 0) {
25066 	xmlSchemaSimpleTypeErr(ACTXT_CAST vctxt,
25067 	    XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
25068 	    value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
25069 	return (1);
25070     }
25071     {
25072 	xmlChar *local = NULL;
25073 	xmlChar *prefix;
25074 
25075 	/*
25076 	* NOTE: xmlSplitQName2 will return a duplicated
25077 	* string.
25078 	*/
25079 	local = xmlSplitQName2(value, &prefix);
25080 	if (local == NULL)
25081 	    *localName = xmlDictLookup(vctxt->dict, value, -1);
25082 	else {
25083 	    *localName = xmlDictLookup(vctxt->dict, local, -1);
25084 	    xmlFree(local);
25085 	}
25086 
25087 	*nsName = xmlSchemaLookupNamespace(vctxt, prefix);
25088 
25089 	if (prefix != NULL) {
25090 	    xmlFree(prefix);
25091 	    /*
25092 	    * A namespace must be found if the prefix is NOT NULL.
25093 	    */
25094 	    if (*nsName == NULL) {
25095 		xmlSchemaCustomErr(ACTXT_CAST vctxt,
25096 		    XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
25097 		    WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
25098 		    "The QName value '%s' has no "
25099 		    "corresponding namespace declaration in scope",
25100 		    value, NULL);
25101 		return (2);
25102 	    }
25103 	}
25104     }
25105     return (0);
25106 }
25107 
25108 static int
xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,xmlSchemaAttrInfoPtr iattr,xmlSchemaTypePtr * localType,xmlSchemaElementPtr elemDecl)25109 xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
25110 			xmlSchemaAttrInfoPtr iattr,
25111 			xmlSchemaTypePtr *localType,
25112 			xmlSchemaElementPtr elemDecl)
25113 {
25114     int ret = 0;
25115     /*
25116     * cvc-elt (3.3.4) : (4)
25117     * AND
25118     * Schema-Validity Assessment (Element) (cvc-assess-elt)
25119     *   (1.2.1.2.1) - (1.2.1.2.4)
25120     * Handle 'xsi:type'.
25121     */
25122     if (localType == NULL)
25123 	return (-1);
25124     *localType = NULL;
25125     if (iattr == NULL)
25126 	return (0);
25127     else {
25128 	const xmlChar *nsName = NULL, *local = NULL;
25129 	/*
25130 	* TODO: We should report a *warning* that the type was overridden
25131 	* by the instance.
25132 	*/
25133 	ACTIVATE_ATTRIBUTE(iattr);
25134 	/*
25135 	* (cvc-elt) (3.3.4) : (4.1)
25136 	* (cvc-assess-elt) (1.2.1.2.2)
25137 	*/
25138 	ret = xmlSchemaVExpandQName(vctxt, iattr->value,
25139 	    &nsName, &local);
25140 	if (ret != 0) {
25141 	    if (ret < 0) {
25142 		VERROR_INT("xmlSchemaValidateElementByDeclaration",
25143 		    "calling xmlSchemaQNameExpand() to validate the "
25144 		    "attribute 'xsi:type'");
25145 		goto internal_error;
25146 	    }
25147 	    goto exit;
25148 	}
25149 	/*
25150 	* (cvc-elt) (3.3.4) : (4.2)
25151 	* (cvc-assess-elt) (1.2.1.2.3)
25152 	*/
25153 	*localType = xmlSchemaGetType(vctxt->schema, local, nsName);
25154 	if (*localType == NULL) {
25155 	    xmlChar *str = NULL;
25156 
25157 	    xmlSchemaCustomErr(ACTXT_CAST vctxt,
25158 		XML_SCHEMAV_CVC_ELT_4_2, NULL,
25159 		WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
25160 		"The QName value '%s' of the xsi:type attribute does not "
25161 		"resolve to a type definition",
25162 		xmlSchemaFormatQName(&str, nsName, local), NULL);
25163 	    FREE_AND_NULL(str);
25164 	    ret = vctxt->err;
25165 	    goto exit;
25166 	}
25167 	if (elemDecl != NULL) {
25168 	    int set = 0;
25169 
25170 	    /*
25171 	    * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
25172 	    * "The `local type definition` must be validly
25173 	    * derived from the {type definition} given the union of
25174 	    * the {disallowed substitutions} and the {type definition}'s
25175 	    * {prohibited substitutions}, as defined in
25176 	    * Type Derivation OK (Complex) ($3.4.6)
25177 	    * (if it is a complex type definition),
25178 	    * or given {disallowed substitutions} as defined in Type
25179 	    * Derivation OK (Simple) ($3.14.6) (if it is a simple type
25180 	    * definition)."
25181 	    *
25182 	    * {disallowed substitutions}: the "block" on the element decl.
25183 	    * {prohibited substitutions}: the "block" on the type def.
25184 	    */
25185 	    /*
25186 	    * OPTIMIZE TODO: We could map types already evaluated
25187 	    * to be validly derived from other types to avoid checking
25188 	    * this over and over for the same types.
25189 	    */
25190 	    if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
25191 		(elemDecl->subtypes->flags &
25192 		    XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
25193 		set |= SUBSET_EXTENSION;
25194 
25195 	    if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
25196 		(elemDecl->subtypes->flags &
25197 		    XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
25198 		set |= SUBSET_RESTRICTION;
25199 
25200 	    /*
25201 	    * REMOVED and CHANGED since this produced a parser context
25202 	    * which adds to the string dict of the schema. So this would
25203 	    * change the schema and we don't want this. We don't need
25204 	    * the parser context anymore.
25205 	    *
25206 	    * if ((vctxt->pctxt == NULL) &&
25207 	    *	(xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
25208 	    *	    return (-1);
25209 	    */
25210 
25211 	    if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST vctxt, *localType,
25212 		elemDecl->subtypes, set) != 0) {
25213 		xmlChar *str = NULL;
25214 
25215 		xmlSchemaCustomErr(ACTXT_CAST vctxt,
25216 		    XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
25217 		    "The type definition '%s', specified by xsi:type, is "
25218 		    "blocked or not validly derived from the type definition "
25219 		    "of the element declaration",
25220 		    xmlSchemaFormatQName(&str,
25221 			(*localType)->targetNamespace,
25222 			(*localType)->name),
25223 		    NULL);
25224 		FREE_AND_NULL(str);
25225 		ret = vctxt->err;
25226 		*localType = NULL;
25227 	    }
25228 	}
25229     }
25230 exit:
25231     ACTIVATE_ELEM;
25232     return (ret);
25233 internal_error:
25234     ACTIVATE_ELEM;
25235     return (-1);
25236 }
25237 
25238 static int
xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)25239 xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
25240 {
25241     xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
25242     xmlSchemaTypePtr actualType;
25243 
25244     /*
25245     * cvc-elt (3.3.4) : 1
25246     */
25247     if (elemDecl == NULL) {
25248 	VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
25249 	    "No matching declaration available");
25250         return (vctxt->err);
25251     }
25252     actualType = WXS_ELEM_TYPEDEF(elemDecl);
25253     /*
25254     * cvc-elt (3.3.4) : 2
25255     */
25256     if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
25257 	VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
25258 	    "The element declaration is abstract");
25259         return (vctxt->err);
25260     }
25261     if (actualType == NULL) {
25262 	VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
25263 	    "The type definition is absent");
25264 	return (XML_SCHEMAV_CVC_TYPE_1);
25265     }
25266     if (vctxt->nbAttrInfos != 0) {
25267 	int ret;
25268 	xmlSchemaAttrInfoPtr iattr;
25269 	/*
25270 	* cvc-elt (3.3.4) : 3
25271 	* Handle 'xsi:nil'.
25272 	*/
25273 	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25274 	    XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
25275 	if (iattr) {
25276 	    ACTIVATE_ATTRIBUTE(iattr);
25277 	    /*
25278 	    * Validate the value.
25279 	    */
25280 	    ret = xmlSchemaVCheckCVCSimpleType(
25281 		ACTXT_CAST vctxt, NULL,
25282 		xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
25283 		iattr->value, &(iattr->val), 1, 0, 0);
25284 	    ACTIVATE_ELEM;
25285 	    if (ret < 0) {
25286 		VERROR_INT("xmlSchemaValidateElemDecl",
25287 		    "calling xmlSchemaVCheckCVCSimpleType() to "
25288 		    "validate the attribute 'xsi:nil'");
25289 		return (-1);
25290 	    }
25291 	    if (ret == 0) {
25292 		if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
25293 		    /*
25294 		    * cvc-elt (3.3.4) : 3.1
25295 		    */
25296 		    VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
25297 			"The element is not 'nillable'");
25298 		    /* Does not return an error on purpose. */
25299 		} else {
25300 		    if (xmlSchemaValueGetAsBoolean(iattr->val)) {
25301 			/*
25302 			* cvc-elt (3.3.4) : 3.2.2
25303 			*/
25304 			if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
25305 			    (elemDecl->value != NULL)) {
25306 			    VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
25307 				"The element cannot be 'nilled' because "
25308 				"there is a fixed value constraint defined "
25309 				"for it");
25310 			     /* Does not return an error on purpose. */
25311 			} else
25312 			    vctxt->inode->flags |=
25313 				XML_SCHEMA_ELEM_INFO_NILLED;
25314 		    }
25315 		}
25316 	    }
25317 	}
25318 	/*
25319 	* cvc-elt (3.3.4) : 4
25320 	* Handle 'xsi:type'.
25321 	*/
25322 	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25323 	    XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25324 	if (iattr) {
25325 	    xmlSchemaTypePtr localType = NULL;
25326 
25327 	    ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
25328 		elemDecl);
25329 	    if (ret != 0) {
25330 		if (ret == -1) {
25331 		    VERROR_INT("xmlSchemaValidateElemDecl",
25332 			"calling xmlSchemaProcessXSIType() to "
25333 			"process the attribute 'xsi:type'");
25334 		    return (-1);
25335 		}
25336 		/* Does not return an error on purpose. */
25337 	    }
25338 	    if (localType != NULL) {
25339 		vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
25340 		actualType = localType;
25341 	    }
25342 	}
25343     }
25344     /*
25345     * IDC: Register identity-constraint XPath matchers.
25346     */
25347     if ((elemDecl->idcs != NULL) &&
25348 	(xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
25349 	    return (-1);
25350     /*
25351     * No actual type definition.
25352     */
25353     if (actualType == NULL) {
25354 	VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
25355 	    "The type definition is absent");
25356 	return (XML_SCHEMAV_CVC_TYPE_1);
25357     }
25358     /*
25359     * Remember the actual type definition.
25360     */
25361     vctxt->inode->typeDef = actualType;
25362 
25363     return (0);
25364 }
25365 
25366 static int
xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)25367 xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
25368 {
25369     xmlSchemaAttrInfoPtr iattr;
25370     int ret = 0, i;
25371 
25372     /*
25373     * SPEC cvc-type (3.1.1)
25374     * "The attributes of must be empty, excepting those whose namespace
25375     * name is identical to http://www.w3.org/2001/XMLSchema-instance and
25376     * whose local name is one of type, nil, schemaLocation or
25377     * noNamespaceSchemaLocation."
25378     */
25379     if (vctxt->nbAttrInfos == 0)
25380 	return (0);
25381     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25382 	iattr = vctxt->attrInfos[i];
25383 	if (! iattr->metaType) {
25384 	    ACTIVATE_ATTRIBUTE(iattr)
25385 	    xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25386 		XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
25387 	    ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
25388         }
25389     }
25390     ACTIVATE_ELEM
25391     return (ret);
25392 }
25393 
25394 /*
25395 * Cleanup currently used attribute infos.
25396 */
25397 static void
xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)25398 xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
25399 {
25400     int i;
25401     xmlSchemaAttrInfoPtr attr;
25402 
25403     if (vctxt->nbAttrInfos == 0)
25404 	return;
25405     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25406 	attr = vctxt->attrInfos[i];
25407 	if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
25408 	    if (attr->localName != NULL)
25409 		xmlFree((xmlChar *) attr->localName);
25410 	    if (attr->nsName != NULL)
25411 		xmlFree((xmlChar *) attr->nsName);
25412 	}
25413 	if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
25414 	    if (attr->value != NULL)
25415 		xmlFree((xmlChar *) attr->value);
25416 	}
25417 	if (attr->val != NULL) {
25418 	    xmlSchemaFreeValue(attr->val);
25419 	    attr->val = NULL;
25420 	}
25421 	memset(attr, 0, sizeof(xmlSchemaAttrInfo));
25422     }
25423     vctxt->nbAttrInfos = 0;
25424 }
25425 
25426 /*
25427 * 3.4.4 Complex Type Definition Validation Rules
25428 *   Element Locally Valid (Complex Type) (cvc-complex-type)
25429 * 3.2.4 Attribute Declaration Validation Rules
25430 *   Validation Rule: Attribute Locally Valid (cvc-attribute)
25431 *   Attribute Locally Valid (Use) (cvc-au)
25432 *
25433 * Only "assessed" attribute information items will be visible to
25434 * IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
25435 */
25436 static int
xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)25437 xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
25438 {
25439     xmlSchemaTypePtr type = vctxt->inode->typeDef;
25440     xmlSchemaItemListPtr attrUseList;
25441     xmlSchemaAttributeUsePtr attrUse = NULL;
25442     xmlSchemaAttributePtr attrDecl = NULL;
25443     xmlSchemaAttrInfoPtr iattr, tmpiattr;
25444     int i, j, found, nbAttrs, nbUses;
25445     int xpathRes = 0, res, wildIDs = 0, fixed;
25446     xmlNodePtr defAttrOwnerElem = NULL;
25447 
25448     /*
25449     * SPEC (cvc-attribute)
25450     * (1) "The declaration must not be `absent` (see Missing
25451     * Sub-components ($5.3) for how this can fail to be
25452     * the case)."
25453     * (2) "Its {type definition} must not be absent."
25454     *
25455     * NOTE (1) + (2): This is not handled here, since we currently do not
25456     * allow validation against schemas which have missing sub-components.
25457     *
25458     * SPEC (cvc-complex-type)
25459     * (3) "For each attribute information item in the element information
25460     * item's [attributes] excepting those whose [namespace name] is
25461     * identical to http://www.w3.org/2001/XMLSchema-instance and whose
25462     * [local name] is one of type, nil, schemaLocation or
25463     * noNamespaceSchemaLocation, the appropriate case among the following
25464     * must be true:
25465     *
25466     */
25467     attrUseList = (xmlSchemaItemListPtr) type->attrUses;
25468     /*
25469     * @nbAttrs is the number of attributes present in the instance.
25470     */
25471     nbAttrs = vctxt->nbAttrInfos;
25472     if (attrUseList != NULL)
25473 	nbUses = attrUseList->nbItems;
25474     else
25475 	nbUses = 0;
25476     for (i = 0; i < nbUses; i++) {
25477         found = 0;
25478 	attrUse = attrUseList->items[i];
25479 	attrDecl = WXS_ATTRUSE_DECL(attrUse);
25480         for (j = 0; j < nbAttrs; j++) {
25481 	    iattr = vctxt->attrInfos[j];
25482 	    /*
25483 	    * SPEC (cvc-complex-type) (3)
25484 	    * Skip meta attributes.
25485 	    */
25486 	    if (iattr->metaType)
25487 		continue;
25488 	    if (iattr->localName[0] != attrDecl->name[0])
25489 		continue;
25490 	    if (!xmlStrEqual(iattr->localName, attrDecl->name))
25491 		continue;
25492 	    if (!xmlStrEqual(iattr->nsName, attrDecl->targetNamespace))
25493 		continue;
25494 	    found = 1;
25495 	    /*
25496 	    * SPEC (cvc-complex-type)
25497 	    * (3.1) "If there is among the {attribute uses} an attribute
25498 	    * use with an {attribute declaration} whose {name} matches
25499 	    * the attribute information item's [local name] and whose
25500 	    * {target namespace} is identical to the attribute information
25501 	    * item's [namespace name] (where an `absent` {target namespace}
25502 	    * is taken to be identical to a [namespace name] with no value),
25503 	    * then the attribute information must be `valid` with respect
25504 	    * to that attribute use as per Attribute Locally Valid (Use)
25505 	    * ($3.5.4). In this case the {attribute declaration} of that
25506 	    * attribute use is the `context-determined declaration` for the
25507 	    * attribute information item with respect to Schema-Validity
25508 	    * Assessment (Attribute) ($3.2.4) and
25509 	    * Assessment Outcome (Attribute) ($3.2.5).
25510 	    */
25511 	    iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25512 	    iattr->use = attrUse;
25513 	    /*
25514 	    * Context-determined declaration.
25515 	    */
25516 	    iattr->decl = attrDecl;
25517 	    iattr->typeDef = attrDecl->subtypes;
25518 	    break;
25519 	}
25520 
25521 	if (found)
25522 	    continue;
25523 
25524 	if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
25525 	    /*
25526 	    * Handle non-existent, required attributes.
25527 	    *
25528 	    * SPEC (cvc-complex-type)
25529 	    * (4) "The {attribute declaration} of each attribute use in
25530 	    * the {attribute uses} whose {required} is true matches one
25531 	    * of the attribute information items in the element information
25532 	    * item's [attributes] as per clause 3.1 above."
25533 	    */
25534 	    tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25535 	    if (tmpiattr == NULL) {
25536 		VERROR_INT(
25537 		    "xmlSchemaVAttributesComplex",
25538 		    "calling xmlSchemaGetFreshAttrInfo()");
25539 		return (-1);
25540 	    }
25541 	    tmpiattr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
25542 	    tmpiattr->use = attrUse;
25543 	    tmpiattr->decl = attrDecl;
25544 	} else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
25545 	    ((attrUse->defValue != NULL) ||
25546 	     (attrDecl->defValue != NULL))) {
25547 	    /*
25548 	    * Handle non-existent, optional, default/fixed attributes.
25549 	    */
25550 	    tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25551 	    if (tmpiattr == NULL) {
25552 		VERROR_INT(
25553 		    "xmlSchemaVAttributesComplex",
25554 		    "calling xmlSchemaGetFreshAttrInfo()");
25555 		return (-1);
25556 	    }
25557 	    tmpiattr->state = XML_SCHEMAS_ATTR_DEFAULT;
25558 	    tmpiattr->use = attrUse;
25559 	    tmpiattr->decl = attrDecl;
25560 	    tmpiattr->typeDef = attrDecl->subtypes;
25561 	    tmpiattr->localName = attrDecl->name;
25562 	    tmpiattr->nsName = attrDecl->targetNamespace;
25563 	}
25564     }
25565 
25566     if (vctxt->nbAttrInfos == 0)
25567 	return (0);
25568     /*
25569     * Validate against the wildcard.
25570     */
25571     if (type->attributeWildcard != NULL) {
25572 	/*
25573 	* SPEC (cvc-complex-type)
25574 	* (3.2.1) "There must be an {attribute wildcard}."
25575 	*/
25576 	for (i = 0; i < nbAttrs; i++) {
25577 	    iattr = vctxt->attrInfos[i];
25578 	    /*
25579 	    * SPEC (cvc-complex-type) (3)
25580 	    * Skip meta attributes.
25581 	    */
25582 	    if (iattr->state != XML_SCHEMAS_ATTR_UNKNOWN)
25583 		continue;
25584 	    /*
25585 	    * SPEC (cvc-complex-type)
25586 	    * (3.2.2) "The attribute information item must be `valid` with
25587 	    * respect to it as defined in Item Valid (Wildcard) ($3.10.4)."
25588 	    *
25589 	    * SPEC Item Valid (Wildcard) (cvc-wildcard)
25590 	    * "... its [namespace name] must be `valid` with respect to
25591 	    * the wildcard constraint, as defined in Wildcard allows
25592 	    * Namespace Name ($3.10.4)."
25593 	    */
25594 	    if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
25595 		    iattr->nsName) == 0) {
25596 		/*
25597 		* Handle processContents.
25598 		*
25599 		* SPEC (cvc-wildcard):
25600 		* processContents | context-determined declaration:
25601 		* "strict"          "mustFind"
25602 		* "lax"             "none"
25603 		* "skip"            "skip"
25604 		*/
25605 		if (type->attributeWildcard->processContents ==
25606 		    XML_SCHEMAS_ANY_SKIP) {
25607 		     /*
25608 		    * context-determined declaration = "skip"
25609 		    *
25610 		    * SPEC PSVI Assessment Outcome (Attribute)
25611 		    * [validity] = "notKnown"
25612 		    * [validation attempted] = "none"
25613 		    */
25614 		    iattr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
25615 		    continue;
25616 		}
25617 		/*
25618 		* Find an attribute declaration.
25619 		*/
25620 		iattr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
25621 		    iattr->localName, iattr->nsName);
25622 		if (iattr->decl != NULL) {
25623 		    iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25624 		    /*
25625 		    * SPEC (cvc-complex-type)
25626 		    * (5) "Let [Definition:]  the wild IDs be the set of
25627 		    * all attribute information item to which clause 3.2
25628 		    * applied and whose `validation` resulted in a
25629 		    * `context-determined declaration` of mustFind or no
25630 		    * `context-determined declaration` at all, and whose
25631 		    * [local name] and [namespace name] resolve (as
25632 		    * defined by QName resolution (Instance) ($3.15.4)) to
25633 		    * an attribute declaration whose {type definition} is
25634 		    * or is derived from ID. Then all of the following
25635 		    * must be true:"
25636 		    */
25637 		    iattr->typeDef = WXS_ATTR_TYPEDEF(iattr->decl);
25638 		    if (xmlSchemaIsDerivedFromBuiltInType(
25639 			iattr->typeDef, XML_SCHEMAS_ID)) {
25640 			/*
25641 			* SPEC (5.1) "There must be no more than one
25642 			* item in `wild IDs`."
25643 			*/
25644 			if (wildIDs != 0) {
25645 			    /* VAL TODO */
25646 			    iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
25647 			    TODO
25648 			    continue;
25649 			}
25650 			wildIDs++;
25651 			/*
25652 			* SPEC (cvc-complex-type)
25653 			* (5.2) "If `wild IDs` is non-empty, there must not
25654 			* be any attribute uses among the {attribute uses}
25655 			* whose {attribute declaration}'s {type definition}
25656 			* is or is derived from ID."
25657 			*/
25658                         if (attrUseList != NULL) {
25659                             for (j = 0; j < attrUseList->nbItems; j++) {
25660                                 if (xmlSchemaIsDerivedFromBuiltInType(
25661                                     WXS_ATTRUSE_TYPEDEF(attrUseList->items[j]),
25662                                     XML_SCHEMAS_ID)) {
25663                                     /* URGENT VAL TODO: implement */
25664                             iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
25665                                     TODO
25666                                     break;
25667                                 }
25668                             }
25669                         }
25670 		    }
25671 		} else if (type->attributeWildcard->processContents ==
25672 		    XML_SCHEMAS_ANY_LAX) {
25673 		    iattr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
25674 		    /*
25675 		    * SPEC PSVI Assessment Outcome (Attribute)
25676 		    * [validity] = "notKnown"
25677 		    * [validation attempted] = "none"
25678 		    */
25679 		} else {
25680 		    iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
25681 		}
25682 	    }
25683 	}
25684     }
25685 
25686     if (vctxt->nbAttrInfos == 0)
25687 	return (0);
25688 
25689     /*
25690     * Get the owner element; needed for creation of default attributes.
25691     * This fixes bug #341337, reported by David Grohmann.
25692     */
25693     if (vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
25694 	xmlSchemaNodeInfoPtr ielem = vctxt->elemInfos[vctxt->depth];
25695 	if (ielem && ielem->node && ielem->node->doc)
25696 	    defAttrOwnerElem = ielem->node;
25697     }
25698     /*
25699     * Validate values, create default attributes, evaluate IDCs.
25700     */
25701     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25702 	iattr = vctxt->attrInfos[i];
25703 	/*
25704 	* VAL TODO: Note that we won't try to resolve IDCs to
25705 	* "lax" and "skip" validated attributes. Check what to
25706 	* do in this case.
25707 	*/
25708 	if ((iattr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
25709 	    (iattr->state != XML_SCHEMAS_ATTR_DEFAULT))
25710 	    continue;
25711 	/*
25712 	* VAL TODO: What to do if the type definition is missing?
25713 	*/
25714 	if (iattr->typeDef == NULL) {
25715 	    iattr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
25716 	    continue;
25717 	}
25718 
25719 	ACTIVATE_ATTRIBUTE(iattr);
25720 	fixed = 0;
25721 	xpathRes = 0;
25722 
25723 	if (vctxt->xpathStates != NULL) {
25724 	    /*
25725 	    * Evaluate IDCs.
25726 	    */
25727 	    xpathRes = xmlSchemaXPathEvaluate(vctxt,
25728 		XML_ATTRIBUTE_NODE);
25729 	    if (xpathRes == -1) {
25730 		VERROR_INT("xmlSchemaVAttributesComplex",
25731 		    "calling xmlSchemaXPathEvaluate()");
25732 		goto internal_error;
25733 	    }
25734 	}
25735 
25736 	if (iattr->state == XML_SCHEMAS_ATTR_DEFAULT) {
25737 	    /*
25738 	    * Default/fixed attributes.
25739 	    * We need the value only if we need to resolve IDCs or
25740 	    * will create default attributes.
25741 	    */
25742 	    if ((xpathRes) || (defAttrOwnerElem)) {
25743 		if (iattr->use->defValue != NULL) {
25744 		    iattr->value = (xmlChar *) iattr->use->defValue;
25745 		    iattr->val = iattr->use->defVal;
25746 		} else {
25747 		    iattr->value = (xmlChar *) iattr->decl->defValue;
25748 		    iattr->val = iattr->decl->defVal;
25749 		}
25750 		/*
25751 		* IDCs will consume the precomputed default value,
25752 		* so we need to clone it.
25753 		*/
25754 		if (iattr->val == NULL) {
25755 		    VERROR_INT("xmlSchemaVAttributesComplex",
25756 			"default/fixed value on an attribute use was "
25757 			"not precomputed");
25758 		    goto internal_error;
25759 		}
25760 		iattr->val = xmlSchemaCopyValue(iattr->val);
25761 		if (iattr->val == NULL) {
25762 		    VERROR_INT("xmlSchemaVAttributesComplex",
25763 			"calling xmlSchemaCopyValue()");
25764 		    goto internal_error;
25765 		}
25766 	    }
25767 	    /*
25768 	    * PSVI: Add the default attribute to the current element.
25769 	    * VAL TODO: Should we use the *normalized* value? This currently
25770 	    *   uses the *initial* value.
25771 	    */
25772 
25773 	    if (defAttrOwnerElem) {
25774 		xmlChar *normValue;
25775 		const xmlChar *value;
25776 
25777 		value = iattr->value;
25778 		/*
25779 		* Normalize the value.
25780 		*/
25781 		normValue = xmlSchemaNormalizeValue(iattr->typeDef,
25782 		    iattr->value);
25783 		if (normValue != NULL)
25784 		    value = BAD_CAST normValue;
25785 
25786 		if (iattr->nsName == NULL) {
25787 		    if (xmlNewProp(defAttrOwnerElem,
25788 			iattr->localName, value) == NULL) {
25789 			VERROR_INT("xmlSchemaVAttributesComplex",
25790 			    "calling xmlNewProp()");
25791 			if (normValue != NULL)
25792 			    xmlFree(normValue);
25793 			goto internal_error;
25794 		    }
25795 		} else {
25796 		    xmlNsPtr ns;
25797 
25798 		    ns = xmlSearchNsByHref(defAttrOwnerElem->doc,
25799 			defAttrOwnerElem, iattr->nsName);
25800 		    if (ns == NULL) {
25801 			xmlChar prefix[12];
25802 			int counter = 0;
25803 
25804 			/*
25805 			* Create a namespace declaration on the validation
25806 			* root node if no namespace declaration is in scope.
25807 			*/
25808 			do {
25809 			    snprintf((char *) prefix, 12, "p%d", counter++);
25810 			    ns = xmlSearchNs(defAttrOwnerElem->doc,
25811 				defAttrOwnerElem, BAD_CAST prefix);
25812 			    if (counter > 1000) {
25813 				VERROR_INT(
25814 				    "xmlSchemaVAttributesComplex",
25815 				    "could not compute a ns prefix for a "
25816 				    "default/fixed attribute");
25817 				if (normValue != NULL)
25818 				    xmlFree(normValue);
25819 				goto internal_error;
25820 			    }
25821 			} while (ns != NULL);
25822 			ns = xmlNewNs(vctxt->validationRoot,
25823 			    iattr->nsName, BAD_CAST prefix);
25824 		    }
25825 		    /*
25826 		    * TODO:
25827 		    * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0406.html
25828 		    * If we have QNames: do we need to ensure there's a
25829 		    * prefix defined for the QName?
25830 		    */
25831 		    xmlNewNsProp(defAttrOwnerElem, ns, iattr->localName, value);
25832 		}
25833 		if (normValue != NULL)
25834 		    xmlFree(normValue);
25835 	    }
25836 	    /*
25837 	    * Go directly to IDC evaluation.
25838 	    */
25839 	    goto eval_idcs;
25840 	}
25841 	/*
25842 	* Validate the value.
25843 	*/
25844 	if (vctxt->value != NULL) {
25845 	    /*
25846 	    * Free last computed value; just for safety reasons.
25847 	    */
25848 	    xmlSchemaFreeValue(vctxt->value);
25849 	    vctxt->value = NULL;
25850 	}
25851 	/*
25852 	* Note that the attribute *use* can be unavailable, if
25853 	* the attribute was a wild attribute.
25854 	*/
25855 	if ((iattr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
25856 	    ((iattr->use != NULL) &&
25857 	     (iattr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
25858 	    fixed = 1;
25859 	else
25860 	    fixed = 0;
25861 	/*
25862 	* SPEC (cvc-attribute)
25863 	* (3) "The item's `normalized value` must be locally `valid`
25864 	* with respect to that {type definition} as per
25865 	* String Valid ($3.14.4)."
25866 	*
25867 	* VAL TODO: Do we already have the
25868 	* "normalized attribute value" here?
25869 	*/
25870 	if (xpathRes || fixed) {
25871 	    iattr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
25872 	    /*
25873 	    * Request a computed value.
25874 	    */
25875 	    res = xmlSchemaVCheckCVCSimpleType(
25876 		ACTXT_CAST vctxt,
25877 		iattr->node, iattr->typeDef, iattr->value, &(iattr->val),
25878 		1, 1, 0);
25879 	} else {
25880 	    res = xmlSchemaVCheckCVCSimpleType(
25881 		ACTXT_CAST vctxt,
25882 		iattr->node, iattr->typeDef, iattr->value, NULL,
25883 		1, 0, 0);
25884 	}
25885 
25886 	if (res != 0) {
25887 	    if (res == -1) {
25888 		VERROR_INT("xmlSchemaVAttributesComplex",
25889 		    "calling xmlSchemaStreamValidateSimpleTypeValue()");
25890 		goto internal_error;
25891 	    }
25892 	    iattr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
25893 	    /*
25894 	    * SPEC PSVI Assessment Outcome (Attribute)
25895 	    * [validity] = "invalid"
25896 	    */
25897 	    goto eval_idcs;
25898 	}
25899 
25900 	if (fixed) {
25901 	    /*
25902 	    * SPEC Attribute Locally Valid (Use) (cvc-au)
25903 	    * "For an attribute information item to be `valid`
25904 	    * with respect to an attribute use its *normalized*
25905 	    * value must match the *canonical* lexical
25906 	    * representation of the attribute use's {value
25907 	    * constraint}value, if it is present and fixed."
25908 	    *
25909 	    * VAL TODO: The requirement for the *canonical* value
25910 	    * will be removed in XML Schema 1.1.
25911 	    */
25912 	    /*
25913 	    * SPEC Attribute Locally Valid (cvc-attribute)
25914 	    * (4) "The item's *actual* value must match the *value* of
25915 	    * the {value constraint}, if it is present and fixed."
25916 	    */
25917 	    if (iattr->val == NULL) {
25918 		/* VAL TODO: A value was not precomputed. */
25919 		TODO
25920 		goto eval_idcs;
25921 	    }
25922 	    if ((iattr->use != NULL) &&
25923 		(iattr->use->defValue != NULL)) {
25924 		if (iattr->use->defVal == NULL) {
25925 		    /* VAL TODO: A default value was not precomputed. */
25926 		    TODO
25927 		    goto eval_idcs;
25928 		}
25929 		iattr->vcValue = iattr->use->defValue;
25930 		/*
25931 		if (xmlSchemaCompareValuesWhtsp(attr->val,
25932 		    (xmlSchemaWhitespaceValueType) ws,
25933 		    attr->use->defVal,
25934 		    (xmlSchemaWhitespaceValueType) ws) != 0) {
25935 		*/
25936 		if (! xmlSchemaAreValuesEqual(iattr->val, iattr->use->defVal))
25937 		    iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25938 	    } else {
25939 		if (iattr->decl->defVal == NULL) {
25940 		    /* VAL TODO: A default value was not precomputed. */
25941 		    TODO
25942 		    goto eval_idcs;
25943 		}
25944 		iattr->vcValue = iattr->decl->defValue;
25945 		/*
25946 		if (xmlSchemaCompareValuesWhtsp(attr->val,
25947 		    (xmlSchemaWhitespaceValueType) ws,
25948 		    attrDecl->defVal,
25949 		    (xmlSchemaWhitespaceValueType) ws) != 0) {
25950 		*/
25951 		if (! xmlSchemaAreValuesEqual(iattr->val, iattr->decl->defVal))
25952 		    iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25953 	    }
25954 	    /*
25955 	    * [validity] = "valid"
25956 	    */
25957 	}
25958 eval_idcs:
25959 	/*
25960 	* Evaluate IDCs.
25961 	*/
25962 	if (xpathRes) {
25963 	    if (xmlSchemaXPathProcessHistory(vctxt,
25964 		vctxt->depth +1) == -1) {
25965 		VERROR_INT("xmlSchemaVAttributesComplex",
25966 		    "calling xmlSchemaXPathEvaluate()");
25967 		goto internal_error;
25968 	    }
25969 	} else if (vctxt->xpathStates != NULL)
25970 	    xmlSchemaXPathPop(vctxt);
25971     }
25972 
25973     /*
25974     * Report errors.
25975     */
25976     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25977 	iattr = vctxt->attrInfos[i];
25978 	if ((iattr->state == XML_SCHEMAS_ATTR_META) ||
25979 	    (iattr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
25980 	    (iattr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
25981 	    (iattr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
25982 	    continue;
25983 	ACTIVATE_ATTRIBUTE(iattr);
25984 	switch (iattr->state) {
25985 	    case XML_SCHEMAS_ATTR_ERR_MISSING: {
25986 		    xmlChar *str = NULL;
25987 		    ACTIVATE_ELEM;
25988 		    xmlSchemaCustomErr(ACTXT_CAST vctxt,
25989 			XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
25990 			"The attribute '%s' is required but missing",
25991 			xmlSchemaFormatQName(&str,
25992 			    iattr->decl->targetNamespace,
25993 			    iattr->decl->name),
25994 			NULL);
25995 		    FREE_AND_NULL(str)
25996 		    break;
25997 		}
25998 	    case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
25999 		VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
26000 		    "The type definition is absent");
26001 		break;
26002 	    case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
26003 		xmlSchemaCustomErr(ACTXT_CAST vctxt,
26004 		    XML_SCHEMAV_CVC_AU, NULL, NULL,
26005 		    "The value '%s' does not match the fixed "
26006 		    "value constraint '%s'",
26007 		    iattr->value, iattr->vcValue);
26008 		break;
26009 	    case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
26010 		VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
26011 		    "No matching global attribute declaration available, but "
26012 		    "demanded by the strict wildcard");
26013 		break;
26014 	    case XML_SCHEMAS_ATTR_UNKNOWN:
26015 		if (iattr->metaType)
26016 		    break;
26017 		/*
26018 		* MAYBE VAL TODO: One might report different error messages
26019 		* for the following errors.
26020 		*/
26021 		if (type->attributeWildcard == NULL) {
26022 		    xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
26023 			XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, iattr, NULL);
26024 		} else {
26025 		    xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
26026 			XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, iattr, NULL);
26027 		}
26028 		break;
26029 	    default:
26030 		break;
26031 	}
26032     }
26033 
26034     ACTIVATE_ELEM;
26035     return (0);
26036 internal_error:
26037     ACTIVATE_ELEM;
26038     return (-1);
26039 }
26040 
26041 static int
xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,int * skip)26042 xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
26043 			      int *skip)
26044 {
26045     xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
26046     /*
26047     * The namespace of the element was already identified to be
26048     * matching the wildcard.
26049     */
26050     if ((skip == NULL) || (wild == NULL) ||
26051 	(wild->type != XML_SCHEMA_TYPE_ANY)) {
26052 	VERROR_INT("xmlSchemaValidateElemWildcard",
26053 	    "bad arguments");
26054 	return (-1);
26055     }
26056     *skip = 0;
26057     if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
26058 	/*
26059 	* URGENT VAL TODO: Either we need to position the stream to the
26060 	* next sibling, or walk the whole subtree.
26061 	*/
26062 	*skip = 1;
26063 	return (0);
26064     }
26065     {
26066 	xmlSchemaElementPtr decl = NULL;
26067 
26068 	decl = xmlSchemaGetElem(vctxt->schema,
26069 	    vctxt->inode->localName, vctxt->inode->nsName);
26070 	if (decl != NULL) {
26071 	    vctxt->inode->decl = decl;
26072 	    return (0);
26073 	}
26074     }
26075     if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
26076 	/* VAL TODO: Change to proper error code. */
26077 	VERROR(XML_SCHEMAV_CVC_ELT_1, NULL, /* WXS_BASIC_CAST wild */
26078 	    "No matching global element declaration available, but "
26079 	    "demanded by the strict wildcard");
26080 	return (vctxt->err);
26081     }
26082     if (vctxt->nbAttrInfos != 0) {
26083 	xmlSchemaAttrInfoPtr iattr;
26084 	/*
26085 	* SPEC Validation Rule: Schema-Validity Assessment (Element)
26086 	* (1.2.1.2.1) - (1.2.1.2.3 )
26087 	*
26088 	* Use the xsi:type attribute for the type definition.
26089 	*/
26090 	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
26091 	    XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
26092 	if (iattr != NULL) {
26093 	    if (xmlSchemaProcessXSIType(vctxt, iattr,
26094 		&(vctxt->inode->typeDef), NULL) == -1) {
26095 		VERROR_INT("xmlSchemaValidateElemWildcard",
26096 		    "calling xmlSchemaProcessXSIType() to "
26097 		    "process the attribute 'xsi:nil'");
26098 		return (-1);
26099 	    }
26100 	    /*
26101 	    * Don't return an error on purpose.
26102 	    */
26103 	    return (0);
26104 	}
26105     }
26106     /*
26107     * SPEC Validation Rule: Schema-Validity Assessment (Element)
26108     *
26109     * Fallback to "anyType".
26110     */
26111     vctxt->inode->typeDef =
26112 	xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
26113     return (0);
26114 }
26115 
26116 /*
26117 * xmlSchemaCheckCOSValidDefault:
26118 *
26119 * This will be called if: not nilled, no content and a default/fixed
26120 * value is provided.
26121 */
26122 
26123 static int
xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,const xmlChar * value,xmlSchemaValPtr * val)26124 xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
26125 			      const xmlChar *value,
26126 			      xmlSchemaValPtr *val)
26127 {
26128     int ret = 0;
26129     xmlSchemaNodeInfoPtr inode = vctxt->inode;
26130 
26131     /*
26132     * cos-valid-default:
26133     * Schema Component Constraint: Element Default Valid (Immediate)
26134     * For a string to be a valid default with respect to a type
26135     * definition the appropriate case among the following must be true:
26136     */
26137     if WXS_IS_COMPLEX(inode->typeDef) {
26138 	/*
26139 	* Complex type.
26140 	*
26141 	* SPEC (2.1) "its {content type} must be a simple type definition
26142 	* or mixed."
26143 	* SPEC (2.2.2) "If the {content type} is mixed, then the {content
26144 	* type}'s particle must be `emptiable` as defined by
26145 	* Particle Emptiable ($3.9.6)."
26146 	*/
26147 	if ((! WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) &&
26148 	    ((! WXS_HAS_MIXED_CONTENT(inode->typeDef)) ||
26149 	     (! WXS_EMPTIABLE(inode->typeDef)))) {
26150 	    ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
26151 	    /* NOTE that this covers (2.2.2) as well. */
26152 	    VERROR(ret, NULL,
26153 		"For a string to be a valid default, the type definition "
26154 		"must be a simple type or a complex type with simple content "
26155 		"or mixed content and a particle emptiable");
26156 	    return(ret);
26157 	}
26158     }
26159     /*
26160     * 1 If the type definition is a simple type definition, then the string
26161     * must be `valid` with respect to that definition as defined by String
26162     * Valid ($3.14.4).
26163     *
26164     * AND
26165     *
26166     * 2.2.1 If the {content type} is a simple type definition, then the
26167     * string must be `valid` with respect to that simple type definition
26168     * as defined by String Valid ($3.14.4).
26169     */
26170     if (WXS_IS_SIMPLE(inode->typeDef)) {
26171 
26172 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
26173 	    NULL, inode->typeDef, value, val, 1, 1, 0);
26174 
26175     } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26176 
26177 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
26178 	    NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
26179     }
26180     if (ret < 0) {
26181 	VERROR_INT("xmlSchemaCheckCOSValidDefault",
26182 	    "calling xmlSchemaVCheckCVCSimpleType()");
26183     }
26184     return (ret);
26185 }
26186 
26187 static void
xmlSchemaVContentModelCallback(xmlRegExecCtxtPtr exec ATTRIBUTE_UNUSED,const xmlChar * name ATTRIBUTE_UNUSED,void * transdata,void * inputdata)26188 xmlSchemaVContentModelCallback(xmlRegExecCtxtPtr exec ATTRIBUTE_UNUSED,
26189 			       const xmlChar * name ATTRIBUTE_UNUSED,
26190 			       void *transdata, void *inputdata)
26191 {
26192     xmlSchemaElementPtr item = (xmlSchemaElementPtr) transdata;
26193     xmlSchemaNodeInfoPtr inode = (xmlSchemaNodeInfoPtr) inputdata;
26194     inode->decl = item;
26195 #ifdef DEBUG_CONTENT
26196     {
26197 	xmlChar *str = NULL;
26198 
26199 	if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
26200 	    xmlGenericError(xmlGenericErrorContext,
26201 		"AUTOMATON callback for '%s' [declaration]\n",
26202 		xmlSchemaFormatQName(&str,
26203 		inode->localName, inode->nsName));
26204 	} else {
26205 	    xmlGenericError(xmlGenericErrorContext,
26206 		    "AUTOMATON callback for '%s' [wildcard]\n",
26207 		    xmlSchemaFormatQName(&str,
26208 		    inode->localName, inode->nsName));
26209 
26210 	}
26211 	FREE_AND_NULL(str)
26212     }
26213 #endif
26214 }
26215 
26216 static int
xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)26217 xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
26218 {
26219     vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
26220     if (vctxt->inode == NULL) {
26221 	VERROR_INT("xmlSchemaValidatorPushElem",
26222 	    "calling xmlSchemaGetFreshElemInfo()");
26223 	return (-1);
26224     }
26225     vctxt->nbAttrInfos = 0;
26226     return (0);
26227 }
26228 
26229 static int
xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,xmlSchemaNodeInfoPtr inode,xmlSchemaTypePtr type,const xmlChar * value)26230 xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
26231 			     xmlSchemaNodeInfoPtr inode,
26232 			     xmlSchemaTypePtr type,
26233 			     const xmlChar *value)
26234 {
26235     if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
26236 	return (xmlSchemaVCheckCVCSimpleType(
26237 	    ACTXT_CAST vctxt, NULL,
26238 	    type, value, &(inode->val), 1, 1, 0));
26239     else
26240 	return (xmlSchemaVCheckCVCSimpleType(
26241 	    ACTXT_CAST vctxt, NULL,
26242 	    type, value, NULL, 1, 0, 0));
26243 }
26244 
26245 
26246 
26247 /*
26248 * Process END of element.
26249 */
26250 static int
xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)26251 xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
26252 {
26253     int ret = 0;
26254     xmlSchemaNodeInfoPtr inode = vctxt->inode;
26255 
26256     if (vctxt->nbAttrInfos != 0)
26257 	xmlSchemaClearAttrInfos(vctxt);
26258     if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
26259 	/*
26260 	* This element was not expected;
26261 	* we will not validate child elements of broken parents.
26262 	* Skip validation of all content of the parent.
26263 	*/
26264 	vctxt->skipDepth = vctxt->depth -1;
26265 	goto end_elem;
26266     }
26267     if ((inode->typeDef == NULL) ||
26268 	(inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
26269 	/*
26270 	* 1. the type definition might be missing if the element was
26271 	*    error prone
26272 	* 2. it might be abstract.
26273 	*/
26274 	goto end_elem;
26275     }
26276     /*
26277     * Check the content model.
26278     */
26279     if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
26280 	(inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
26281 
26282 	/*
26283 	* Workaround for "anyType".
26284 	*/
26285 	if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
26286 	    goto character_content;
26287 
26288 	if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
26289 	    xmlChar *values[10];
26290 	    int terminal, nbval = 10, nbneg;
26291 
26292 	    if (inode->regexCtxt == NULL) {
26293 		/*
26294 		* Create the regex context.
26295 		*/
26296 		inode->regexCtxt =
26297 		    xmlRegNewExecCtxt(inode->typeDef->contModel,
26298 		    xmlSchemaVContentModelCallback, vctxt);
26299 		if (inode->regexCtxt == NULL) {
26300 		    VERROR_INT("xmlSchemaValidatorPopElem",
26301 			"failed to create a regex context");
26302 		    goto internal_error;
26303 		}
26304 #ifdef DEBUG_AUTOMATA
26305 		xmlGenericError(xmlGenericErrorContext,
26306 		    "AUTOMATON create on '%s'\n", inode->localName);
26307 #endif
26308 	    }
26309 
26310 	    /*
26311 	     * Do not check further content if the node has been nilled
26312 	     */
26313 	    if (INODE_NILLED(inode)) {
26314 		ret = 0;
26315 #ifdef DEBUG_AUTOMATA
26316 		xmlGenericError(xmlGenericErrorContext,
26317 		    "AUTOMATON succeeded on nilled '%s'\n",
26318 		    inode->localName);
26319 #endif
26320                 goto skip_nilled;
26321 	    }
26322 
26323 	    /*
26324 	    * Get hold of the still expected content, since a further
26325 	    * call to xmlRegExecPushString() will lose this information.
26326 	    */
26327 	    xmlRegExecNextValues(inode->regexCtxt,
26328 		&nbval, &nbneg, &values[0], &terminal);
26329 	    ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
26330 	    if ((ret<0) || ((ret==0) && (!INODE_NILLED(inode)))) {
26331 		/*
26332 		* Still missing something.
26333 		*/
26334 		ret = 1;
26335 		inode->flags |=
26336 		    XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26337 		xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26338 		    XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
26339 		    "Missing child element(s)",
26340 		    nbval, nbneg, values);
26341 #ifdef DEBUG_AUTOMATA
26342 		xmlGenericError(xmlGenericErrorContext,
26343 		    "AUTOMATON missing ERROR on '%s'\n",
26344 		    inode->localName);
26345 #endif
26346 	    } else {
26347 		/*
26348 		* Content model is satisfied.
26349 		*/
26350 		ret = 0;
26351 #ifdef DEBUG_AUTOMATA
26352 		xmlGenericError(xmlGenericErrorContext,
26353 		    "AUTOMATON succeeded on '%s'\n",
26354 		    inode->localName);
26355 #endif
26356 	    }
26357 
26358 	}
26359     }
26360 
26361 skip_nilled:
26362 
26363     if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
26364 	goto end_elem;
26365 
26366 character_content:
26367 
26368     if (vctxt->value != NULL) {
26369 	xmlSchemaFreeValue(vctxt->value);
26370 	vctxt->value = NULL;
26371     }
26372     /*
26373     * Check character content.
26374     */
26375     if (inode->decl == NULL) {
26376 	/*
26377 	* Speedup if no declaration exists.
26378 	*/
26379 	if (WXS_IS_SIMPLE(inode->typeDef)) {
26380 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26381 		inode, inode->typeDef, inode->value);
26382 	} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26383 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26384 		inode, inode->typeDef->contentTypeDef,
26385 		inode->value);
26386 	}
26387 	if (ret < 0) {
26388 	    VERROR_INT("xmlSchemaValidatorPopElem",
26389 		"calling xmlSchemaVCheckCVCSimpleType()");
26390 	    goto internal_error;
26391 	}
26392 	goto end_elem;
26393     }
26394     /*
26395     * cvc-elt (3.3.4) : 5
26396     * The appropriate case among the following must be true:
26397     */
26398     /*
26399     * cvc-elt (3.3.4) : 5.1
26400     * If the declaration has a {value constraint},
26401     * the item has neither element nor character [children] and
26402     * clause 3.2 has not applied, then all of the following must be true:
26403     */
26404     if ((inode->decl->value != NULL) &&
26405 	(inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
26406 	(! INODE_NILLED(inode))) {
26407 	/*
26408 	* cvc-elt (3.3.4) : 5.1.1
26409 	* If the `actual type definition` is a `local type definition`
26410 	* then the canonical lexical representation of the {value constraint}
26411 	* value must be a valid default for the `actual type definition` as
26412 	* defined in Element Default Valid (Immediate) ($3.3.6).
26413 	*/
26414 	/*
26415 	* NOTE: 'local' above means types acquired by xsi:type.
26416 	* NOTE: Although the *canonical* value is stated, it is not
26417 	* relevant if canonical or not. Additionally XML Schema 1.1
26418 	* will removed this requirement as well.
26419 	*/
26420 	if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
26421 
26422 	    ret = xmlSchemaCheckCOSValidDefault(vctxt,
26423 		inode->decl->value, &(inode->val));
26424 	    if (ret != 0) {
26425 		if (ret < 0) {
26426 		    VERROR_INT("xmlSchemaValidatorPopElem",
26427 			"calling xmlSchemaCheckCOSValidDefault()");
26428 		    goto internal_error;
26429 		}
26430 		goto end_elem;
26431 	    }
26432 	    /*
26433 	    * Stop here, to avoid redundant validation of the value
26434 	    * (see following).
26435 	    */
26436 	    goto default_psvi;
26437 	}
26438 	/*
26439 	* cvc-elt (3.3.4) : 5.1.2
26440 	* The element information item with the canonical lexical
26441 	* representation of the {value constraint} value used as its
26442 	* `normalized value` must be `valid` with respect to the
26443 	* `actual type definition` as defined by Element Locally Valid (Type)
26444 	* ($3.3.4).
26445 	*/
26446 	if (WXS_IS_SIMPLE(inode->typeDef)) {
26447 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26448 		inode, inode->typeDef, inode->decl->value);
26449 	} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26450 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26451 		inode, inode->typeDef->contentTypeDef,
26452 		inode->decl->value);
26453 	}
26454 	if (ret != 0) {
26455 	    if (ret < 0) {
26456 		VERROR_INT("xmlSchemaValidatorPopElem",
26457 		    "calling xmlSchemaVCheckCVCSimpleType()");
26458 		goto internal_error;
26459 	    }
26460 	    goto end_elem;
26461 	}
26462 
26463 default_psvi:
26464 	/*
26465 	* PSVI: Create a text node on the instance element.
26466 	*/
26467 	if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
26468 	    (inode->node != NULL)) {
26469 	    xmlNodePtr textChild;
26470 	    xmlChar *normValue;
26471 	    /*
26472 	    * VAL TODO: Normalize the value.
26473 	    */
26474 	    normValue = xmlSchemaNormalizeValue(inode->typeDef,
26475 		inode->decl->value);
26476 	    if (normValue != NULL) {
26477 		textChild = xmlNewText(BAD_CAST normValue);
26478 		xmlFree(normValue);
26479 	    } else
26480 		textChild = xmlNewText(inode->decl->value);
26481 	    if (textChild == NULL) {
26482 		VERROR_INT("xmlSchemaValidatorPopElem",
26483 		    "calling xmlNewText()");
26484 		goto internal_error;
26485 	    } else
26486 		xmlAddChild(inode->node, textChild);
26487 	}
26488 
26489     } else if (! INODE_NILLED(inode)) {
26490 	/*
26491 	* 5.2.1 The element information item must be `valid` with respect
26492 	* to the `actual type definition` as defined by Element Locally
26493 	* Valid (Type) ($3.3.4).
26494 	*/
26495 	if (WXS_IS_SIMPLE(inode->typeDef)) {
26496 	     /*
26497 	    * SPEC (cvc-type) (3.1)
26498 	    * "If the type definition is a simple type definition, ..."
26499 	    * (3.1.3) "If clause 3.2 of Element Locally Valid
26500 	    * (Element) ($3.3.4) did not apply, then the `normalized value`
26501 	    * must be `valid` with respect to the type definition as defined
26502 	    * by String Valid ($3.14.4).
26503 	    */
26504 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26505 		    inode, inode->typeDef, inode->value);
26506 	} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26507 	    /*
26508 	    * SPEC (cvc-type) (3.2) "If the type definition is a complex type
26509 	    * definition, then the element information item must be
26510 	    * `valid` with respect to the type definition as per
26511 	    * Element Locally Valid (Complex Type) ($3.4.4);"
26512 	    *
26513 	    * SPEC (cvc-complex-type) (2.2)
26514 	    * "If the {content type} is a simple type definition, ...
26515 	    * the `normalized value` of the element information item is
26516 	    * `valid` with respect to that simple type definition as
26517 	    * defined by String Valid ($3.14.4)."
26518 	    */
26519 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26520 		inode, inode->typeDef->contentTypeDef, inode->value);
26521 	}
26522 	if (ret != 0) {
26523 	    if (ret < 0) {
26524 		VERROR_INT("xmlSchemaValidatorPopElem",
26525 		    "calling xmlSchemaVCheckCVCSimpleType()");
26526 		goto internal_error;
26527 	    }
26528 	    goto end_elem;
26529 	}
26530 	/*
26531 	* 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
26532 	* not applied, all of the following must be true:
26533 	*/
26534 	if ((inode->decl->value != NULL) &&
26535 	    (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
26536 
26537 	    /*
26538 	    * TODO: We will need a computed value, when comparison is
26539 	    * done on computed values.
26540 	    */
26541 	    /*
26542 	    * 5.2.2.1 The element information item must have no element
26543 	    * information item [children].
26544 	    */
26545 	    if (inode->flags &
26546 		    XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
26547 		ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
26548 		VERROR(ret, NULL,
26549 		    "The content must not contain element nodes since "
26550 		    "there is a fixed value constraint");
26551 		goto end_elem;
26552 	    } else {
26553 		/*
26554 		* 5.2.2.2 The appropriate case among the following must
26555 		* be true:
26556 		*/
26557 		if (WXS_HAS_MIXED_CONTENT(inode->typeDef)) {
26558 		    /*
26559 		    * 5.2.2.2.1 If the {content type} of the `actual type
26560 		    * definition` is mixed, then the *initial value* of the
26561 		    * item must match the canonical lexical representation
26562 		    * of the {value constraint} value.
26563 		    *
26564 		    * ... the *initial value* of an element information
26565 		    * item is the string composed of, in order, the
26566 		    * [character code] of each character information item in
26567 		    * the [children] of that element information item.
26568 		    */
26569 		    if (! xmlStrEqual(inode->value, inode->decl->value)){
26570 			/*
26571 			* VAL TODO: Report invalid & expected values as well.
26572 			* VAL TODO: Implement the canonical stuff.
26573 			*/
26574 			ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
26575 			xmlSchemaCustomErr(ACTXT_CAST vctxt,
26576 			    ret, NULL, NULL,
26577 			    "The initial value '%s' does not match the fixed "
26578 			    "value constraint '%s'",
26579 			    inode->value, inode->decl->value);
26580 			goto end_elem;
26581 		    }
26582 		} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26583 		    /*
26584 		    * 5.2.2.2.2 If the {content type} of the `actual type
26585 		    * definition` is a simple type definition, then the
26586 		    * *actual value* of the item must match the canonical
26587 		    * lexical representation of the {value constraint} value.
26588 		    */
26589 		    /*
26590 		    * VAL TODO: *actual value* is the normalized value, impl.
26591 		    *           this.
26592 		    * VAL TODO: Report invalid & expected values as well.
26593 		    * VAL TODO: Implement a comparison with the computed values.
26594 		    */
26595 		    if (! xmlStrEqual(inode->value,
26596 			    inode->decl->value)) {
26597 			ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
26598 			xmlSchemaCustomErr(ACTXT_CAST vctxt,
26599 			    ret, NULL, NULL,
26600 			    "The actual value '%s' does not match the fixed "
26601 			    "value constraint '%s'",
26602 			    inode->value,
26603 			    inode->decl->value);
26604 			goto end_elem;
26605 		    }
26606 		}
26607 	    }
26608 	}
26609     }
26610 
26611 end_elem:
26612     if (vctxt->depth < 0) {
26613 	/* TODO: raise error? */
26614 	return (0);
26615     }
26616     if (vctxt->depth == vctxt->skipDepth)
26617 	vctxt->skipDepth = -1;
26618     /*
26619     * Evaluate the history of XPath state objects.
26620     */
26621     if (inode->appliedXPath &&
26622 	(xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1))
26623 	goto internal_error;
26624     /*
26625     * MAYBE TODO:
26626     * SPEC (6) "The element information item must be `valid` with
26627     * respect to each of the {identity-constraint definitions} as per
26628     * Identity-constraint Satisfied ($3.11.4)."
26629     */
26630     /*
26631     * PSVI TODO: If we expose IDC node-tables via PSVI then the tables
26632     *   need to be built in any case.
26633     *   We will currently build IDC node-tables and bubble them only if
26634     *   keyrefs do exist.
26635     */
26636 
26637     /*
26638     * Add the current IDC target-nodes to the IDC node-tables.
26639     */
26640     if ((inode->idcMatchers != NULL) &&
26641 	(vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26642     {
26643 	if (xmlSchemaIDCFillNodeTables(vctxt, inode) == -1)
26644 	    goto internal_error;
26645     }
26646     /*
26647     * Validate IDC keyrefs.
26648     */
26649     if (vctxt->inode->hasKeyrefs)
26650 	if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
26651 	    goto internal_error;
26652     /*
26653     * Merge/free the IDC table.
26654     */
26655     if (inode->idcTable != NULL) {
26656 #ifdef DEBUG_IDC_NODE_TABLE
26657 	xmlSchemaDebugDumpIDCTable(stdout,
26658 	    inode->nsName,
26659 	    inode->localName,
26660 	    inode->idcTable);
26661 #endif
26662 	if ((vctxt->depth > 0) &&
26663 	    (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26664 	{
26665 	    /*
26666 	    * Merge the IDC node table with the table of the parent node.
26667 	    */
26668 	    if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
26669 		goto internal_error;
26670 	}
26671     }
26672     /*
26673     * Clear the current ielem.
26674     * VAL TODO: Don't free the PSVI IDC tables if they are
26675     * requested for the PSVI.
26676     */
26677     xmlSchemaClearElemInfo(vctxt, inode);
26678     /*
26679     * Skip further processing if we are on the validation root.
26680     */
26681     if (vctxt->depth == 0) {
26682 	vctxt->depth--;
26683 	vctxt->inode = NULL;
26684 	return (0);
26685     }
26686     /*
26687     * Reset the keyrefDepth if needed.
26688     */
26689     if (vctxt->aidcs != NULL) {
26690 	xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
26691 	do {
26692 	    if (aidc->keyrefDepth == vctxt->depth) {
26693 		/*
26694 		* A 'keyrefDepth' of a key/unique IDC matches the current
26695 		* depth, this means that we are leaving the scope of the
26696 		* top-most keyref IDC which refers to this IDC.
26697 		*/
26698 		aidc->keyrefDepth = -1;
26699 	    }
26700 	    aidc = aidc->next;
26701 	} while (aidc != NULL);
26702     }
26703     vctxt->depth--;
26704     vctxt->inode = vctxt->elemInfos[vctxt->depth];
26705     /*
26706     * VAL TODO: 7 If the element information item is the `validation root`, it must be
26707     * `valid` per Validation Root Valid (ID/IDREF) ($3.3.4).
26708     */
26709     return (ret);
26710 
26711 internal_error:
26712     vctxt->err = -1;
26713     return (-1);
26714 }
26715 
26716 /*
26717 * 3.4.4 Complex Type Definition Validation Rules
26718 * Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
26719 */
26720 static int
xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)26721 xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
26722 {
26723     xmlSchemaNodeInfoPtr pielem;
26724     xmlSchemaTypePtr ptype;
26725     int ret = 0;
26726 
26727     if (vctxt->depth <= 0) {
26728 	VERROR_INT("xmlSchemaValidateChildElem",
26729 	    "not intended for the validation root");
26730 	return (-1);
26731     }
26732     pielem = vctxt->elemInfos[vctxt->depth -1];
26733     if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26734 	pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26735     /*
26736     * Handle 'nilled' elements.
26737     */
26738     if (INODE_NILLED(pielem)) {
26739 	/*
26740 	* SPEC (cvc-elt) (3.3.4) : (3.2.1)
26741 	*/
26742 	ACTIVATE_PARENT_ELEM;
26743 	ret = XML_SCHEMAV_CVC_ELT_3_2_1;
26744 	VERROR(ret, NULL,
26745 	    "Neither character nor element content is allowed, "
26746 	    "because the element was 'nilled'");
26747 	ACTIVATE_ELEM;
26748 	goto unexpected_elem;
26749     }
26750 
26751     ptype = pielem->typeDef;
26752 
26753     if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
26754 	/*
26755 	* Workaround for "anyType": we have currently no content model
26756 	* assigned for "anyType", so handle it explicitly.
26757 	* "anyType" has an unbounded, lax "any" wildcard.
26758 	*/
26759 	vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26760 	    vctxt->inode->localName,
26761 	    vctxt->inode->nsName);
26762 
26763 	if (vctxt->inode->decl == NULL) {
26764 	    xmlSchemaAttrInfoPtr iattr;
26765 	    /*
26766 	    * Process "xsi:type".
26767 	    * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
26768 	    */
26769 	    iattr = xmlSchemaGetMetaAttrInfo(vctxt,
26770 		XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
26771 	    if (iattr != NULL) {
26772 		ret = xmlSchemaProcessXSIType(vctxt, iattr,
26773 		    &(vctxt->inode->typeDef), NULL);
26774 		if (ret != 0) {
26775 		    if (ret == -1) {
26776 			VERROR_INT("xmlSchemaValidateChildElem",
26777 			    "calling xmlSchemaProcessXSIType() to "
26778 			    "process the attribute 'xsi:nil'");
26779 			return (-1);
26780 		    }
26781 		    return (ret);
26782 		}
26783 	    } else {
26784 		 /*
26785 		 * Fallback to "anyType".
26786 		 *
26787 		 * SPEC (cvc-assess-elt)
26788 		 * "If the item cannot be `strictly assessed`, [...]
26789 		 * an element information item's schema validity may be laxly
26790 		 * assessed if its `context-determined declaration` is not
26791 		 * skip by `validating` with respect to the `ur-type
26792 		 * definition` as per Element Locally Valid (Type) ($3.3.4)."
26793 		*/
26794 		vctxt->inode->typeDef =
26795 		    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
26796 	    }
26797 	}
26798 	return (0);
26799     }
26800 
26801     switch (ptype->contentType) {
26802 	case XML_SCHEMA_CONTENT_EMPTY:
26803 	    /*
26804 	    * SPEC (2.1) "If the {content type} is empty, then the
26805 	    * element information item has no character or element
26806 	    * information item [children]."
26807 	    */
26808 	    ACTIVATE_PARENT_ELEM
26809 	    ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
26810 	    VERROR(ret, NULL,
26811 		"Element content is not allowed, "
26812 		"because the content type is empty");
26813 	    ACTIVATE_ELEM
26814 	    goto unexpected_elem;
26815 	    break;
26816 
26817 	case XML_SCHEMA_CONTENT_MIXED:
26818         case XML_SCHEMA_CONTENT_ELEMENTS: {
26819 	    xmlRegExecCtxtPtr regexCtxt;
26820 	    xmlChar *values[10];
26821 	    int terminal, nbval = 10, nbneg;
26822 
26823 	    /* VAL TODO: Optimized "anyType" validation.*/
26824 
26825 	    if (ptype->contModel == NULL) {
26826 		VERROR_INT("xmlSchemaValidateChildElem",
26827 		    "type has elem content but no content model");
26828 		return (-1);
26829 	    }
26830 	    /*
26831 	    * Safety belt for evaluation if the cont. model was already
26832 	    * examined to be invalid.
26833 	    */
26834 	    if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
26835 		VERROR_INT("xmlSchemaValidateChildElem",
26836 		    "validating elem, but elem content is already invalid");
26837 		return (-1);
26838 	    }
26839 
26840 	    regexCtxt = pielem->regexCtxt;
26841 	    if (regexCtxt == NULL) {
26842 		/*
26843 		* Create the regex context.
26844 		*/
26845 		regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
26846 		    xmlSchemaVContentModelCallback, vctxt);
26847 		if (regexCtxt == NULL) {
26848 		    VERROR_INT("xmlSchemaValidateChildElem",
26849 			"failed to create a regex context");
26850 		    return (-1);
26851 		}
26852 		pielem->regexCtxt = regexCtxt;
26853 #ifdef DEBUG_AUTOMATA
26854 		xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
26855 		    pielem->localName);
26856 #endif
26857 	    }
26858 
26859 	    /*
26860 	    * SPEC (2.4) "If the {content type} is element-only or mixed,
26861 	    * then the sequence of the element information item's
26862 	    * element information item [children], if any, taken in
26863 	    * order, is `valid` with respect to the {content type}'s
26864 	    * particle, as defined in Element Sequence Locally Valid
26865 	    * (Particle) ($3.9.4)."
26866 	    */
26867 	    ret = xmlRegExecPushString2(regexCtxt,
26868 		vctxt->inode->localName,
26869 		vctxt->inode->nsName,
26870 		vctxt->inode);
26871 #ifdef DEBUG_AUTOMATA
26872 	    if (ret < 0)
26873 		xmlGenericError(xmlGenericErrorContext,
26874 		"AUTOMATON push ERROR for '%s' on '%s'\n",
26875 		vctxt->inode->localName, pielem->localName);
26876 	    else
26877 		xmlGenericError(xmlGenericErrorContext,
26878 		"AUTOMATON push OK for '%s' on '%s'\n",
26879 		vctxt->inode->localName, pielem->localName);
26880 #endif
26881 	    if (vctxt->err == XML_SCHEMAV_INTERNAL) {
26882 		VERROR_INT("xmlSchemaValidateChildElem",
26883 		    "calling xmlRegExecPushString2()");
26884 		return (-1);
26885 	    }
26886 	    if (ret < 0) {
26887 		xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
26888 		    &values[0], &terminal);
26889 		xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26890 		    XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
26891 		    "This element is not expected",
26892 		    nbval, nbneg, values);
26893 		ret = vctxt->err;
26894 		goto unexpected_elem;
26895 	    } else
26896 		ret = 0;
26897 	}
26898 	    break;
26899 	case XML_SCHEMA_CONTENT_SIMPLE:
26900 	case XML_SCHEMA_CONTENT_BASIC:
26901 	    ACTIVATE_PARENT_ELEM
26902 	    if (WXS_IS_COMPLEX(ptype)) {
26903 		/*
26904 		* SPEC (cvc-complex-type) (2.2)
26905 		* "If the {content type} is a simple type definition, then
26906 		* the element information item has no element information
26907 		* item [children], ..."
26908 		*/
26909 		ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
26910 		VERROR(ret, NULL, "Element content is not allowed, "
26911 		    "because the content type is a simple type definition");
26912 	    } else {
26913 		/*
26914 		* SPEC (cvc-type) (3.1.2) "The element information item must
26915 		* have no element information item [children]."
26916 		*/
26917 		ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
26918 		VERROR(ret, NULL, "Element content is not allowed, "
26919 		    "because the type definition is simple");
26920 	    }
26921 	    ACTIVATE_ELEM
26922 	    ret = vctxt->err;
26923 	    goto unexpected_elem;
26924 	    break;
26925 
26926 	default:
26927 	    break;
26928     }
26929     return (ret);
26930 unexpected_elem:
26931     /*
26932     * Pop this element and set the skipDepth to skip
26933     * all further content of the parent element.
26934     */
26935     vctxt->skipDepth = vctxt->depth;
26936     vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
26937     pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26938     return (ret);
26939 }
26940 
26941 #define XML_SCHEMA_PUSH_TEXT_PERSIST 1
26942 #define XML_SCHEMA_PUSH_TEXT_CREATED 2
26943 #define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
26944 
26945 static int
xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,int nodeType,const xmlChar * value,int len,int mode,int * consumed)26946 xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
26947 		  int nodeType, const xmlChar *value, int len,
26948 		  int mode, int *consumed)
26949 {
26950     /*
26951     * Unfortunately we have to duplicate the text sometimes.
26952     * OPTIMIZE: Maybe we could skip it, if:
26953     *   1. content type is simple
26954     *   2. whitespace is "collapse"
26955     *   3. it consists of whitespace only
26956     *
26957     * Process character content.
26958     */
26959     if (consumed != NULL)
26960 	*consumed = 0;
26961     if (INODE_NILLED(vctxt->inode)) {
26962 	/*
26963 	* SPEC cvc-elt (3.3.4 - 3.2.1)
26964 	* "The element information item must have no character or
26965 	* element information item [children]."
26966 	*/
26967 	VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
26968 	    "Neither character nor element content is allowed "
26969 	    "because the element is 'nilled'");
26970 	return (vctxt->err);
26971     }
26972     /*
26973     * SPEC (2.1) "If the {content type} is empty, then the
26974     * element information item has no character or element
26975     * information item [children]."
26976     */
26977     if (vctxt->inode->typeDef->contentType ==
26978 	    XML_SCHEMA_CONTENT_EMPTY) {
26979 	VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
26980 	    "Character content is not allowed, "
26981 	    "because the content type is empty");
26982 	return (vctxt->err);
26983     }
26984 
26985     if (vctxt->inode->typeDef->contentType ==
26986 	    XML_SCHEMA_CONTENT_ELEMENTS) {
26987 	if ((nodeType != XML_TEXT_NODE) ||
26988 	    (! xmlSchemaIsBlank((xmlChar *) value, len))) {
26989 	    /*
26990 	    * SPEC cvc-complex-type (2.3)
26991 	    * "If the {content type} is element-only, then the
26992 	    * element information item has no character information
26993 	    * item [children] other than those whose [character
26994 	    * code] is defined as a white space in [XML 1.0 (Second
26995 	    * Edition)]."
26996 	    */
26997 	    VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
26998 		"Character content other than whitespace is not allowed "
26999 		"because the content type is 'element-only'");
27000 	    return (vctxt->err);
27001 	}
27002 	return (0);
27003     }
27004 
27005     if ((value == NULL) || (value[0] == 0))
27006 	return (0);
27007     /*
27008     * Save the value.
27009     * NOTE that even if the content type is *mixed*, we need the
27010     * *initial value* for default/fixed value constraints.
27011     */
27012     if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
27013 	((vctxt->inode->decl == NULL) ||
27014 	(vctxt->inode->decl->value == NULL)))
27015 	return (0);
27016 
27017     if (vctxt->inode->value == NULL) {
27018 	/*
27019 	* Set the value.
27020 	*/
27021 	switch (mode) {
27022 	    case XML_SCHEMA_PUSH_TEXT_PERSIST:
27023 		/*
27024 		* When working on a tree.
27025 		*/
27026 		vctxt->inode->value = value;
27027 		break;
27028 	    case XML_SCHEMA_PUSH_TEXT_CREATED:
27029 		/*
27030 		* When working with the reader.
27031 		* The value will be freed by the element info.
27032 		*/
27033 		vctxt->inode->value = value;
27034 		if (consumed != NULL)
27035 		    *consumed = 1;
27036 		vctxt->inode->flags |=
27037 		    XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
27038 		break;
27039 	    case XML_SCHEMA_PUSH_TEXT_VOLATILE:
27040 		/*
27041 		* When working with SAX.
27042 		* The value will be freed by the element info.
27043 		*/
27044 		if (len != -1)
27045 		    vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
27046 		else
27047 		    vctxt->inode->value = BAD_CAST xmlStrdup(value);
27048 		vctxt->inode->flags |=
27049 		    XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
27050 		break;
27051 	    default:
27052 		break;
27053 	}
27054     } else {
27055 	if (len < 0)
27056 	    len = xmlStrlen(value);
27057 	/*
27058 	* Concat the value.
27059 	*/
27060 	if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
27061 	    vctxt->inode->value = BAD_CAST xmlStrncat(
27062 		(xmlChar *) vctxt->inode->value, value, len);
27063 	} else {
27064 	    vctxt->inode->value =
27065 		BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
27066 	    vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
27067 	}
27068     }
27069 
27070     return (0);
27071 }
27072 
27073 static int
xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)27074 xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
27075 {
27076     int ret = 0;
27077 
27078     if ((vctxt->skipDepth != -1) &&
27079 	(vctxt->depth >= vctxt->skipDepth)) {
27080 	VERROR_INT("xmlSchemaValidateElem",
27081 	    "in skip-state");
27082 	goto internal_error;
27083     }
27084     if (vctxt->xsiAssemble) {
27085 	/*
27086 	* We will stop validation if there was an error during
27087 	* dynamic schema construction.
27088 	* Note that we simply set @skipDepth to 0, this could
27089 	* mean that a streaming document via SAX would be
27090 	* still read to the end but it won't be validated any more.
27091 	* TODO: If we are sure how to stop the validation at once
27092 	*   for all input scenarios, then this should be changed to
27093 	*   instantly stop the validation.
27094 	*/
27095 	ret = xmlSchemaAssembleByXSI(vctxt);
27096 	if (ret != 0) {
27097 	    if (ret == -1)
27098 		goto internal_error;
27099 	    vctxt->skipDepth = 0;
27100 	    return(ret);
27101 	}
27102         /*
27103          * Augment the IDC definitions for the main schema and all imported ones
27104          * NOTE: main schema is the first in the imported list
27105          */
27106         xmlHashScan(vctxt->schema->schemasImports, xmlSchemaAugmentImportedIDC,
27107                     vctxt);
27108     }
27109     if (vctxt->depth > 0) {
27110 	/*
27111 	* Validate this element against the content model
27112 	* of the parent.
27113 	*/
27114 	ret = xmlSchemaValidateChildElem(vctxt);
27115 	if (ret != 0) {
27116 	    if (ret < 0) {
27117 		VERROR_INT("xmlSchemaValidateElem",
27118 		    "calling xmlSchemaStreamValidateChildElement()");
27119 		goto internal_error;
27120 	    }
27121 	    goto exit;
27122 	}
27123 	if (vctxt->depth == vctxt->skipDepth)
27124 	    goto exit;
27125 	if ((vctxt->inode->decl == NULL) &&
27126 	    (vctxt->inode->typeDef == NULL)) {
27127 	    VERROR_INT("xmlSchemaValidateElem",
27128 		"the child element was valid but neither the "
27129 		"declaration nor the type was set");
27130 	    goto internal_error;
27131 	}
27132     } else {
27133 	/*
27134 	* Get the declaration of the validation root.
27135 	*/
27136 	vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
27137 	    vctxt->inode->localName,
27138 	    vctxt->inode->nsName);
27139 	if (vctxt->inode->decl == NULL) {
27140 	    ret = XML_SCHEMAV_CVC_ELT_1;
27141 	    VERROR(ret, NULL,
27142 		"No matching global declaration available "
27143 		"for the validation root");
27144 	    goto exit;
27145 	}
27146     }
27147 
27148     if (vctxt->inode->decl == NULL)
27149 	goto type_validation;
27150 
27151     if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
27152 	int skip;
27153 	/*
27154 	* Wildcards.
27155 	*/
27156 	ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
27157 	if (ret != 0) {
27158 	    if (ret < 0) {
27159 		VERROR_INT("xmlSchemaValidateElem",
27160 		    "calling xmlSchemaValidateElemWildcard()");
27161 		goto internal_error;
27162 	    }
27163 	    goto exit;
27164 	}
27165 	if (skip) {
27166 	    vctxt->skipDepth = vctxt->depth;
27167 	    goto exit;
27168 	}
27169 	/*
27170 	* The declaration might be set by the wildcard validation,
27171 	* when the processContents is "lax" or "strict".
27172 	*/
27173 	if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
27174 	    /*
27175 	    * Clear the "decl" field to not confuse further processing.
27176 	    */
27177 	    vctxt->inode->decl = NULL;
27178 	    goto type_validation;
27179 	}
27180     }
27181     /*
27182     * Validate against the declaration.
27183     */
27184     ret = xmlSchemaValidateElemDecl(vctxt);
27185     if (ret != 0) {
27186 	if (ret < 0) {
27187 	    VERROR_INT("xmlSchemaValidateElem",
27188 		"calling xmlSchemaValidateElemDecl()");
27189 	    goto internal_error;
27190 	}
27191 	goto exit;
27192     }
27193     /*
27194     * Validate against the type definition.
27195     */
27196 type_validation:
27197 
27198     if (vctxt->inode->typeDef == NULL) {
27199 	vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
27200 	ret = XML_SCHEMAV_CVC_TYPE_1;
27201 	VERROR(ret, NULL,
27202 	    "The type definition is absent");
27203 	goto exit;
27204     }
27205     if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
27206 	vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
27207 	ret = XML_SCHEMAV_CVC_TYPE_2;
27208 	    VERROR(ret, NULL,
27209 	    "The type definition is abstract");
27210 	goto exit;
27211     }
27212     /*
27213     * Evaluate IDCs. Do it here, since new IDC matchers are registered
27214     * during validation against the declaration. This must be done
27215     * _before_ attribute validation.
27216     */
27217     if (vctxt->xpathStates != NULL) {
27218 	ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
27219 	vctxt->inode->appliedXPath = 1;
27220 	if (ret == -1) {
27221 	    VERROR_INT("xmlSchemaValidateElem",
27222 		"calling xmlSchemaXPathEvaluate()");
27223 	    goto internal_error;
27224 	}
27225     }
27226     /*
27227     * Validate attributes.
27228     */
27229     if (WXS_IS_COMPLEX(vctxt->inode->typeDef)) {
27230 	if ((vctxt->nbAttrInfos != 0) ||
27231 	    (vctxt->inode->typeDef->attrUses != NULL)) {
27232 
27233 	    ret = xmlSchemaVAttributesComplex(vctxt);
27234 	}
27235     } else if (vctxt->nbAttrInfos != 0) {
27236 
27237 	ret = xmlSchemaVAttributesSimple(vctxt);
27238     }
27239     /*
27240     * Clear registered attributes.
27241     */
27242     if (vctxt->nbAttrInfos != 0)
27243 	xmlSchemaClearAttrInfos(vctxt);
27244     if (ret == -1) {
27245 	VERROR_INT("xmlSchemaValidateElem",
27246 	    "calling attributes validation");
27247 	goto internal_error;
27248     }
27249     /*
27250     * Don't return an error if attributes are invalid on purpose.
27251     */
27252     ret = 0;
27253 
27254 exit:
27255     if (ret != 0)
27256 	vctxt->skipDepth = vctxt->depth;
27257     return (ret);
27258 internal_error:
27259     return (-1);
27260 }
27261 
27262 #ifdef XML_SCHEMA_READER_ENABLED
27263 static int
xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)27264 xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
27265 {
27266     const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
27267     int depth, nodeType, ret = 0, consumed;
27268     xmlSchemaNodeInfoPtr ielem;
27269 
27270     vctxt->depth = -1;
27271     ret = xmlTextReaderRead(vctxt->reader);
27272     /*
27273     * Move to the document element.
27274     */
27275     while (ret == 1) {
27276 	nodeType = xmlTextReaderNodeType(vctxt->reader);
27277 	if (nodeType == XML_ELEMENT_NODE)
27278 	    goto root_found;
27279 	ret = xmlTextReaderRead(vctxt->reader);
27280     }
27281     goto exit;
27282 
27283 root_found:
27284 
27285     do {
27286 	depth = xmlTextReaderDepth(vctxt->reader);
27287 	nodeType = xmlTextReaderNodeType(vctxt->reader);
27288 
27289 	if (nodeType == XML_ELEMENT_NODE) {
27290 
27291 	    vctxt->depth++;
27292 	    if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27293 		VERROR_INT("xmlSchemaVReaderWalk",
27294 		    "calling xmlSchemaValidatorPushElem()");
27295 		goto internal_error;
27296 	    }
27297 	    ielem = vctxt->inode;
27298 	    ielem->localName = xmlTextReaderLocalName(vctxt->reader);
27299 	    ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
27300 	    ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
27301 	    /*
27302 	    * Is the element empty?
27303 	    */
27304 	    ret = xmlTextReaderIsEmptyElement(vctxt->reader);
27305 	    if (ret == -1) {
27306 		VERROR_INT("xmlSchemaVReaderWalk",
27307 		    "calling xmlTextReaderIsEmptyElement()");
27308 		goto internal_error;
27309 	    }
27310 	    if (ret) {
27311 		ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27312 	    }
27313 	    /*
27314 	    * Register attributes.
27315 	    */
27316 	    vctxt->nbAttrInfos = 0;
27317 	    ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
27318 	    if (ret == -1) {
27319 		VERROR_INT("xmlSchemaVReaderWalk",
27320 		    "calling xmlTextReaderMoveToFirstAttribute()");
27321 		goto internal_error;
27322 	    }
27323 	    if (ret == 1) {
27324 		do {
27325 		    /*
27326 		    * VAL TODO: How do we know that the reader works on a
27327 		    * node tree, to be able to pass a node here?
27328 		    */
27329 		    if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
27330 			(const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
27331 			xmlTextReaderNamespaceUri(vctxt->reader), 1,
27332 			xmlTextReaderValue(vctxt->reader), 1) == -1) {
27333 
27334 			VERROR_INT("xmlSchemaVReaderWalk",
27335 			    "calling xmlSchemaValidatorPushAttribute()");
27336 			goto internal_error;
27337 		    }
27338 		    ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
27339 		    if (ret == -1) {
27340 			VERROR_INT("xmlSchemaVReaderWalk",
27341 			    "calling xmlTextReaderMoveToFirstAttribute()");
27342 			goto internal_error;
27343 		    }
27344 		} while (ret == 1);
27345 		/*
27346 		* Back to element position.
27347 		*/
27348 		ret = xmlTextReaderMoveToElement(vctxt->reader);
27349 		if (ret == -1) {
27350 		    VERROR_INT("xmlSchemaVReaderWalk",
27351 			"calling xmlTextReaderMoveToElement()");
27352 		    goto internal_error;
27353 		}
27354 	    }
27355 	    /*
27356 	    * Validate the element.
27357 	    */
27358 	    ret= xmlSchemaValidateElem(vctxt);
27359 	    if (ret != 0) {
27360 		if (ret == -1) {
27361 		    VERROR_INT("xmlSchemaVReaderWalk",
27362 			"calling xmlSchemaValidateElem()");
27363 		    goto internal_error;
27364 		}
27365 		goto exit;
27366 	    }
27367 	    if (vctxt->depth == vctxt->skipDepth) {
27368 		int curDepth;
27369 		/*
27370 		* Skip all content.
27371 		*/
27372 		if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
27373 		    ret = xmlTextReaderRead(vctxt->reader);
27374 		    curDepth = xmlTextReaderDepth(vctxt->reader);
27375 		    while ((ret == 1) && (curDepth != depth)) {
27376 			ret = xmlTextReaderRead(vctxt->reader);
27377 			curDepth = xmlTextReaderDepth(vctxt->reader);
27378 		    }
27379 		    if (ret < 0) {
27380 			/*
27381 			* VAL TODO: A reader error occurred; what to do here?
27382 			*/
27383 			ret = 1;
27384 			goto exit;
27385 		    }
27386 		}
27387 		goto leave_elem;
27388 	    }
27389 	    /*
27390 	    * READER VAL TODO: Is an END_ELEM really never called
27391 	    * if the elem is empty?
27392 	    */
27393 	    if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27394 		goto leave_elem;
27395 	} else if (nodeType == END_ELEM) {
27396 	    /*
27397 	    * Process END of element.
27398 	    */
27399 leave_elem:
27400 	    ret = xmlSchemaValidatorPopElem(vctxt);
27401 	    if (ret != 0) {
27402 		if (ret < 0) {
27403 		    VERROR_INT("xmlSchemaVReaderWalk",
27404 			"calling xmlSchemaValidatorPopElem()");
27405 		    goto internal_error;
27406 		}
27407 		goto exit;
27408 	    }
27409 	    if (vctxt->depth >= 0)
27410 		ielem = vctxt->inode;
27411 	    else
27412 		ielem = NULL;
27413 	} else if ((nodeType == XML_TEXT_NODE) ||
27414 	    (nodeType == XML_CDATA_SECTION_NODE) ||
27415 	    (nodeType == WHTSP) ||
27416 	    (nodeType == SIGN_WHTSP)) {
27417 	    /*
27418 	    * Process character content.
27419 	    */
27420 	    xmlChar *value;
27421 
27422 	    if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
27423 		nodeType = XML_TEXT_NODE;
27424 
27425 	    value = xmlTextReaderValue(vctxt->reader);
27426 	    ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
27427 		-1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
27428 	    if (! consumed)
27429 		xmlFree(value);
27430 	    if (ret == -1) {
27431 		VERROR_INT("xmlSchemaVReaderWalk",
27432 		    "calling xmlSchemaVPushText()");
27433 		goto internal_error;
27434 	    }
27435 	} else if ((nodeType == XML_ENTITY_NODE) ||
27436 	    (nodeType == XML_ENTITY_REF_NODE)) {
27437 	    /*
27438 	    * VAL TODO: What to do with entities?
27439 	    */
27440 	    TODO
27441 	}
27442 	/*
27443 	* Read next node.
27444 	*/
27445 	ret = xmlTextReaderRead(vctxt->reader);
27446     } while (ret == 1);
27447 
27448 exit:
27449     return (ret);
27450 internal_error:
27451     return (-1);
27452 }
27453 #endif
27454 
27455 /************************************************************************
27456  *									*
27457  *			SAX validation handlers				*
27458  *									*
27459  ************************************************************************/
27460 
27461 /*
27462 * Process text content.
27463 */
27464 static void
xmlSchemaSAXHandleText(void * ctx,const xmlChar * ch,int len)27465 xmlSchemaSAXHandleText(void *ctx,
27466 		       const xmlChar * ch,
27467 		       int len)
27468 {
27469     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27470 
27471     if (vctxt->depth < 0)
27472 	return;
27473     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27474 	return;
27475     if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27476 	vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27477     if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
27478 	XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27479 	VERROR_INT("xmlSchemaSAXHandleCDataSection",
27480 	    "calling xmlSchemaVPushText()");
27481 	vctxt->err = -1;
27482 	xmlStopParser(vctxt->parserCtxt);
27483     }
27484 }
27485 
27486 /*
27487 * Process CDATA content.
27488 */
27489 static void
xmlSchemaSAXHandleCDataSection(void * ctx,const xmlChar * ch,int len)27490 xmlSchemaSAXHandleCDataSection(void *ctx,
27491 			     const xmlChar * ch,
27492 			     int len)
27493 {
27494     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27495 
27496     if (vctxt->depth < 0)
27497 	return;
27498     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27499 	return;
27500     if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27501 	vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27502     if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
27503 	XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27504 	VERROR_INT("xmlSchemaSAXHandleCDataSection",
27505 	    "calling xmlSchemaVPushText()");
27506 	vctxt->err = -1;
27507 	xmlStopParser(vctxt->parserCtxt);
27508     }
27509 }
27510 
27511 static void
xmlSchemaSAXHandleReference(void * ctx ATTRIBUTE_UNUSED,const xmlChar * name ATTRIBUTE_UNUSED)27512 xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
27513 			    const xmlChar * name ATTRIBUTE_UNUSED)
27514 {
27515     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27516 
27517     if (vctxt->depth < 0)
27518 	return;
27519     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27520 	return;
27521     /* SAX VAL TODO: What to do here? */
27522     TODO
27523 }
27524 
27525 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)27526 xmlSchemaSAXHandleStartElementNs(void *ctx,
27527 				 const xmlChar * localname,
27528 				 const xmlChar * prefix ATTRIBUTE_UNUSED,
27529 				 const xmlChar * URI,
27530 				 int nb_namespaces,
27531 				 const xmlChar ** namespaces,
27532 				 int nb_attributes,
27533 				 int nb_defaulted ATTRIBUTE_UNUSED,
27534 				 const xmlChar ** attributes)
27535 {
27536     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27537     int ret;
27538     xmlSchemaNodeInfoPtr ielem;
27539     int i, j;
27540 
27541     /*
27542     * SAX VAL TODO: What to do with nb_defaulted?
27543     */
27544     /*
27545     * Skip elements if inside a "skip" wildcard or invalid.
27546     */
27547     vctxt->depth++;
27548     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27549 	return;
27550     /*
27551     * Push the element.
27552     */
27553     if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27554 	VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27555 	    "calling xmlSchemaValidatorPushElem()");
27556 	goto internal_error;
27557     }
27558     ielem = vctxt->inode;
27559     /*
27560     * TODO: Is this OK?
27561     */
27562     ielem->nodeLine = xmlSAX2GetLineNumber(vctxt->parserCtxt);
27563     ielem->localName = localname;
27564     ielem->nsName = URI;
27565     ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27566     /*
27567     * Register namespaces on the elem info.
27568     */
27569     if (nb_namespaces != 0) {
27570 	/*
27571 	* Although the parser builds its own namespace list,
27572 	* we have no access to it, so we'll use an own one.
27573 	*/
27574         for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
27575 	    /*
27576 	    * Store prefix and namespace name.
27577 	    */
27578 	    if (ielem->nsBindings == NULL) {
27579 		ielem->nsBindings =
27580 		    (const xmlChar **) xmlMalloc(10 *
27581 			sizeof(const xmlChar *));
27582 		if (ielem->nsBindings == NULL) {
27583 		    xmlSchemaVErrMemory(vctxt,
27584 			"allocating namespace bindings for SAX validation",
27585 			NULL);
27586 		    goto internal_error;
27587 		}
27588 		ielem->nbNsBindings = 0;
27589 		ielem->sizeNsBindings = 5;
27590 	    } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
27591 		ielem->sizeNsBindings *= 2;
27592 		ielem->nsBindings =
27593 		    (const xmlChar **) xmlRealloc(
27594 			(void *) ielem->nsBindings,
27595 			ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
27596 		if (ielem->nsBindings == NULL) {
27597 		    xmlSchemaVErrMemory(vctxt,
27598 			"re-allocating namespace bindings for SAX validation",
27599 			NULL);
27600 		    goto internal_error;
27601 		}
27602 	    }
27603 
27604 	    ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
27605 	    if (namespaces[j+1][0] == 0) {
27606 		/*
27607 		* Handle xmlns="".
27608 		*/
27609 		ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
27610 	    } else
27611 		ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
27612 		    namespaces[j+1];
27613 	    ielem->nbNsBindings++;
27614 	}
27615     }
27616     /*
27617     * Register attributes.
27618     * SAX VAL TODO: We are not adding namespace declaration
27619     * attributes yet.
27620     */
27621     if (nb_attributes != 0) {
27622 	int valueLen, k, l;
27623 	xmlChar *value;
27624 
27625         for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
27626 	    /*
27627 	    * Duplicate the value, changing any &#38; to a literal ampersand.
27628 	    *
27629 	    * libxml2 differs from normal SAX here in that it escapes all ampersands
27630 	    * as &#38; instead of delivering the raw converted string. Changing the
27631 	    * behavior at this point would break applications that use this API, so
27632 	    * we are forced to work around it.
27633 	    */
27634 	    valueLen = attributes[j+4] - attributes[j+3];
27635 	    value = xmlMallocAtomic(valueLen + 1);
27636 	    if (value == NULL) {
27637 		xmlSchemaVErrMemory(vctxt,
27638 		    "allocating string for decoded attribute",
27639 		    NULL);
27640 		goto internal_error;
27641 	    }
27642 	    for (k = 0, l = 0; k < valueLen; l++) {
27643 		if (k < valueLen - 4 &&
27644 		    attributes[j+3][k+0] == '&' &&
27645 		    attributes[j+3][k+1] == '#' &&
27646 		    attributes[j+3][k+2] == '3' &&
27647 		    attributes[j+3][k+3] == '8' &&
27648 		    attributes[j+3][k+4] == ';') {
27649 		    value[l] = '&';
27650 		    k += 5;
27651 		} else {
27652 		    value[l] = attributes[j+3][k];
27653 		    k++;
27654 		}
27655 	    }
27656 	    value[l] = '\0';
27657 	    /*
27658 	    * TODO: Set the node line.
27659 	    */
27660 	    ret = xmlSchemaValidatorPushAttribute(vctxt,
27661 		NULL, ielem->nodeLine, attributes[j], attributes[j+2], 0,
27662 		value, 1);
27663 	    if (ret == -1) {
27664 		VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27665 		    "calling xmlSchemaValidatorPushAttribute()");
27666 		goto internal_error;
27667 	    }
27668 	}
27669     }
27670     /*
27671     * Validate the element.
27672     */
27673     ret = xmlSchemaValidateElem(vctxt);
27674     if (ret != 0) {
27675 	if (ret == -1) {
27676 	    VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27677 		"calling xmlSchemaValidateElem()");
27678 	    goto internal_error;
27679 	}
27680 	goto exit;
27681     }
27682 
27683 exit:
27684     return;
27685 internal_error:
27686     vctxt->err = -1;
27687     xmlStopParser(vctxt->parserCtxt);
27688     return;
27689 }
27690 
27691 static void
xmlSchemaSAXHandleEndElementNs(void * ctx,const xmlChar * localname ATTRIBUTE_UNUSED,const xmlChar * prefix ATTRIBUTE_UNUSED,const xmlChar * URI ATTRIBUTE_UNUSED)27692 xmlSchemaSAXHandleEndElementNs(void *ctx,
27693 			       const xmlChar * localname ATTRIBUTE_UNUSED,
27694 			       const xmlChar * prefix ATTRIBUTE_UNUSED,
27695 			       const xmlChar * URI ATTRIBUTE_UNUSED)
27696 {
27697     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27698     int res;
27699 
27700     /*
27701     * Skip elements if inside a "skip" wildcard or if invalid.
27702     */
27703     if (vctxt->skipDepth != -1) {
27704 	if (vctxt->depth > vctxt->skipDepth) {
27705 	    vctxt->depth--;
27706 	    return;
27707 	} else
27708 	    vctxt->skipDepth = -1;
27709     }
27710     /*
27711     * SAX VAL TODO: Just a temporary check.
27712     */
27713     if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
27714 	(!xmlStrEqual(vctxt->inode->nsName, URI))) {
27715 	VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27716 	    "elem pop mismatch");
27717     }
27718     res = xmlSchemaValidatorPopElem(vctxt);
27719     if (res != 0) {
27720 	if (res < 0) {
27721 	    VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27722 		"calling xmlSchemaValidatorPopElem()");
27723 	    goto internal_error;
27724 	}
27725 	goto exit;
27726     }
27727 exit:
27728     return;
27729 internal_error:
27730     vctxt->err = -1;
27731     xmlStopParser(vctxt->parserCtxt);
27732     return;
27733 }
27734 
27735 /************************************************************************
27736  *									*
27737  *			Validation interfaces				*
27738  *									*
27739  ************************************************************************/
27740 
27741 /**
27742  * xmlSchemaNewValidCtxt:
27743  * @schema:  a precompiled XML Schemas
27744  *
27745  * Create an XML Schemas validation context based on the given schema.
27746  *
27747  * Returns the validation context or NULL in case of error
27748  */
27749 xmlSchemaValidCtxtPtr
xmlSchemaNewValidCtxt(xmlSchemaPtr schema)27750 xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
27751 {
27752     xmlSchemaValidCtxtPtr ret;
27753 
27754     ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
27755     if (ret == NULL) {
27756         xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
27757         return (NULL);
27758     }
27759     memset(ret, 0, sizeof(xmlSchemaValidCtxt));
27760     ret->type = XML_SCHEMA_CTXT_VALIDATOR;
27761     ret->dict = xmlDictCreate();
27762     ret->nodeQNames = xmlSchemaItemListCreate();
27763     ret->schema = schema;
27764     return (ret);
27765 }
27766 
27767 /**
27768  * xmlSchemaValidateSetFilename:
27769  * @vctxt: the schema validation context
27770  * @filename: the file name
27771  *
27772  * Workaround to provide file error reporting information when this is
27773  * not provided by current APIs
27774  */
27775 void
xmlSchemaValidateSetFilename(xmlSchemaValidCtxtPtr vctxt,const char * filename)27776 xmlSchemaValidateSetFilename(xmlSchemaValidCtxtPtr vctxt, const char *filename) {
27777     if (vctxt == NULL)
27778         return;
27779     if (vctxt->filename != NULL)
27780         xmlFree(vctxt->filename);
27781     if (filename != NULL)
27782         vctxt->filename = (char *) xmlStrdup((const xmlChar *) filename);
27783     else
27784         vctxt->filename = NULL;
27785 }
27786 
27787 /**
27788  * xmlSchemaClearValidCtxt:
27789  * @vctxt: the schema validation context
27790  *
27791  * Free the resources associated to the schema validation context;
27792  * leaves some fields alive intended for reuse of the context.
27793  */
27794 static void
xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)27795 xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
27796 {
27797     if (vctxt == NULL)
27798         return;
27799 
27800     /*
27801     * TODO: Should we clear the flags?
27802     *   Might be problematic if one reuses the context
27803     *   and assumes that the options remain the same.
27804     */
27805     vctxt->flags = 0;
27806     vctxt->validationRoot = NULL;
27807     vctxt->doc = NULL;
27808 #ifdef LIBXML_READER_ENABLED
27809     vctxt->reader = NULL;
27810 #endif
27811     vctxt->hasKeyrefs = 0;
27812 
27813     if (vctxt->value != NULL) {
27814         xmlSchemaFreeValue(vctxt->value);
27815 	vctxt->value = NULL;
27816     }
27817     /*
27818     * Augmented IDC information.
27819     */
27820     if (vctxt->aidcs != NULL) {
27821 	xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
27822 	do {
27823 	    next = cur->next;
27824 	    xmlFree(cur);
27825 	    cur = next;
27826 	} while (cur != NULL);
27827 	vctxt->aidcs = NULL;
27828     }
27829     if (vctxt->idcMatcherCache != NULL) {
27830 	xmlSchemaIDCMatcherPtr matcher = vctxt->idcMatcherCache, tmp;
27831 
27832 	while (matcher) {
27833 	    tmp = matcher;
27834 	    matcher = matcher->nextCached;
27835 	    xmlSchemaIDCFreeMatcherList(tmp);
27836 	}
27837 	vctxt->idcMatcherCache = NULL;
27838     }
27839 
27840 
27841     if (vctxt->idcNodes != NULL) {
27842 	int i;
27843 	xmlSchemaPSVIIDCNodePtr item;
27844 
27845 	for (i = 0; i < vctxt->nbIdcNodes; i++) {
27846 	    item = vctxt->idcNodes[i];
27847 	    xmlFree(item->keys);
27848 	    xmlFree(item);
27849 	}
27850 	xmlFree(vctxt->idcNodes);
27851 	vctxt->idcNodes = NULL;
27852 	vctxt->nbIdcNodes = 0;
27853 	vctxt->sizeIdcNodes = 0;
27854     }
27855 
27856     if (vctxt->idcKeys != NULL) {
27857 	int i;
27858 	for (i = 0; i < vctxt->nbIdcKeys; i++)
27859 	    xmlSchemaIDCFreeKey(vctxt->idcKeys[i]);
27860 	xmlFree(vctxt->idcKeys);
27861 	vctxt->idcKeys = NULL;
27862 	vctxt->nbIdcKeys = 0;
27863 	vctxt->sizeIdcKeys = 0;
27864     }
27865 
27866     /*
27867     * Note that we won't delete the XPath state pool here.
27868     */
27869     if (vctxt->xpathStates != NULL) {
27870 	xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
27871 	vctxt->xpathStates = NULL;
27872     }
27873     /*
27874     * Attribute info.
27875     */
27876     if (vctxt->nbAttrInfos != 0) {
27877 	xmlSchemaClearAttrInfos(vctxt);
27878     }
27879     /*
27880     * Element info.
27881     */
27882     if (vctxt->elemInfos != NULL) {
27883 	int i;
27884 	xmlSchemaNodeInfoPtr ei;
27885 
27886 	for (i = 0; i < vctxt->sizeElemInfos; i++) {
27887 	    ei = vctxt->elemInfos[i];
27888 	    if (ei == NULL)
27889 		break;
27890 	    xmlSchemaClearElemInfo(vctxt, ei);
27891 	}
27892     }
27893     xmlSchemaItemListClear(vctxt->nodeQNames);
27894     /* Recreate the dict. */
27895     xmlDictFree(vctxt->dict);
27896     /*
27897     * TODO: Is is save to recreate it? Do we have a scenario
27898     * where the user provides the dict?
27899     */
27900     vctxt->dict = xmlDictCreate();
27901 
27902     if (vctxt->filename != NULL) {
27903         xmlFree(vctxt->filename);
27904 	vctxt->filename = NULL;
27905     }
27906 }
27907 
27908 /**
27909  * xmlSchemaFreeValidCtxt:
27910  * @ctxt:  the schema validation context
27911  *
27912  * Free the resources associated to the schema validation context
27913  */
27914 void
xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)27915 xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
27916 {
27917     if (ctxt == NULL)
27918         return;
27919     if (ctxt->value != NULL)
27920         xmlSchemaFreeValue(ctxt->value);
27921     if (ctxt->pctxt != NULL)
27922 	xmlSchemaFreeParserCtxt(ctxt->pctxt);
27923     if (ctxt->idcNodes != NULL) {
27924 	int i;
27925 	xmlSchemaPSVIIDCNodePtr item;
27926 
27927 	for (i = 0; i < ctxt->nbIdcNodes; i++) {
27928 	    item = ctxt->idcNodes[i];
27929 	    xmlFree(item->keys);
27930 	    xmlFree(item);
27931 	}
27932 	xmlFree(ctxt->idcNodes);
27933     }
27934     if (ctxt->idcKeys != NULL) {
27935 	int i;
27936 	for (i = 0; i < ctxt->nbIdcKeys; i++)
27937 	    xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
27938 	xmlFree(ctxt->idcKeys);
27939     }
27940 
27941     if (ctxt->xpathStates != NULL) {
27942 	xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
27943 	ctxt->xpathStates = NULL;
27944     }
27945     if (ctxt->xpathStatePool != NULL) {
27946 	xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
27947 	ctxt->xpathStatePool = NULL;
27948     }
27949 
27950     /*
27951     * Augmented IDC information.
27952     */
27953     if (ctxt->aidcs != NULL) {
27954 	xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
27955 	do {
27956 	    next = cur->next;
27957 	    xmlFree(cur);
27958 	    cur = next;
27959 	} while (cur != NULL);
27960     }
27961     if (ctxt->attrInfos != NULL) {
27962 	int i;
27963 	xmlSchemaAttrInfoPtr attr;
27964 
27965 	/* Just a paranoid call to the cleanup. */
27966 	if (ctxt->nbAttrInfos != 0)
27967 	    xmlSchemaClearAttrInfos(ctxt);
27968 	for (i = 0; i < ctxt->sizeAttrInfos; i++) {
27969 	    attr = ctxt->attrInfos[i];
27970 	    xmlFree(attr);
27971 	}
27972 	xmlFree(ctxt->attrInfos);
27973     }
27974     if (ctxt->elemInfos != NULL) {
27975 	int i;
27976 	xmlSchemaNodeInfoPtr ei;
27977 
27978 	for (i = 0; i < ctxt->sizeElemInfos; i++) {
27979 	    ei = ctxt->elemInfos[i];
27980 	    if (ei == NULL)
27981 		break;
27982 	    xmlSchemaClearElemInfo(ctxt, ei);
27983 	    xmlFree(ei);
27984 	}
27985 	xmlFree(ctxt->elemInfos);
27986     }
27987     if (ctxt->nodeQNames != NULL)
27988 	xmlSchemaItemListFree(ctxt->nodeQNames);
27989     if (ctxt->dict != NULL)
27990 	xmlDictFree(ctxt->dict);
27991     if (ctxt->filename != NULL)
27992 	xmlFree(ctxt->filename);
27993     xmlFree(ctxt);
27994 }
27995 
27996 /**
27997  * xmlSchemaIsValid:
27998  * @ctxt: the schema validation context
27999  *
28000  * Check if any error was detected during validation.
28001  *
28002  * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
28003  *         of internal error.
28004  */
28005 int
xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)28006 xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
28007 {
28008     if (ctxt == NULL)
28009         return(-1);
28010     return(ctxt->err == 0);
28011 }
28012 
28013 /**
28014  * xmlSchemaSetValidErrors:
28015  * @ctxt:  a schema validation context
28016  * @err:  the error function
28017  * @warn: the warning function
28018  * @ctx: the functions context
28019  *
28020  * Set the error and warning callback information
28021  */
28022 void
xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,xmlSchemaValidityErrorFunc err,xmlSchemaValidityWarningFunc warn,void * ctx)28023 xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
28024                         xmlSchemaValidityErrorFunc err,
28025                         xmlSchemaValidityWarningFunc warn, void *ctx)
28026 {
28027     if (ctxt == NULL)
28028         return;
28029     ctxt->error = err;
28030     ctxt->warning = warn;
28031     ctxt->errCtxt = ctx;
28032     if (ctxt->pctxt != NULL)
28033 	xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
28034 }
28035 
28036 /**
28037  * xmlSchemaSetValidStructuredErrors:
28038  * @ctxt:  a schema validation context
28039  * @serror:  the structured error function
28040  * @ctx: the functions context
28041  *
28042  * Set the structured error callback
28043  */
28044 void
xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,xmlStructuredErrorFunc serror,void * ctx)28045 xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
28046 				  xmlStructuredErrorFunc serror, void *ctx)
28047 {
28048     if (ctxt == NULL)
28049         return;
28050     ctxt->serror = serror;
28051     ctxt->error = NULL;
28052     ctxt->warning = NULL;
28053     ctxt->errCtxt = ctx;
28054     if (ctxt->pctxt != NULL)
28055 	xmlSchemaSetParserStructuredErrors(ctxt->pctxt, serror, ctx);
28056 }
28057 
28058 /**
28059  * xmlSchemaGetValidErrors:
28060  * @ctxt: a XML-Schema validation context
28061  * @err: the error function result
28062  * @warn: the warning function result
28063  * @ctx: the functions context result
28064  *
28065  * Get the error and warning callback information
28066  *
28067  * Returns -1 in case of error and 0 otherwise
28068  */
28069 int
xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,xmlSchemaValidityErrorFunc * err,xmlSchemaValidityWarningFunc * warn,void ** ctx)28070 xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
28071 			xmlSchemaValidityErrorFunc * err,
28072 			xmlSchemaValidityWarningFunc * warn, void **ctx)
28073 {
28074 	if (ctxt == NULL)
28075 		return (-1);
28076 	if (err != NULL)
28077 		*err = ctxt->error;
28078 	if (warn != NULL)
28079 		*warn = ctxt->warning;
28080 	if (ctx != NULL)
28081 		*ctx = ctxt->errCtxt;
28082 	return (0);
28083 }
28084 
28085 
28086 /**
28087  * xmlSchemaSetValidOptions:
28088  * @ctxt:	a schema validation context
28089  * @options: a combination of xmlSchemaValidOption
28090  *
28091  * Sets the options to be used during the validation.
28092  *
28093  * Returns 0 in case of success, -1 in case of an
28094  * API error.
28095  */
28096 int
xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,int options)28097 xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
28098 			 int options)
28099 
28100 {
28101     int i;
28102 
28103     if (ctxt == NULL)
28104 	return (-1);
28105     /*
28106     * WARNING: Change the start value if adding to the
28107     * xmlSchemaValidOption.
28108     * TODO: Is there an other, more easy to maintain,
28109     * way?
28110     */
28111     for (i = 1; i < (int) sizeof(int) * 8; i++) {
28112         if (options & 1<<i)
28113 	    return (-1);
28114     }
28115     ctxt->options = options;
28116     return (0);
28117 }
28118 
28119 /**
28120  * xmlSchemaValidCtxtGetOptions:
28121  * @ctxt: a schema validation context
28122  *
28123  * Get the validation context options.
28124  *
28125  * Returns the option combination or -1 on error.
28126  */
28127 int
xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)28128 xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
28129 
28130 {
28131     if (ctxt == NULL)
28132 	return (-1);
28133     else
28134 	return (ctxt->options);
28135 }
28136 
28137 static int
xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)28138 xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
28139 {
28140     xmlAttrPtr attr;
28141     int ret = 0;
28142     xmlSchemaNodeInfoPtr ielem = NULL;
28143     xmlNodePtr node, valRoot;
28144     const xmlChar *nsName;
28145 
28146     /* DOC VAL TODO: Move this to the start function. */
28147     if (vctxt->validationRoot != NULL)
28148         valRoot = vctxt->validationRoot;
28149     else
28150 	valRoot = xmlDocGetRootElement(vctxt->doc);
28151     if (valRoot == NULL) {
28152 	/* VAL TODO: Error code? */
28153 	VERROR(1, NULL, "The document has no document element");
28154 	return (1);
28155     }
28156     vctxt->depth = -1;
28157     vctxt->validationRoot = valRoot;
28158     node = valRoot;
28159     while (node != NULL) {
28160 	if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
28161 	    goto next_sibling;
28162 	if (node->type == XML_ELEMENT_NODE) {
28163 
28164 	    /*
28165 	    * Init the node-info.
28166 	    */
28167 	    vctxt->depth++;
28168 	    if (xmlSchemaValidatorPushElem(vctxt) == -1)
28169 		goto internal_error;
28170 	    ielem = vctxt->inode;
28171 	    ielem->node = node;
28172 	    ielem->nodeLine = node->line;
28173 	    ielem->localName = node->name;
28174 	    if (node->ns != NULL)
28175 		ielem->nsName = node->ns->href;
28176 	    ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
28177 	    /*
28178 	    * Register attributes.
28179 	    * DOC VAL TODO: We do not register namespace declaration
28180 	    * attributes yet.
28181 	    */
28182 	    vctxt->nbAttrInfos = 0;
28183 	    if (node->properties != NULL) {
28184 		attr = node->properties;
28185 		do {
28186 		    if (attr->ns != NULL)
28187 			nsName = attr->ns->href;
28188 		    else
28189 			nsName = NULL;
28190 		    ret = xmlSchemaValidatorPushAttribute(vctxt,
28191 			(xmlNodePtr) attr,
28192 			/*
28193 			* Note that we give it the line number of the
28194 			* parent element.
28195 			*/
28196 			ielem->nodeLine,
28197 			attr->name, nsName, 0,
28198 			xmlNodeListGetString(attr->doc, attr->children, 1), 1);
28199 		    if (ret == -1) {
28200 			VERROR_INT("xmlSchemaDocWalk",
28201 			    "calling xmlSchemaValidatorPushAttribute()");
28202 			goto internal_error;
28203 		    }
28204 		    attr = attr->next;
28205 		} while (attr);
28206 	    }
28207 	    /*
28208 	    * Validate the element.
28209 	    */
28210 	    ret = xmlSchemaValidateElem(vctxt);
28211 	    if (ret != 0) {
28212 		if (ret == -1) {
28213 		    VERROR_INT("xmlSchemaDocWalk",
28214 			"calling xmlSchemaValidateElem()");
28215 		    goto internal_error;
28216 		}
28217 		/*
28218 		* Don't stop validation; just skip the content
28219 		* of this element.
28220 		*/
28221 		goto leave_node;
28222 	    }
28223 	    if ((vctxt->skipDepth != -1) &&
28224 		(vctxt->depth >= vctxt->skipDepth))
28225 		goto leave_node;
28226 	} else if ((node->type == XML_TEXT_NODE) ||
28227 	    (node->type == XML_CDATA_SECTION_NODE)) {
28228 	    /*
28229 	    * Process character content.
28230 	    */
28231 	    if ((ielem != NULL) && (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY))
28232 		ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
28233 	    ret = xmlSchemaVPushText(vctxt, node->type, node->content,
28234 		-1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
28235 	    if (ret < 0) {
28236 		VERROR_INT("xmlSchemaVDocWalk",
28237 		    "calling xmlSchemaVPushText()");
28238 		goto internal_error;
28239 	    }
28240 	    /*
28241 	    * DOC VAL TODO: Should we skip further validation of the
28242 	    * element content here?
28243 	    */
28244 	} else if ((node->type == XML_ENTITY_NODE) ||
28245 	    (node->type == XML_ENTITY_REF_NODE)) {
28246 	    /*
28247 	    * DOC VAL TODO: What to do with entities?
28248 	    */
28249 	    VERROR_INT("xmlSchemaVDocWalk",
28250 		"there is at least one entity reference in the node-tree "
28251 		"currently being validated. Processing of entities with "
28252 		"this XML Schema processor is not supported (yet). Please "
28253 		"substitute entities before validation.");
28254 	    goto internal_error;
28255 	} else {
28256 	    goto leave_node;
28257 	    /*
28258 	    * DOC VAL TODO: XInclude nodes, etc.
28259 	    */
28260 	}
28261 	/*
28262 	* Walk the doc.
28263 	*/
28264 	if (node->children != NULL) {
28265 	    node = node->children;
28266 	    continue;
28267 	}
28268 leave_node:
28269 	if (node->type == XML_ELEMENT_NODE) {
28270 	    /*
28271 	    * Leaving the scope of an element.
28272 	    */
28273 	    if (node != vctxt->inode->node) {
28274 		VERROR_INT("xmlSchemaVDocWalk",
28275 		    "element position mismatch");
28276 		goto internal_error;
28277 	    }
28278 	    ret = xmlSchemaValidatorPopElem(vctxt);
28279 	    if (ret != 0) {
28280 		if (ret < 0) {
28281 		    VERROR_INT("xmlSchemaVDocWalk",
28282 			"calling xmlSchemaValidatorPopElem()");
28283 		    goto internal_error;
28284 		}
28285 	    }
28286 	    if (node == valRoot)
28287 		goto exit;
28288 	}
28289 next_sibling:
28290 	if (node->next != NULL)
28291 	    node = node->next;
28292 	else {
28293 	    node = node->parent;
28294 	    goto leave_node;
28295 	}
28296     }
28297 
28298 exit:
28299     return (ret);
28300 internal_error:
28301     return (-1);
28302 }
28303 
28304 static int
xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt)28305 xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
28306     /*
28307     * Some initialization.
28308     */
28309     vctxt->err = 0;
28310     vctxt->nberrors = 0;
28311     vctxt->depth = -1;
28312     vctxt->skipDepth = -1;
28313     vctxt->hasKeyrefs = 0;
28314 #ifdef ENABLE_IDC_NODE_TABLES_TEST
28315     vctxt->createIDCNodeTables = 1;
28316 #else
28317     vctxt->createIDCNodeTables = 0;
28318 #endif
28319     /*
28320     * Create a schema + parser if necessary.
28321     */
28322     if (vctxt->schema == NULL) {
28323 	xmlSchemaParserCtxtPtr pctxt;
28324 
28325 	vctxt->xsiAssemble = 1;
28326 	/*
28327 	* If not schema was given then we will create a schema
28328 	* dynamically using XSI schema locations.
28329 	*
28330 	* Create the schema parser context.
28331 	*/
28332 	if ((vctxt->pctxt == NULL) &&
28333 	   (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
28334 	   return (-1);
28335 	pctxt = vctxt->pctxt;
28336 	pctxt->xsiAssemble = 1;
28337 	/*
28338 	* Create the schema.
28339 	*/
28340 	vctxt->schema = xmlSchemaNewSchema(pctxt);
28341 	if (vctxt->schema == NULL)
28342 	    return (-1);
28343 	/*
28344 	* Create the schema construction context.
28345 	*/
28346 	pctxt->constructor = xmlSchemaConstructionCtxtCreate(pctxt->dict);
28347 	if (pctxt->constructor == NULL)
28348 	    return(-1);
28349 	pctxt->constructor->mainSchema = vctxt->schema;
28350 	/*
28351 	* Take ownership of the constructor to be able to free it.
28352 	*/
28353 	pctxt->ownsConstructor = 1;
28354     }
28355     /*
28356     * Augment the IDC definitions for the main schema and all imported ones
28357     * NOTE: main schema if the first in the imported list
28358     */
28359     xmlHashScan(vctxt->schema->schemasImports, xmlSchemaAugmentImportedIDC,
28360                 vctxt);
28361 
28362     return(0);
28363 }
28364 
28365 static void
xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt)28366 xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
28367     if (vctxt->xsiAssemble) {
28368 	if (vctxt->schema != NULL) {
28369 	    xmlSchemaFree(vctxt->schema);
28370 	    vctxt->schema = NULL;
28371 	}
28372     }
28373     xmlSchemaClearValidCtxt(vctxt);
28374 }
28375 
28376 static int
xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)28377 xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
28378 {
28379     int ret = 0;
28380 
28381     if (xmlSchemaPreRun(vctxt) < 0)
28382         return(-1);
28383 
28384     if (vctxt->doc != NULL) {
28385 	/*
28386 	 * Tree validation.
28387 	 */
28388 	ret = xmlSchemaVDocWalk(vctxt);
28389 #ifdef LIBXML_READER_ENABLED
28390     } else if (vctxt->reader != NULL) {
28391 	/*
28392 	 * XML Reader validation.
28393 	 */
28394 #ifdef XML_SCHEMA_READER_ENABLED
28395 	ret = xmlSchemaVReaderWalk(vctxt);
28396 #endif
28397 #endif
28398     } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
28399 	/*
28400 	 * SAX validation.
28401 	 */
28402 	ret = xmlParseDocument(vctxt->parserCtxt);
28403     } else {
28404 	VERROR_INT("xmlSchemaVStart",
28405 	    "no instance to validate");
28406 	ret = -1;
28407     }
28408 
28409     xmlSchemaPostRun(vctxt);
28410     if (ret == 0)
28411 	ret = vctxt->err;
28412     return (ret);
28413 }
28414 
28415 /**
28416  * xmlSchemaValidateOneElement:
28417  * @ctxt:  a schema validation context
28418  * @elem:  an element node
28419  *
28420  * Validate a branch of a tree, starting with the given @elem.
28421  *
28422  * Returns 0 if the element and its subtree is valid, a positive error
28423  * code number otherwise and -1 in case of an internal or API error.
28424  */
28425 int
xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt,xmlNodePtr elem)28426 xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
28427 {
28428     if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
28429 	return (-1);
28430 
28431     if (ctxt->schema == NULL)
28432 	return (-1);
28433 
28434     ctxt->doc = elem->doc;
28435     ctxt->node = elem;
28436     ctxt->validationRoot = elem;
28437     return(xmlSchemaVStart(ctxt));
28438 }
28439 
28440 /**
28441  * xmlSchemaValidateDoc:
28442  * @ctxt:  a schema validation context
28443  * @doc:  a parsed document tree
28444  *
28445  * Validate a document tree in memory.
28446  *
28447  * Returns 0 if the document is schemas valid, a positive error code
28448  *     number otherwise and -1 in case of internal or API error.
28449  */
28450 int
xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt,xmlDocPtr doc)28451 xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
28452 {
28453     if ((ctxt == NULL) || (doc == NULL))
28454         return (-1);
28455 
28456     ctxt->doc = doc;
28457     ctxt->node = xmlDocGetRootElement(doc);
28458     if (ctxt->node == NULL) {
28459         xmlSchemaCustomErr(ACTXT_CAST ctxt,
28460 	    XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
28461 	    (xmlNodePtr) doc, NULL,
28462 	    "The document has no document element", NULL, NULL);
28463         return (ctxt->err);
28464     }
28465     ctxt->validationRoot = ctxt->node;
28466     return (xmlSchemaVStart(ctxt));
28467 }
28468 
28469 
28470 /************************************************************************
28471  *									*
28472  *		Function and data for SAX streaming API			*
28473  *									*
28474  ************************************************************************/
28475 typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
28476 typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
28477 
28478 struct _xmlSchemaSplitSAXData {
28479     xmlSAXHandlerPtr      user_sax;
28480     void                 *user_data;
28481     xmlSchemaValidCtxtPtr ctxt;
28482     xmlSAXHandlerPtr      schemas_sax;
28483 };
28484 
28485 #define XML_SAX_PLUG_MAGIC 0xdc43ba21
28486 
28487 struct _xmlSchemaSAXPlug {
28488     unsigned int magic;
28489 
28490     /* the original callbacks information */
28491     xmlSAXHandlerPtr     *user_sax_ptr;
28492     xmlSAXHandlerPtr      user_sax;
28493     void                **user_data_ptr;
28494     void                 *user_data;
28495 
28496     /* the block plugged back and validation information */
28497     xmlSAXHandler         schemas_sax;
28498     xmlSchemaValidCtxtPtr ctxt;
28499 };
28500 
28501 /* All those functions just bounces to the user provided SAX handlers */
28502 static void
internalSubsetSplit(void * ctx,const xmlChar * name,const xmlChar * ExternalID,const xmlChar * SystemID)28503 internalSubsetSplit(void *ctx, const xmlChar *name,
28504 	       const xmlChar *ExternalID, const xmlChar *SystemID)
28505 {
28506     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28507     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28508         (ctxt->user_sax->internalSubset != NULL))
28509 	ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
28510 	                               SystemID);
28511 }
28512 
28513 static int
isStandaloneSplit(void * ctx)28514 isStandaloneSplit(void *ctx)
28515 {
28516     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28517     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28518         (ctxt->user_sax->isStandalone != NULL))
28519 	return(ctxt->user_sax->isStandalone(ctxt->user_data));
28520     return(0);
28521 }
28522 
28523 static int
hasInternalSubsetSplit(void * ctx)28524 hasInternalSubsetSplit(void *ctx)
28525 {
28526     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28527     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28528         (ctxt->user_sax->hasInternalSubset != NULL))
28529 	return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
28530     return(0);
28531 }
28532 
28533 static int
hasExternalSubsetSplit(void * ctx)28534 hasExternalSubsetSplit(void *ctx)
28535 {
28536     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28537     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28538         (ctxt->user_sax->hasExternalSubset != NULL))
28539 	return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
28540     return(0);
28541 }
28542 
28543 static void
externalSubsetSplit(void * ctx,const xmlChar * name,const xmlChar * ExternalID,const xmlChar * SystemID)28544 externalSubsetSplit(void *ctx, const xmlChar *name,
28545 	       const xmlChar *ExternalID, const xmlChar *SystemID)
28546 {
28547     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28548     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28549         (ctxt->user_sax->externalSubset != NULL))
28550 	ctxt->user_sax->externalSubset(ctxt->user_data, name, ExternalID,
28551 	                               SystemID);
28552 }
28553 
28554 static xmlParserInputPtr
resolveEntitySplit(void * ctx,const xmlChar * publicId,const xmlChar * systemId)28555 resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
28556 {
28557     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28558     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28559         (ctxt->user_sax->resolveEntity != NULL))
28560 	return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
28561 	                                     systemId));
28562     return(NULL);
28563 }
28564 
28565 static xmlEntityPtr
getEntitySplit(void * ctx,const xmlChar * name)28566 getEntitySplit(void *ctx, const xmlChar *name)
28567 {
28568     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28569     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28570         (ctxt->user_sax->getEntity != NULL))
28571 	return(ctxt->user_sax->getEntity(ctxt->user_data, name));
28572     return(NULL);
28573 }
28574 
28575 static xmlEntityPtr
getParameterEntitySplit(void * ctx,const xmlChar * name)28576 getParameterEntitySplit(void *ctx, const xmlChar *name)
28577 {
28578     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28579     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28580         (ctxt->user_sax->getParameterEntity != NULL))
28581 	return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
28582     return(NULL);
28583 }
28584 
28585 
28586 static void
entityDeclSplit(void * ctx,const xmlChar * name,int type,const xmlChar * publicId,const xmlChar * systemId,xmlChar * content)28587 entityDeclSplit(void *ctx, const xmlChar *name, int type,
28588           const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
28589 {
28590     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28591     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28592         (ctxt->user_sax->entityDecl != NULL))
28593 	ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
28594 	                           systemId, content);
28595 }
28596 
28597 static void
attributeDeclSplit(void * ctx,const xmlChar * elem,const xmlChar * name,int type,int def,const xmlChar * defaultValue,xmlEnumerationPtr tree)28598 attributeDeclSplit(void *ctx, const xmlChar * elem,
28599                    const xmlChar * name, int type, int def,
28600                    const xmlChar * defaultValue, xmlEnumerationPtr tree)
28601 {
28602     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28603     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28604         (ctxt->user_sax->attributeDecl != NULL)) {
28605 	ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
28606 	                              def, defaultValue, tree);
28607     } else {
28608 	xmlFreeEnumeration(tree);
28609     }
28610 }
28611 
28612 static void
elementDeclSplit(void * ctx,const xmlChar * name,int type,xmlElementContentPtr content)28613 elementDeclSplit(void *ctx, const xmlChar *name, int type,
28614 	    xmlElementContentPtr content)
28615 {
28616     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28617     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28618         (ctxt->user_sax->elementDecl != NULL))
28619 	ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
28620 }
28621 
28622 static void
notationDeclSplit(void * ctx,const xmlChar * name,const xmlChar * publicId,const xmlChar * systemId)28623 notationDeclSplit(void *ctx, const xmlChar *name,
28624 	     const xmlChar *publicId, const xmlChar *systemId)
28625 {
28626     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28627     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28628         (ctxt->user_sax->notationDecl != NULL))
28629 	ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
28630 	                             systemId);
28631 }
28632 
28633 static void
unparsedEntityDeclSplit(void * ctx,const xmlChar * name,const xmlChar * publicId,const xmlChar * systemId,const xmlChar * notationName)28634 unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
28635 		   const xmlChar *publicId, const xmlChar *systemId,
28636 		   const xmlChar *notationName)
28637 {
28638     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28639     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28640         (ctxt->user_sax->unparsedEntityDecl != NULL))
28641 	ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
28642 	                                   systemId, notationName);
28643 }
28644 
28645 static void
setDocumentLocatorSplit(void * ctx,xmlSAXLocatorPtr loc)28646 setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
28647 {
28648     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28649     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28650         (ctxt->user_sax->setDocumentLocator != NULL))
28651 	ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
28652 }
28653 
28654 static void
startDocumentSplit(void * ctx)28655 startDocumentSplit(void *ctx)
28656 {
28657     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28658     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28659         (ctxt->user_sax->startDocument != NULL))
28660 	ctxt->user_sax->startDocument(ctxt->user_data);
28661 }
28662 
28663 static void
endDocumentSplit(void * ctx)28664 endDocumentSplit(void *ctx)
28665 {
28666     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28667     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28668         (ctxt->user_sax->endDocument != NULL))
28669 	ctxt->user_sax->endDocument(ctxt->user_data);
28670 }
28671 
28672 static void
processingInstructionSplit(void * ctx,const xmlChar * target,const xmlChar * data)28673 processingInstructionSplit(void *ctx, const xmlChar *target,
28674                       const xmlChar *data)
28675 {
28676     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28677     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28678         (ctxt->user_sax->processingInstruction != NULL))
28679 	ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
28680 }
28681 
28682 static void
commentSplit(void * ctx,const xmlChar * value)28683 commentSplit(void *ctx, const xmlChar *value)
28684 {
28685     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28686     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28687         (ctxt->user_sax->comment != NULL))
28688 	ctxt->user_sax->comment(ctxt->user_data, value);
28689 }
28690 
28691 /*
28692  * Varargs error callbacks to the user application, harder ...
28693  */
28694 
28695 static void XMLCDECL
warningSplit(void * ctx,const char * msg ATTRIBUTE_UNUSED,...)28696 warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28697     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28698     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28699         (ctxt->user_sax->warning != NULL)) {
28700 	TODO
28701     }
28702 }
28703 static void XMLCDECL
errorSplit(void * ctx,const char * msg ATTRIBUTE_UNUSED,...)28704 errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28705     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28706     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28707         (ctxt->user_sax->error != NULL)) {
28708 	TODO
28709     }
28710 }
28711 static void XMLCDECL
fatalErrorSplit(void * ctx,const char * msg ATTRIBUTE_UNUSED,...)28712 fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28713     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28714     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28715         (ctxt->user_sax->fatalError != NULL)) {
28716 	TODO
28717     }
28718 }
28719 
28720 /*
28721  * Those are function where both the user handler and the schemas handler
28722  * need to be called.
28723  */
28724 static void
charactersSplit(void * ctx,const xmlChar * ch,int len)28725 charactersSplit(void *ctx, const xmlChar *ch, int len)
28726 {
28727     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28728     if (ctxt == NULL)
28729         return;
28730     if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
28731 	ctxt->user_sax->characters(ctxt->user_data, ch, len);
28732     if (ctxt->ctxt != NULL)
28733 	xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28734 }
28735 
28736 static void
ignorableWhitespaceSplit(void * ctx,const xmlChar * ch,int len)28737 ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
28738 {
28739     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28740     if (ctxt == NULL)
28741         return;
28742     if ((ctxt->user_sax != NULL) &&
28743         (ctxt->user_sax->ignorableWhitespace != NULL))
28744 	ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
28745     if (ctxt->ctxt != NULL)
28746 	xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28747 }
28748 
28749 static void
cdataBlockSplit(void * ctx,const xmlChar * value,int len)28750 cdataBlockSplit(void *ctx, const xmlChar *value, int len)
28751 {
28752     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28753     if (ctxt == NULL)
28754         return;
28755     if ((ctxt->user_sax != NULL) &&
28756         (ctxt->user_sax->cdataBlock != NULL))
28757 	ctxt->user_sax->cdataBlock(ctxt->user_data, value, len);
28758     if (ctxt->ctxt != NULL)
28759 	xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
28760 }
28761 
28762 static void
referenceSplit(void * ctx,const xmlChar * name)28763 referenceSplit(void *ctx, const xmlChar *name)
28764 {
28765     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28766     if (ctxt == NULL)
28767         return;
28768     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28769         (ctxt->user_sax->reference != NULL))
28770 	ctxt->user_sax->reference(ctxt->user_data, name);
28771     if (ctxt->ctxt != NULL)
28772         xmlSchemaSAXHandleReference(ctxt->user_data, name);
28773 }
28774 
28775 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)28776 startElementNsSplit(void *ctx, const xmlChar * localname,
28777 		    const xmlChar * prefix, const xmlChar * URI,
28778 		    int nb_namespaces, const xmlChar ** namespaces,
28779 		    int nb_attributes, int nb_defaulted,
28780 		    const xmlChar ** attributes) {
28781     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28782     if (ctxt == NULL)
28783         return;
28784     if ((ctxt->user_sax != NULL) &&
28785         (ctxt->user_sax->startElementNs != NULL))
28786 	ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
28787 	                               URI, nb_namespaces, namespaces,
28788 				       nb_attributes, nb_defaulted,
28789 				       attributes);
28790     if (ctxt->ctxt != NULL)
28791 	xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
28792 	                                 URI, nb_namespaces, namespaces,
28793 					 nb_attributes, nb_defaulted,
28794 					 attributes);
28795 }
28796 
28797 static void
endElementNsSplit(void * ctx,const xmlChar * localname,const xmlChar * prefix,const xmlChar * URI)28798 endElementNsSplit(void *ctx, const xmlChar * localname,
28799 		    const xmlChar * prefix, const xmlChar * URI) {
28800     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28801     if (ctxt == NULL)
28802         return;
28803     if ((ctxt->user_sax != NULL) &&
28804         (ctxt->user_sax->endElementNs != NULL))
28805 	ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
28806     if (ctxt->ctxt != NULL)
28807 	xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
28808 }
28809 
28810 /**
28811  * xmlSchemaSAXPlug:
28812  * @ctxt:  a schema validation context
28813  * @sax:  a pointer to the original xmlSAXHandlerPtr
28814  * @user_data:  a pointer to the original SAX user data pointer
28815  *
28816  * Plug a SAX based validation layer in a SAX parsing event flow.
28817  * The original @saxptr and @dataptr data are replaced by new pointers
28818  * but the calls to the original will be maintained.
28819  *
28820  * Returns a pointer to a data structure needed to unplug the validation layer
28821  *         or NULL in case of errors.
28822  */
28823 xmlSchemaSAXPlugPtr
xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,xmlSAXHandlerPtr * sax,void ** user_data)28824 xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
28825 		 xmlSAXHandlerPtr *sax, void **user_data)
28826 {
28827     xmlSchemaSAXPlugPtr ret;
28828     xmlSAXHandlerPtr old_sax;
28829 
28830     if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
28831         return(NULL);
28832 
28833     /*
28834      * We only allow to plug into SAX2 event streams
28835      */
28836     old_sax = *sax;
28837     if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
28838         return(NULL);
28839     if ((old_sax != NULL) &&
28840         (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
28841         ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
28842         return(NULL);
28843 
28844     /*
28845      * everything seems right allocate the local data needed for that layer
28846      */
28847     ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
28848     if (ret == NULL) {
28849         return(NULL);
28850     }
28851     memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
28852     ret->magic = XML_SAX_PLUG_MAGIC;
28853     ret->schemas_sax.initialized = XML_SAX2_MAGIC;
28854     ret->ctxt = ctxt;
28855     ret->user_sax_ptr = sax;
28856     ret->user_sax = old_sax;
28857     if (old_sax == NULL) {
28858         /*
28859 	 * go direct, no need for the split block and functions.
28860 	 */
28861 	ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
28862 	ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
28863 	/*
28864 	 * Note that we use the same text-function for both, to prevent
28865 	 * the parser from testing for ignorable whitespace.
28866 	 */
28867 	ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
28868 	ret->schemas_sax.characters = xmlSchemaSAXHandleText;
28869 
28870 	ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
28871 	ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
28872 
28873 	ret->user_data = ctxt;
28874 	*user_data = ctxt;
28875     } else {
28876        /*
28877         * for each callback unused by Schemas initialize it to the Split
28878 	* routine only if non NULL in the user block, this can speed up
28879 	* things at the SAX level.
28880 	*/
28881         if (old_sax->internalSubset != NULL)
28882             ret->schemas_sax.internalSubset = internalSubsetSplit;
28883         if (old_sax->isStandalone != NULL)
28884             ret->schemas_sax.isStandalone = isStandaloneSplit;
28885         if (old_sax->hasInternalSubset != NULL)
28886             ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
28887         if (old_sax->hasExternalSubset != NULL)
28888             ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
28889         if (old_sax->resolveEntity != NULL)
28890             ret->schemas_sax.resolveEntity = resolveEntitySplit;
28891         if (old_sax->getEntity != NULL)
28892             ret->schemas_sax.getEntity = getEntitySplit;
28893         if (old_sax->entityDecl != NULL)
28894             ret->schemas_sax.entityDecl = entityDeclSplit;
28895         if (old_sax->notationDecl != NULL)
28896             ret->schemas_sax.notationDecl = notationDeclSplit;
28897         if (old_sax->attributeDecl != NULL)
28898             ret->schemas_sax.attributeDecl = attributeDeclSplit;
28899         if (old_sax->elementDecl != NULL)
28900             ret->schemas_sax.elementDecl = elementDeclSplit;
28901         if (old_sax->unparsedEntityDecl != NULL)
28902             ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
28903         if (old_sax->setDocumentLocator != NULL)
28904             ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
28905         if (old_sax->startDocument != NULL)
28906             ret->schemas_sax.startDocument = startDocumentSplit;
28907         if (old_sax->endDocument != NULL)
28908             ret->schemas_sax.endDocument = endDocumentSplit;
28909         if (old_sax->processingInstruction != NULL)
28910             ret->schemas_sax.processingInstruction = processingInstructionSplit;
28911         if (old_sax->comment != NULL)
28912             ret->schemas_sax.comment = commentSplit;
28913         if (old_sax->warning != NULL)
28914             ret->schemas_sax.warning = warningSplit;
28915         if (old_sax->error != NULL)
28916             ret->schemas_sax.error = errorSplit;
28917         if (old_sax->fatalError != NULL)
28918             ret->schemas_sax.fatalError = fatalErrorSplit;
28919         if (old_sax->getParameterEntity != NULL)
28920             ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
28921         if (old_sax->externalSubset != NULL)
28922             ret->schemas_sax.externalSubset = externalSubsetSplit;
28923 
28924 	/*
28925 	 * the 6 schemas callback have to go to the splitter functions
28926 	 * Note that we use the same text-function for ignorableWhitespace
28927 	 * if possible, to prevent the parser from testing for ignorable
28928 	 * whitespace.
28929 	 */
28930         ret->schemas_sax.characters = charactersSplit;
28931 	if ((old_sax->ignorableWhitespace != NULL) &&
28932 	    (old_sax->ignorableWhitespace != old_sax->characters))
28933 	    ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
28934 	else
28935 	    ret->schemas_sax.ignorableWhitespace = charactersSplit;
28936         ret->schemas_sax.cdataBlock = cdataBlockSplit;
28937         ret->schemas_sax.reference = referenceSplit;
28938         ret->schemas_sax.startElementNs = startElementNsSplit;
28939         ret->schemas_sax.endElementNs = endElementNsSplit;
28940 
28941 	ret->user_data_ptr = user_data;
28942 	ret->user_data = *user_data;
28943 	*user_data = ret;
28944     }
28945 
28946     /*
28947      * plug the pointers back.
28948      */
28949     *sax = &(ret->schemas_sax);
28950     ctxt->sax = *sax;
28951     ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28952     xmlSchemaPreRun(ctxt);
28953     return(ret);
28954 }
28955 
28956 /**
28957  * xmlSchemaSAXUnplug:
28958  * @plug:  a data structure returned by xmlSchemaSAXPlug
28959  *
28960  * Unplug a SAX based validation layer in a SAX parsing event flow.
28961  * The original pointers used in the call are restored.
28962  *
28963  * Returns 0 in case of success and -1 in case of failure.
28964  */
28965 int
xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)28966 xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
28967 {
28968     xmlSAXHandlerPtr *sax;
28969     void **user_data;
28970 
28971     if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
28972         return(-1);
28973     plug->magic = 0;
28974 
28975     xmlSchemaPostRun(plug->ctxt);
28976     /* restore the data */
28977     sax = plug->user_sax_ptr;
28978     *sax = plug->user_sax;
28979     if (plug->user_sax != NULL) {
28980 	user_data = plug->user_data_ptr;
28981 	*user_data = plug->user_data;
28982     }
28983 
28984     /* free and return */
28985     xmlFree(plug);
28986     return(0);
28987 }
28988 
28989 /**
28990  * xmlSchemaValidateSetLocator:
28991  * @vctxt: a schema validation context
28992  * @f: the locator function pointer
28993  * @ctxt: the locator context
28994  *
28995  * Allows to set a locator function to the validation context,
28996  * which will be used to provide file and line information since
28997  * those are not provided as part of the SAX validation flow
28998  * Setting @f to NULL disable the locator.
28999  */
29000 
29001 void
xmlSchemaValidateSetLocator(xmlSchemaValidCtxtPtr vctxt,xmlSchemaValidityLocatorFunc f,void * ctxt)29002 xmlSchemaValidateSetLocator(xmlSchemaValidCtxtPtr vctxt,
29003                             xmlSchemaValidityLocatorFunc f,
29004 			    void *ctxt)
29005 {
29006     if (vctxt == NULL) return;
29007     vctxt->locFunc = f;
29008     vctxt->locCtxt = ctxt;
29009 }
29010 
29011 /**
29012  * xmlSchemaValidateStreamLocator:
29013  * @ctx: the xmlTextReaderPtr used
29014  * @file: returned file information
29015  * @line: returned line information
29016  *
29017  * Internal locator function for the readers
29018  *
29019  * Returns 0 in case the Schema validation could be (de)activated and
29020  *         -1 in case of error.
29021  */
29022 static int
xmlSchemaValidateStreamLocator(void * ctx,const char ** file,unsigned long * line)29023 xmlSchemaValidateStreamLocator(void *ctx, const char **file,
29024                                unsigned long *line) {
29025     xmlParserCtxtPtr ctxt;
29026 
29027     if ((ctx == NULL) || ((file == NULL) && (line == NULL)))
29028         return(-1);
29029 
29030     if (file != NULL)
29031         *file = NULL;
29032     if (line != NULL)
29033         *line = 0;
29034 
29035     ctxt = (xmlParserCtxtPtr) ctx;
29036     if (ctxt->input != NULL) {
29037        if (file != NULL)
29038            *file = ctxt->input->filename;
29039        if (line != NULL)
29040            *line = ctxt->input->line;
29041        return(0);
29042     }
29043     return(-1);
29044 }
29045 
29046 /**
29047  * xmlSchemaValidateStream:
29048  * @ctxt:  a schema validation context
29049  * @input:  the input to use for reading the data
29050  * @enc:  an optional encoding information
29051  * @sax:  a SAX handler for the resulting events
29052  * @user_data:  the context to provide to the SAX handler.
29053  *
29054  * Validate an input based on a flow of SAX event from the parser
29055  * and forward the events to the @sax handler with the provided @user_data
29056  * the user provided @sax handler must be a SAX2 one.
29057  *
29058  * Returns 0 if the document is schemas valid, a positive error code
29059  *     number otherwise and -1 in case of internal or API error.
29060  */
29061 int
xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,xmlParserInputBufferPtr input,xmlCharEncoding enc,xmlSAXHandlerPtr sax,void * user_data)29062 xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
29063                         xmlParserInputBufferPtr input, xmlCharEncoding enc,
29064                         xmlSAXHandlerPtr sax, void *user_data)
29065 {
29066     xmlSchemaSAXPlugPtr plug = NULL;
29067     xmlSAXHandlerPtr old_sax = NULL;
29068     xmlParserCtxtPtr pctxt = NULL;
29069     xmlParserInputPtr inputStream = NULL;
29070     int ret;
29071 
29072     if ((ctxt == NULL) || (input == NULL))
29073         return (-1);
29074 
29075     /*
29076      * prepare the parser
29077      */
29078     pctxt = xmlNewParserCtxt();
29079     if (pctxt == NULL)
29080         return (-1);
29081     old_sax = pctxt->sax;
29082     pctxt->sax = sax;
29083     pctxt->userData = user_data;
29084 #if 0
29085     if (options)
29086         xmlCtxtUseOptions(pctxt, options);
29087 #endif
29088     pctxt->linenumbers = 1;
29089     xmlSchemaValidateSetLocator(ctxt, xmlSchemaValidateStreamLocator, pctxt);
29090 
29091     inputStream = xmlNewIOInputStream(pctxt, input, enc);;
29092     if (inputStream == NULL) {
29093         ret = -1;
29094 	goto done;
29095     }
29096     inputPush(pctxt, inputStream);
29097     ctxt->parserCtxt = pctxt;
29098     ctxt->input = input;
29099 
29100     /*
29101      * Plug the validation and launch the parsing
29102      */
29103     plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
29104     if (plug == NULL) {
29105         ret = -1;
29106 	goto done;
29107     }
29108     ctxt->input = input;
29109     ctxt->enc = enc;
29110     ctxt->sax = pctxt->sax;
29111     ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
29112     ret = xmlSchemaVStart(ctxt);
29113 
29114     if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
29115 	ret = ctxt->parserCtxt->errNo;
29116 	if (ret == 0)
29117 	    ret = 1;
29118     }
29119 
29120 done:
29121     ctxt->parserCtxt = NULL;
29122     ctxt->sax = NULL;
29123     ctxt->input = NULL;
29124     if (plug != NULL) {
29125         xmlSchemaSAXUnplug(plug);
29126     }
29127     /* cleanup */
29128     if (pctxt != NULL) {
29129 	pctxt->sax = old_sax;
29130 	xmlFreeParserCtxt(pctxt);
29131     }
29132     return (ret);
29133 }
29134 
29135 /**
29136  * xmlSchemaValidateFile:
29137  * @ctxt: a schema validation context
29138  * @filename: the URI of the instance
29139  * @options: a future set of options, currently unused
29140  *
29141  * Do a schemas validation of the given resource, it will use the
29142  * SAX streamable validation internally.
29143  *
29144  * Returns 0 if the document is valid, a positive error code
29145  *     number otherwise and -1 in case of an internal or API error.
29146  */
29147 int
xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,const char * filename,int options ATTRIBUTE_UNUSED)29148 xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
29149                       const char * filename,
29150 		      int options ATTRIBUTE_UNUSED)
29151 {
29152     int ret;
29153     xmlParserInputBufferPtr input;
29154 
29155     if ((ctxt == NULL) || (filename == NULL))
29156         return (-1);
29157 
29158     input = xmlParserInputBufferCreateFilename(filename,
29159 	XML_CHAR_ENCODING_NONE);
29160     if (input == NULL)
29161 	return (-1);
29162     ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
29163 	NULL, NULL);
29164     return (ret);
29165 }
29166 
29167 /**
29168  * xmlSchemaValidCtxtGetParserCtxt:
29169  * @ctxt: a schema validation context
29170  *
29171  * allow access to the parser context of the schema validation context
29172  *
29173  * Returns the parser context of the schema validation context or NULL
29174  *         in case of error.
29175  */
29176 xmlParserCtxtPtr
xmlSchemaValidCtxtGetParserCtxt(xmlSchemaValidCtxtPtr ctxt)29177 xmlSchemaValidCtxtGetParserCtxt(xmlSchemaValidCtxtPtr ctxt)
29178 {
29179     if (ctxt == NULL)
29180         return(NULL);
29181     return (ctxt->parserCtxt);
29182 }
29183 
29184 #define bottom_xmlschemas
29185 #include "elfgcchack.h"
29186 #endif /* LIBXML_SCHEMAS_ENABLED */
29187