• 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 #include "private/error.h"
80 #include "private/memory.h"
81 #include "private/parser.h"
82 #include "private/string.h"
83 
84 /* #define WXS_ELEM_DECL_CONS_ENABLED */
85 
86 /* #define ENABLE_PARTICLE_RESTRICTION 1 */
87 
88 #define ENABLE_REDEFINE
89 
90 /* #define ENABLE_NAMED_LOCALS */
91 
92 /* #define ENABLE_IDC_NODE_TABLES_TEST */
93 
94 #define DUMP_CONTENT_MODEL
95 
96 #ifdef LIBXML_READER_ENABLED
97 /* #define XML_SCHEMA_READER_ENABLED */
98 #endif
99 
100 #define UNBOUNDED (1 << 30)
101 
102 #define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
103 
104 /*
105  * The XML Schemas namespaces
106  */
107 static const xmlChar *xmlSchemaNs = (const xmlChar *)
108     "http://www.w3.org/2001/XMLSchema";
109 
110 static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
111     "http://www.w3.org/2001/XMLSchema-instance";
112 
113 static const xmlChar *xmlNamespaceNs = (const xmlChar *)
114     "http://www.w3.org/2000/xmlns/";
115 
116 /*
117 * Come casting macros.
118 */
119 #define ACTXT_CAST (xmlSchemaAbstractCtxtPtr)
120 #define PCTXT_CAST (xmlSchemaParserCtxtPtr)
121 #define VCTXT_CAST (xmlSchemaValidCtxtPtr)
122 #define WXS_BASIC_CAST (xmlSchemaBasicItemPtr)
123 #define WXS_TREE_CAST (xmlSchemaTreeItemPtr)
124 #define WXS_PTC_CAST (xmlSchemaParticlePtr)
125 #define WXS_TYPE_CAST (xmlSchemaTypePtr)
126 #define WXS_ELEM_CAST (xmlSchemaElementPtr)
127 #define WXS_ATTR_GROUP_CAST (xmlSchemaAttributeGroupPtr)
128 #define WXS_ATTR_CAST (xmlSchemaAttributePtr)
129 #define WXS_ATTR_USE_CAST (xmlSchemaAttributeUsePtr)
130 #define WXS_ATTR_PROHIB_CAST (xmlSchemaAttributeUseProhibPtr)
131 #define WXS_MODEL_GROUPDEF_CAST (xmlSchemaModelGroupDefPtr)
132 #define WXS_MODEL_GROUP_CAST (xmlSchemaModelGroupPtr)
133 #define WXS_IDC_CAST (xmlSchemaIDCPtr)
134 #define WXS_QNAME_CAST (xmlSchemaQNameRefPtr)
135 #define WXS_LIST_CAST (xmlSchemaItemListPtr)
136 
137 /*
138 * Macros to query common properties of components.
139 */
140 #define WXS_ITEM_NODE(i) xmlSchemaGetComponentNode(WXS_BASIC_CAST (i))
141 
142 #define WXS_ITEM_TYPE_NAME(i) xmlSchemaGetComponentTypeStr(WXS_BASIC_CAST (i))
143 /*
144 * Macros for element declarations.
145 */
146 #define WXS_ELEM_TYPEDEF(e) (e)->subtypes
147 
148 #define WXS_SUBST_HEAD(item) (item)->refDecl
149 /*
150 * Macros for attribute declarations.
151 */
152 #define WXS_ATTR_TYPEDEF(a) (a)->subtypes
153 /*
154 * Macros for attribute uses.
155 */
156 #define WXS_ATTRUSE_DECL(au) (WXS_ATTR_USE_CAST (au))->attrDecl
157 
158 #define WXS_ATTRUSE_TYPEDEF(au) WXS_ATTR_TYPEDEF(WXS_ATTRUSE_DECL( WXS_ATTR_USE_CAST au))
159 
160 #define WXS_ATTRUSE_DECL_NAME(au) (WXS_ATTRUSE_DECL(au))->name
161 
162 #define WXS_ATTRUSE_DECL_TNS(au) (WXS_ATTRUSE_DECL(au))->targetNamespace
163 /*
164 * Macros for attribute groups.
165 */
166 #define WXS_ATTR_GROUP_HAS_REFS(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS)
167 #define WXS_ATTR_GROUP_EXPANDED(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED)
168 /*
169 * Macros for particles.
170 */
171 #define WXS_PARTICLE(p) WXS_PTC_CAST (p)
172 
173 #define WXS_PARTICLE_TERM(p) (WXS_PARTICLE(p))->children
174 
175 #define WXS_PARTICLE_TERM_AS_ELEM(p) (WXS_ELEM_CAST WXS_PARTICLE_TERM(p))
176 
177 #define WXS_PARTICLE_MODEL(p) WXS_MODEL_GROUP_CAST WXS_PARTICLE(p)->children
178 /*
179 * Macros for model groups definitions.
180 */
181 #define WXS_MODELGROUPDEF_MODEL(mgd) (WXS_MODEL_GROUP_CAST (mgd))->children
182 /*
183 * Macros for model groups.
184 */
185 #define WXS_IS_MODEL_GROUP(i) \
186     (((i)->type == XML_SCHEMA_TYPE_SEQUENCE) || \
187      ((i)->type == XML_SCHEMA_TYPE_CHOICE) || \
188      ((i)->type == XML_SCHEMA_TYPE_ALL))
189 
190 #define WXS_MODELGROUP_PARTICLE(mg) WXS_PTC_CAST (mg)->children
191 /*
192 * Macros for schema buckets.
193 */
194 #define WXS_IS_BUCKET_INCREDEF(t) (((t) == XML_SCHEMA_SCHEMA_INCLUDE) || \
195     ((t) == XML_SCHEMA_SCHEMA_REDEFINE))
196 
197 #define WXS_IS_BUCKET_IMPMAIN(t) (((t) == XML_SCHEMA_SCHEMA_MAIN) || \
198     ((t) == XML_SCHEMA_SCHEMA_IMPORT))
199 
200 #define WXS_IMPBUCKET(b) ((xmlSchemaImportPtr) (b))
201 
202 #define WXS_INCBUCKET(b) ((xmlSchemaIncludePtr) (b))
203 /*
204 * Macros for complex/simple types.
205 */
206 #define WXS_IS_ANYTYPE(i) \
207      (( (i)->type == XML_SCHEMA_TYPE_BASIC) && \
208       ( (WXS_TYPE_CAST (i))->builtInType == XML_SCHEMAS_ANYTYPE))
209 
210 #define WXS_IS_COMPLEX(i) \
211     (((i)->type == XML_SCHEMA_TYPE_COMPLEX) || \
212      ((i)->builtInType == XML_SCHEMAS_ANYTYPE))
213 
214 #define WXS_IS_SIMPLE(item) \
215     ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
216      ((item->type == XML_SCHEMA_TYPE_BASIC) && \
217       (item->builtInType != XML_SCHEMAS_ANYTYPE)))
218 
219 #define WXS_IS_ANY_SIMPLE_TYPE(i) \
220     (((i)->type == XML_SCHEMA_TYPE_BASIC) && \
221       ((i)->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
222 
223 #define WXS_IS_RESTRICTION(t) \
224     ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)
225 
226 #define WXS_IS_EXTENSION(t) \
227     ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
228 
229 #define WXS_IS_TYPE_NOT_FIXED(i) \
230     (((i)->type != XML_SCHEMA_TYPE_BASIC) && \
231      (((i)->flags & XML_SCHEMAS_TYPE_INTERNAL_RESOLVED) == 0))
232 
233 #define WXS_IS_TYPE_NOT_FIXED_1(item) \
234     (((item)->type != XML_SCHEMA_TYPE_BASIC) && \
235      (((item)->flags & XML_SCHEMAS_TYPE_FIXUP_1) == 0))
236 
237 #define WXS_TYPE_IS_GLOBAL(t) ((t)->flags & XML_SCHEMAS_TYPE_GLOBAL)
238 
239 #define WXS_TYPE_IS_LOCAL(t) (((t)->flags & XML_SCHEMAS_TYPE_GLOBAL) == 0)
240 /*
241 * Macros for exclusively for complex types.
242 */
243 #define WXS_HAS_COMPLEX_CONTENT(item) \
244     ((item->contentType == XML_SCHEMA_CONTENT_MIXED) || \
245      (item->contentType == XML_SCHEMA_CONTENT_EMPTY) || \
246      (item->contentType == XML_SCHEMA_CONTENT_ELEMENTS))
247 
248 #define WXS_HAS_SIMPLE_CONTENT(item) \
249     ((item->contentType == XML_SCHEMA_CONTENT_SIMPLE) || \
250      (item->contentType == XML_SCHEMA_CONTENT_BASIC))
251 
252 #define WXS_HAS_MIXED_CONTENT(item) \
253     (item->contentType == XML_SCHEMA_CONTENT_MIXED)
254 
255 #define WXS_EMPTIABLE(t) \
256     (xmlSchemaIsParticleEmptiable(WXS_PTC_CAST (t)->subtypes))
257 
258 #define WXS_TYPE_CONTENTTYPE(t) (t)->subtypes
259 
260 #define WXS_TYPE_PARTICLE(t) WXS_PTC_CAST (t)->subtypes
261 
262 #define WXS_TYPE_PARTICLE_TERM(t) WXS_PARTICLE_TERM(WXS_TYPE_PARTICLE(t))
263 /*
264 * Macros for exclusively for simple types.
265 */
266 #define WXS_LIST_ITEMTYPE(t) (t)->subtypes
267 
268 #define WXS_IS_ATOMIC(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
269 
270 #define WXS_IS_LIST(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
271 
272 #define WXS_IS_UNION(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)
273 /*
274 * Misc parser context macros.
275 */
276 #define WXS_CONSTRUCTOR(ctx) (ctx)->constructor
277 
278 #define WXS_HAS_BUCKETS(ctx) \
279 ( (WXS_CONSTRUCTOR((ctx))->buckets != NULL) && \
280 (WXS_CONSTRUCTOR((ctx))->buckets->nbItems > 0) )
281 
282 #define WXS_SUBST_GROUPS(ctx) WXS_CONSTRUCTOR((ctx))->substGroups
283 
284 #define WXS_BUCKET(ctx) WXS_CONSTRUCTOR((ctx))->bucket
285 
286 #define WXS_SCHEMA(ctx) (ctx)->schema
287 
288 #define WXS_ADD_LOCAL(ctx, item) \
289     do { \
290         if ((item != NULL) && \
291             (xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->locals), 10, \
292                                   item) < 0)) { \
293             xmlSchemaPErrMemory(ctx); \
294             xmlFree(item); \
295             item = NULL; \
296         } \
297     } while (0)
298 
299 #define WXS_ADD_GLOBAL(ctx, item) \
300     do { \
301         if ((item != NULL) && \
302             (xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->globals), 5, \
303                                   item) < 0)) { \
304             xmlSchemaPErrMemory(ctx); \
305             xmlFree(item); \
306             item = NULL; \
307         } \
308     } while (0)
309 
310 #define WXS_ADD_PENDING(ctx, item) \
311     do { \
312         if ((item != NULL) && \
313             (xmlSchemaAddItemSize(&((ctx)->constructor->pending), 10, \
314                                   item) < 0)) { \
315             xmlSchemaPErrMemory(ctx); \
316         } \
317     } while (0)
318 /*
319 * xmlSchemaItemList macros.
320 */
321 #define WXS_ILIST_IS_EMPTY(l) ((l == NULL) || ((l)->nbItems == 0))
322 /*
323 * Misc macros.
324 */
325 #define IS_SCHEMA(node, type) \
326    ((node != NULL) && (node->ns != NULL) && \
327     (xmlStrEqual(node->name, (const xmlChar *) type)) && \
328     (xmlStrEqual(node->ns->href, xmlSchemaNs)))
329 
330 #define FREE_AND_NULL(str) if ((str) != NULL) { xmlFree((xmlChar *) (str)); str = NULL; }
331 
332 /*
333 * Since we put the default/fixed values into the dict, we can
334 * use pointer comparison for those values.
335 * REMOVED: (xmlStrEqual((v1), (v2)))
336 */
337 #define WXS_ARE_DEFAULT_STR_EQUAL(v1, v2) ((v1) == (v2))
338 
339 #define INODE_NILLED(item) (item->flags & XML_SCHEMA_ELEM_INFO_NILLED)
340 
341 #define CAN_PARSE_SCHEMA(b) (((b)->doc != NULL) && ((b)->parsed == 0))
342 
343 #define HFAILURE if (res == -1) goto exit_failure;
344 
345 #define HERROR if (res != 0) goto exit_error;
346 
347 #define HSTOP(ctx) if ((ctx)->stop) goto exit;
348 /*
349 * Some flags used for various schema constraints.
350 */
351 #define SUBSET_RESTRICTION  1<<0
352 #define SUBSET_EXTENSION    1<<1
353 #define SUBSET_SUBSTITUTION 1<<2
354 #define SUBSET_LIST         1<<3
355 #define SUBSET_UNION        1<<4
356 
357 typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
358 typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
359 
360 typedef struct _xmlSchemaItemList xmlSchemaItemList;
361 typedef xmlSchemaItemList *xmlSchemaItemListPtr;
362 struct _xmlSchemaItemList {
363     void **items;  /* used for dynamic addition of schemata */
364     int nbItems; /* used for dynamic addition of schemata */
365     int sizeItems; /* used for dynamic addition of schemata */
366 };
367 
368 #define XML_SCHEMA_CTXT_PARSER 1
369 #define XML_SCHEMA_CTXT_VALIDATOR 2
370 
371 typedef struct _xmlSchemaAbstractCtxt xmlSchemaAbstractCtxt;
372 typedef xmlSchemaAbstractCtxt *xmlSchemaAbstractCtxtPtr;
373 struct _xmlSchemaAbstractCtxt {
374     int type; /* E.g. XML_SCHEMA_CTXT_VALIDATOR */
375     void *dummy; /* Fix alignment issues */
376 };
377 
378 typedef struct _xmlSchemaBucket xmlSchemaBucket;
379 typedef xmlSchemaBucket *xmlSchemaBucketPtr;
380 
381 #define XML_SCHEMA_SCHEMA_MAIN 0
382 #define XML_SCHEMA_SCHEMA_IMPORT 1
383 #define XML_SCHEMA_SCHEMA_INCLUDE 2
384 #define XML_SCHEMA_SCHEMA_REDEFINE 3
385 
386 /**
387  * xmlSchemaSchemaRelation:
388  *
389  * Used to create a graph of schema relationships.
390  */
391 typedef struct _xmlSchemaSchemaRelation xmlSchemaSchemaRelation;
392 typedef xmlSchemaSchemaRelation *xmlSchemaSchemaRelationPtr;
393 struct _xmlSchemaSchemaRelation {
394     xmlSchemaSchemaRelationPtr next;
395     int type; /* E.g. XML_SCHEMA_SCHEMA_IMPORT */
396     const xmlChar *importNamespace;
397     xmlSchemaBucketPtr bucket;
398 };
399 
400 #define XML_SCHEMA_BUCKET_MARKED 1<<0
401 #define XML_SCHEMA_BUCKET_COMPS_ADDED 1<<1
402 
403 struct _xmlSchemaBucket {
404     int type;
405     int flags;
406     const xmlChar *schemaLocation;
407     const xmlChar *origTargetNamespace;
408     const xmlChar *targetNamespace;
409     xmlDocPtr doc;
410     xmlSchemaSchemaRelationPtr relations;
411     int located;
412     int parsed;
413     int imported;
414     int preserveDoc;
415     xmlSchemaItemListPtr globals; /* Global components. */
416     xmlSchemaItemListPtr locals; /* Local components. */
417 };
418 
419 /**
420  * xmlSchemaImport:
421  * (extends xmlSchemaBucket)
422  *
423  * Reflects a schema. Holds some information
424  * about the schema and its toplevel components. Duplicate
425  * toplevel components are not checked at this level.
426  */
427 typedef struct _xmlSchemaImport xmlSchemaImport;
428 typedef xmlSchemaImport *xmlSchemaImportPtr;
429 struct _xmlSchemaImport {
430     int type; /* Main OR import OR include. */
431     int flags;
432     const xmlChar *schemaLocation; /* The URI of the schema document. */
433     /* For chameleon includes, @origTargetNamespace will be NULL */
434     const xmlChar *origTargetNamespace;
435     /*
436     * For chameleon includes, @targetNamespace will be the
437     * targetNamespace of the including schema.
438     */
439     const xmlChar *targetNamespace;
440     xmlDocPtr doc; /* The schema node-tree. */
441     /* @relations will hold any included/imported/redefined schemas. */
442     xmlSchemaSchemaRelationPtr relations;
443     int located;
444     int parsed;
445     int imported;
446     int preserveDoc;
447     xmlSchemaItemListPtr globals;
448     xmlSchemaItemListPtr locals;
449     /* The imported schema. */
450     xmlSchemaPtr schema;
451 };
452 
453 /*
454 * (extends xmlSchemaBucket)
455 */
456 typedef struct _xmlSchemaInclude xmlSchemaInclude;
457 typedef xmlSchemaInclude *xmlSchemaIncludePtr;
458 struct _xmlSchemaInclude {
459     int type;
460     int flags;
461     const xmlChar *schemaLocation;
462     const xmlChar *origTargetNamespace;
463     const xmlChar *targetNamespace;
464     xmlDocPtr doc;
465     xmlSchemaSchemaRelationPtr relations;
466     int located;
467     int parsed;
468     int imported;
469     int preserveDoc;
470     xmlSchemaItemListPtr globals; /* Global components. */
471     xmlSchemaItemListPtr locals; /* Local components. */
472 
473     /* The owning main or import schema bucket. */
474     xmlSchemaImportPtr ownerImport;
475 };
476 
477 /**
478  * xmlSchemaBasicItem:
479  *
480  * The abstract base type for schema components.
481  */
482 typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
483 typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
484 struct _xmlSchemaBasicItem {
485     xmlSchemaTypeType type;
486     void *dummy; /* Fix alignment issues */
487 };
488 
489 /**
490  * xmlSchemaAnnotItem:
491  *
492  * The abstract base type for annotated schema components.
493  * (Extends xmlSchemaBasicItem)
494  */
495 typedef struct _xmlSchemaAnnotItem xmlSchemaAnnotItem;
496 typedef xmlSchemaAnnotItem *xmlSchemaAnnotItemPtr;
497 struct _xmlSchemaAnnotItem {
498     xmlSchemaTypeType type;
499     xmlSchemaAnnotPtr annot;
500 };
501 
502 /**
503  * xmlSchemaTreeItem:
504  *
505  * The abstract base type for tree-like structured schema components.
506  * (Extends xmlSchemaAnnotItem)
507  */
508 typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
509 typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
510 struct _xmlSchemaTreeItem {
511     xmlSchemaTypeType type;
512     xmlSchemaAnnotPtr annot;
513     xmlSchemaTreeItemPtr next;
514     xmlSchemaTreeItemPtr children;
515 };
516 
517 
518 #define XML_SCHEMA_ATTR_USE_FIXED 1<<0
519 /**
520  * xmlSchemaAttributeUsePtr:
521  *
522  * The abstract base type for tree-like structured schema components.
523  * (Extends xmlSchemaTreeItem)
524  */
525 typedef struct _xmlSchemaAttributeUse xmlSchemaAttributeUse;
526 typedef xmlSchemaAttributeUse *xmlSchemaAttributeUsePtr;
527 struct _xmlSchemaAttributeUse {
528     xmlSchemaTypeType type;
529     xmlSchemaAnnotPtr annot;
530     xmlSchemaAttributeUsePtr next; /* The next attr. use. */
531     /*
532     * The attr. decl. OR a QName-ref. to an attr. decl. OR
533     * a QName-ref. to an attribute group definition.
534     */
535     xmlSchemaAttributePtr attrDecl;
536 
537     int flags;
538     xmlNodePtr node;
539     int occurs; /* required, optional */
540     const xmlChar * defValue;
541     xmlSchemaValPtr defVal;
542 };
543 
544 /**
545  * xmlSchemaAttributeUseProhibPtr:
546  *
547  * A helper component to reflect attribute prohibitions.
548  * (Extends xmlSchemaBasicItem)
549  */
550 typedef struct _xmlSchemaAttributeUseProhib xmlSchemaAttributeUseProhib;
551 typedef xmlSchemaAttributeUseProhib *xmlSchemaAttributeUseProhibPtr;
552 struct _xmlSchemaAttributeUseProhib {
553     xmlSchemaTypeType type; /* == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB */
554     xmlNodePtr node;
555     const xmlChar *name;
556     const xmlChar *targetNamespace;
557     int isRef;
558 };
559 
560 /**
561  * xmlSchemaRedef:
562  */
563 typedef struct _xmlSchemaRedef xmlSchemaRedef;
564 typedef xmlSchemaRedef *xmlSchemaRedefPtr;
565 struct _xmlSchemaRedef {
566     xmlSchemaRedefPtr next;
567     xmlSchemaBasicItemPtr item; /* The redefining component. */
568     xmlSchemaBasicItemPtr reference; /* The referencing component. */
569     xmlSchemaBasicItemPtr target; /* The to-be-redefined component. */
570     const xmlChar *refName; /* The name of the to-be-redefined component. */
571     const xmlChar *refTargetNs; /* The target namespace of the
572                                    to-be-redefined comp. */
573     xmlSchemaBucketPtr targetBucket; /* The redefined schema. */
574 };
575 
576 /**
577  * xmlSchemaConstructionCtxt:
578  */
579 typedef struct _xmlSchemaConstructionCtxt xmlSchemaConstructionCtxt;
580 typedef xmlSchemaConstructionCtxt *xmlSchemaConstructionCtxtPtr;
581 struct _xmlSchemaConstructionCtxt {
582     xmlSchemaPtr mainSchema; /* The main schema. */
583     xmlSchemaBucketPtr mainBucket; /* The main schema bucket */
584     xmlDictPtr dict;
585     xmlSchemaItemListPtr buckets; /* List of schema buckets. */
586     /* xmlSchemaItemListPtr relations; */ /* List of schema relations. */
587     xmlSchemaBucketPtr bucket; /* The current schema bucket */
588     xmlSchemaItemListPtr pending; /* All Components of all schemas that
589                                      need to be fixed. */
590     xmlHashTablePtr substGroups;
591     xmlSchemaRedefPtr redefs;
592     xmlSchemaRedefPtr lastRedef;
593 };
594 
595 #define XML_SCHEMAS_PARSE_ERROR		1
596 #define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
597 
598 struct _xmlSchemaParserCtxt {
599     int type;
600     void *errCtxt;             /* user specific error context */
601     xmlSchemaValidityErrorFunc error;   /* the callback in case of errors */
602     xmlSchemaValidityWarningFunc warning;       /* the callback in case of warning */
603     int err;
604     int nberrors;
605     xmlStructuredErrorFunc serror;
606 
607     xmlSchemaConstructionCtxtPtr constructor;
608     int ownsConstructor; /* TODO: Move this to parser *flags*. */
609 
610     /* xmlSchemaPtr topschema;	*/
611     /* xmlHashTablePtr namespaces;  */
612 
613     xmlSchemaPtr schema;        /* The main schema in use */
614     int counter;
615 
616     const xmlChar *URL;
617     xmlDocPtr doc;
618     int preserve;		/* Whether the doc should be freed  */
619 
620     const char *buffer;
621     int size;
622 
623     /*
624      * Used to build complex element content models
625      */
626     xmlAutomataPtr am;
627     xmlAutomataStatePtr start;
628     xmlAutomataStatePtr end;
629     xmlAutomataStatePtr state;
630 
631     xmlDictPtr dict;		/* dictionary for interned string names */
632     xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
633     int options;
634     xmlSchemaValidCtxtPtr vctxt;
635     int isS4S;
636     int isRedefine;
637     int xsiAssemble;
638     int stop; /* If the parser should stop; i.e. a critical error. */
639     const xmlChar *targetNamespace;
640     xmlSchemaBucketPtr redefined; /* The schema to be redefined. */
641 
642     xmlSchemaRedefPtr redef; /* Used for redefinitions. */
643     int redefCounter; /* Used for redefinitions. */
644     xmlSchemaItemListPtr attrProhibs;
645 
646     xmlResourceLoader resourceLoader;
647     void *resourceCtxt;
648 };
649 
650 /**
651  * xmlSchemaQNameRef:
652  *
653  * A component reference item (not a schema component)
654  * (Extends xmlSchemaBasicItem)
655  */
656 typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef;
657 typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr;
658 struct _xmlSchemaQNameRef {
659     xmlSchemaTypeType type;
660     xmlSchemaBasicItemPtr item; /* The resolved referenced item. */
661     xmlSchemaTypeType itemType;
662     const xmlChar *name;
663     const xmlChar *targetNamespace;
664     xmlNodePtr node;
665 };
666 
667 /**
668  * xmlSchemaParticle:
669  *
670  * A particle component.
671  * (Extends xmlSchemaTreeItem)
672  */
673 typedef struct _xmlSchemaParticle xmlSchemaParticle;
674 typedef xmlSchemaParticle *xmlSchemaParticlePtr;
675 struct _xmlSchemaParticle {
676     xmlSchemaTypeType type;
677     xmlSchemaAnnotPtr annot;
678     xmlSchemaTreeItemPtr next; /* next particle */
679     xmlSchemaTreeItemPtr children; /* the "term" (e.g. a model group,
680 	a group definition, a XML_SCHEMA_EXTRA_QNAMEREF (if a reference),
681         etc.) */
682     int minOccurs;
683     int maxOccurs;
684     xmlNodePtr node;
685 };
686 
687 /**
688  * xmlSchemaModelGroup:
689  *
690  * A model group component.
691  * (Extends xmlSchemaTreeItem)
692  */
693 typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
694 typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
695 struct _xmlSchemaModelGroup {
696     xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_SEQUENCE, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL */
697     xmlSchemaAnnotPtr annot;
698     xmlSchemaTreeItemPtr next; /* not used */
699     xmlSchemaTreeItemPtr children; /* first particle (OR "element decl" OR "wildcard") */
700     xmlNodePtr node;
701 };
702 
703 #define XML_SCHEMA_MODEL_GROUP_DEF_MARKED 1<<0
704 #define XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED 1<<1
705 /**
706  * xmlSchemaModelGroupDef:
707  *
708  * A model group definition component.
709  * (Extends xmlSchemaTreeItem)
710  */
711 typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
712 typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
713 struct _xmlSchemaModelGroupDef {
714     xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_GROUP */
715     xmlSchemaAnnotPtr annot;
716     xmlSchemaTreeItemPtr next; /* not used */
717     xmlSchemaTreeItemPtr children; /* the "model group" */
718     const xmlChar *name;
719     const xmlChar *targetNamespace;
720     xmlNodePtr node;
721     int flags;
722 };
723 
724 typedef struct _xmlSchemaIDC xmlSchemaIDC;
725 typedef xmlSchemaIDC *xmlSchemaIDCPtr;
726 
727 /**
728  * xmlSchemaIDCSelect:
729  *
730  * The identity-constraint "field" and "selector" item, holding the
731  * XPath expression.
732  */
733 typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
734 typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
735 struct _xmlSchemaIDCSelect {
736     xmlSchemaIDCSelectPtr next;
737     xmlSchemaIDCPtr idc;
738     int index; /* an index position if significant for IDC key-sequences */
739     const xmlChar *xpath; /* the XPath expression */
740     void *xpathComp; /* the compiled XPath expression */
741 };
742 
743 /**
744  * xmlSchemaIDC:
745  *
746  * The identity-constraint definition component.
747  * (Extends xmlSchemaAnnotItem)
748  */
749 
750 struct _xmlSchemaIDC {
751     xmlSchemaTypeType type;
752     xmlSchemaAnnotPtr annot;
753     xmlSchemaIDCPtr next;
754     xmlNodePtr node;
755     const xmlChar *name;
756     const xmlChar *targetNamespace;
757     xmlSchemaIDCSelectPtr selector;
758     xmlSchemaIDCSelectPtr fields;
759     int nbFields;
760     xmlSchemaQNameRefPtr ref;
761 };
762 
763 /**
764  * xmlSchemaIDCAug:
765  *
766  * The augmented IDC information used for validation.
767  */
768 typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
769 typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
770 struct _xmlSchemaIDCAug {
771     xmlSchemaIDCAugPtr next; /* next in a list */
772     xmlSchemaIDCPtr def; /* the IDC definition */
773     int keyrefDepth; /* the lowest tree level to which IDC
774                         tables need to be bubbled upwards */
775 };
776 
777 /**
778  * xmlSchemaPSVIIDCKeySequence:
779  *
780  * The key sequence of a node table item.
781  */
782 typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
783 typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
784 struct _xmlSchemaPSVIIDCKey {
785     xmlSchemaTypePtr type;
786     xmlSchemaValPtr val;
787 };
788 
789 /**
790  * xmlSchemaPSVIIDCNode:
791  *
792  * The node table item of a node table.
793  */
794 typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
795 typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
796 struct _xmlSchemaPSVIIDCNode {
797     xmlNodePtr node;
798     xmlSchemaPSVIIDCKeyPtr *keys;
799     int nodeLine;
800     int nodeQNameID;
801 
802 };
803 
804 /**
805  * xmlSchemaPSVIIDCBinding:
806  *
807  * The identity-constraint binding item of the [identity-constraint table].
808  */
809 typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
810 typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
811 struct _xmlSchemaPSVIIDCBinding {
812     xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
813     xmlSchemaIDCPtr definition; /* the IDC definition */
814     xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
815     int nbNodes; /* number of entries in the node table */
816     int sizeNodes; /* size of the node table */
817     xmlSchemaItemListPtr dupls;
818 };
819 
820 
821 #define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
822 #define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
823 
824 #define XPATH_STATE_OBJ_MATCHES -2
825 #define XPATH_STATE_OBJ_BLOCKED -3
826 
827 typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
828 typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
829 
830 /**
831  * xmlSchemaIDCStateObj:
832  *
833  * The state object used to evaluate XPath expressions.
834  */
835 typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
836 typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
837 struct _xmlSchemaIDCStateObj {
838     int type;
839     xmlSchemaIDCStateObjPtr next; /* next if in a list */
840     int depth; /* depth of creation */
841     int *history; /* list of (depth, state-id) tuples */
842     int nbHistory;
843     int sizeHistory;
844     xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
845                                        matcher */
846     xmlSchemaIDCSelectPtr sel;
847     void *xpathCtxt;
848 };
849 
850 #define IDC_MATCHER 0
851 
852 /**
853  * xmlSchemaIDCMatcher:
854  *
855  * Used to evaluate IDC selectors (and fields).
856  */
857 struct _xmlSchemaIDCMatcher {
858     int type;
859     int depth; /* the tree depth at creation time */
860     xmlSchemaIDCMatcherPtr next; /* next in the list */
861     xmlSchemaIDCMatcherPtr nextCached; /* next in the cache list */
862     xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
863     int idcType;
864     xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
865                                          elements */
866     int sizeKeySeqs;
867     xmlSchemaItemListPtr targets; /* list of target-node
868                                      (xmlSchemaPSVIIDCNodePtr) entries */
869     xmlHashTablePtr htab;
870 };
871 
872 /*
873 * Element info flags.
874 */
875 #define XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES  (1<<0)
876 #define XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES (1<<1)
877 #define XML_SCHEMA_ELEM_INFO_NILLED            (1<<2)
878 #define XML_SCHEMA_ELEM_INFO_LOCAL_TYPE        (1<<3)
879 
880 #define XML_SCHEMA_NODE_INFO_VALUE_NEEDED      (1<<4)
881 #define XML_SCHEMA_ELEM_INFO_EMPTY             (1<<5)
882 #define XML_SCHEMA_ELEM_INFO_HAS_CONTENT       (1<<6)
883 
884 #define XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT  (1<<7)
885 #define XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT   (1<<8)
886 #define XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED  (1<<9)
887 #define XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE      (1<<10)
888 
889 /**
890  * xmlSchemaNodeInfo:
891  *
892  * Holds information of an element node.
893  */
894 struct _xmlSchemaNodeInfo {
895     int nodeType;
896     xmlNodePtr node;
897     int nodeLine;
898     const xmlChar *localName;
899     const xmlChar *nsName;
900     const xmlChar *value;
901     xmlSchemaValPtr val; /* the pre-computed value if any */
902     xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
903 
904     int flags; /* combination of node info flags */
905 
906     int valNeeded;
907     int normVal;
908 
909     xmlSchemaElementPtr decl; /* the element/attribute declaration */
910     int depth;
911     xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
912                                             for the scope element*/
913     xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
914                                            element */
915     xmlRegExecCtxtPtr regexCtxt;
916 
917     const xmlChar **nsBindings; /* Namespace bindings on this element */
918     int nbNsBindings;
919     int sizeNsBindings;
920 
921     int hasKeyrefs;
922     int appliedXPath; /* Indicates that an XPath has been applied. */
923 };
924 
925 #define XML_SCHEMAS_ATTR_UNKNOWN 1
926 #define XML_SCHEMAS_ATTR_ASSESSED 2
927 #define XML_SCHEMAS_ATTR_PROHIBITED 3
928 #define XML_SCHEMAS_ATTR_ERR_MISSING 4
929 #define XML_SCHEMAS_ATTR_INVALID_VALUE 5
930 #define XML_SCHEMAS_ATTR_ERR_NO_TYPE 6
931 #define XML_SCHEMAS_ATTR_ERR_FIXED_VALUE 7
932 #define XML_SCHEMAS_ATTR_DEFAULT 8
933 #define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
934 #define XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL 10
935 #define XML_SCHEMAS_ATTR_HAS_ATTR_USE 11
936 #define XML_SCHEMAS_ATTR_HAS_ATTR_DECL 12
937 #define XML_SCHEMAS_ATTR_WILD_SKIP 13
938 #define XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL 14
939 #define XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID 15
940 #define XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID 16
941 #define XML_SCHEMAS_ATTR_META 17
942 /*
943 * @metaType values of xmlSchemaAttrInfo.
944 */
945 #define XML_SCHEMA_ATTR_INFO_META_XSI_TYPE 1
946 #define XML_SCHEMA_ATTR_INFO_META_XSI_NIL 2
947 #define XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC 3
948 #define XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC 4
949 #define XML_SCHEMA_ATTR_INFO_META_XMLNS 5
950 
951 typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo;
952 typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr;
953 struct _xmlSchemaAttrInfo {
954     int nodeType;
955     xmlNodePtr node;
956     int nodeLine;
957     const xmlChar *localName;
958     const xmlChar *nsName;
959     const xmlChar *value;
960     xmlSchemaValPtr val; /* the pre-computed value if any */
961     xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
962     int flags; /* combination of node info flags */
963 
964     xmlSchemaAttributePtr decl; /* the attribute declaration */
965     xmlSchemaAttributeUsePtr use;  /* the attribute use */
966     int state;
967     int metaType;
968     const xmlChar *vcValue; /* the value constraint value */
969     xmlSchemaNodeInfoPtr parent;
970 };
971 
972 
973 #define XML_SCHEMA_VALID_CTXT_FLAG_STREAM 1
974 /**
975  * xmlSchemaValidCtxt:
976  *
977  * A Schemas validation context
978  */
979 struct _xmlSchemaValidCtxt {
980     int type;
981     void *errCtxt;             /* user specific data block */
982     xmlSchemaValidityErrorFunc error;   /* the callback in case of errors */
983     xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
984     xmlStructuredErrorFunc serror;
985 
986     xmlSchemaPtr schema;        /* The schema in use */
987     xmlDocPtr doc;
988     xmlParserInputBufferPtr input;
989     xmlCharEncoding enc;
990     xmlSAXHandlerPtr sax;
991     xmlParserCtxtPtr parserCtxt;
992     void *user_data; /* TODO: What is this for? */
993     char *filename;
994 
995     int err;
996     int nberrors;
997 
998     xmlNodePtr node;
999     xmlNodePtr cur;
1000     /* xmlSchemaTypePtr type; */
1001 
1002     xmlRegExecCtxtPtr regexp;
1003     xmlSchemaValPtr value;
1004 
1005     int valueWS;
1006     int options;
1007     xmlNodePtr validationRoot;
1008     xmlSchemaParserCtxtPtr pctxt;
1009     int xsiAssemble;
1010 
1011     int depth;
1012     xmlSchemaNodeInfoPtr *elemInfos; /* array of element information */
1013     int sizeElemInfos;
1014     xmlSchemaNodeInfoPtr inode; /* the current element information */
1015 
1016     xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC information */
1017 
1018     xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
1019     xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
1020     xmlSchemaIDCMatcherPtr idcMatcherCache; /* Cache for IDC matcher objects. */
1021 
1022     xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
1023     int nbIdcNodes;
1024     int sizeIdcNodes;
1025 
1026     xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
1027     int nbIdcKeys;
1028     int sizeIdcKeys;
1029 
1030     int flags;
1031 
1032     xmlDictPtr dict;
1033 
1034 #ifdef LIBXML_READER_ENABLED
1035     xmlTextReaderPtr reader;
1036 #endif
1037 
1038     xmlSchemaAttrInfoPtr *attrInfos;
1039     int nbAttrInfos;
1040     int sizeAttrInfos;
1041 
1042     int skipDepth;
1043     xmlSchemaItemListPtr nodeQNames;
1044     int hasKeyrefs;
1045     int createIDCNodeTables;
1046     int psviExposeIDCNodeTables;
1047 
1048     /* Locator for error reporting in streaming mode */
1049     xmlSchemaValidityLocatorFunc locFunc;
1050     void *locCtxt;
1051 };
1052 
1053 /**
1054  * xmlSchemaSubstGroup:
1055  *
1056  *
1057  */
1058 typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup;
1059 typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr;
1060 struct _xmlSchemaSubstGroup {
1061     xmlSchemaElementPtr head;
1062     xmlSchemaItemListPtr members;
1063 };
1064 
1065 /**
1066  * xmlIDCHashEntry:
1067  *
1068  * an entry in hash tables to quickly look up keys/uniques
1069  */
1070 typedef struct _xmlIDCHashEntry xmlIDCHashEntry;
1071 typedef xmlIDCHashEntry *xmlIDCHashEntryPtr;
1072 struct _xmlIDCHashEntry {
1073     xmlIDCHashEntryPtr next; /* next item with same hash */
1074     int index;               /* index into associated item list */
1075 };
1076 
1077 /************************************************************************
1078  *									*
1079  *			Some predeclarations				*
1080  *									*
1081  ************************************************************************/
1082 
1083 static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
1084                                  xmlSchemaPtr schema,
1085                                  xmlNodePtr node);
1086 static int xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr ctxt,
1087                                  xmlSchemaPtr schema,
1088                                  xmlNodePtr node);
1089 static int
1090 xmlSchemaTypeFixup(xmlSchemaTypePtr type,
1091                    xmlSchemaAbstractCtxtPtr ctxt);
1092 static const xmlChar *
1093 xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
1094 static int
1095 xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1096                      xmlNodePtr node);
1097 static int
1098 xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
1099                        xmlSchemaParserCtxtPtr ctxt);
1100 static void
1101 xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
1102 static xmlSchemaWhitespaceValueType
1103 xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
1104 static xmlSchemaTreeItemPtr
1105 xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1106 			 xmlNodePtr node, xmlSchemaTypeType type,
1107 			 int withParticle);
1108 static const xmlChar *
1109 xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item);
1110 static xmlSchemaTypeLinkPtr
1111 xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
1112 static void
1113 xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
1114 		     const char *funcName,
1115 		     const char *message) LIBXML_ATTR_FORMAT(3,0);
1116 static int
1117 xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr ctxt,
1118 			     xmlSchemaTypePtr type,
1119 			     xmlSchemaTypePtr baseType,
1120 			     int subset);
1121 static void
1122 xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
1123 				   xmlSchemaParserCtxtPtr ctxt);
1124 static void
1125 xmlSchemaComponentListFree(xmlSchemaItemListPtr list);
1126 static xmlSchemaQNameRefPtr
1127 xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
1128 				xmlSchemaPtr schema,
1129 				xmlNodePtr node);
1130 
1131 /************************************************************************
1132  *									*
1133  *			Helper functions			        *
1134  *									*
1135  ************************************************************************/
1136 
1137 /**
1138  * xmlSchemaItemTypeToStr:
1139  * @type: the type of the schema item
1140  *
1141  * Returns the component name of a schema item.
1142  */
1143 static const xmlChar *
xmlSchemaItemTypeToStr(xmlSchemaTypeType type)1144 xmlSchemaItemTypeToStr(xmlSchemaTypeType type)
1145 {
1146     switch (type) {
1147 	case XML_SCHEMA_TYPE_BASIC:
1148 	    return(BAD_CAST "simple type definition");
1149 	case XML_SCHEMA_TYPE_SIMPLE:
1150 	    return(BAD_CAST "simple type definition");
1151 	case XML_SCHEMA_TYPE_COMPLEX:
1152 	    return(BAD_CAST "complex type definition");
1153 	case XML_SCHEMA_TYPE_ELEMENT:
1154 	    return(BAD_CAST "element declaration");
1155 	case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1156 	    return(BAD_CAST "attribute use");
1157 	case XML_SCHEMA_TYPE_ATTRIBUTE:
1158 	    return(BAD_CAST "attribute declaration");
1159 	case XML_SCHEMA_TYPE_GROUP:
1160 	    return(BAD_CAST "model group definition");
1161 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1162 	    return(BAD_CAST "attribute group definition");
1163 	case XML_SCHEMA_TYPE_NOTATION:
1164 	    return(BAD_CAST "notation declaration");
1165 	case XML_SCHEMA_TYPE_SEQUENCE:
1166 	    return(BAD_CAST "model group (sequence)");
1167 	case XML_SCHEMA_TYPE_CHOICE:
1168 	    return(BAD_CAST "model group (choice)");
1169 	case XML_SCHEMA_TYPE_ALL:
1170 	    return(BAD_CAST "model group (all)");
1171 	case XML_SCHEMA_TYPE_PARTICLE:
1172 	    return(BAD_CAST "particle");
1173 	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1174 	    return(BAD_CAST "unique identity-constraint");
1175 	    /* return(BAD_CAST "IDC (unique)"); */
1176 	case XML_SCHEMA_TYPE_IDC_KEY:
1177 	    return(BAD_CAST "key identity-constraint");
1178 	    /* return(BAD_CAST "IDC (key)"); */
1179 	case XML_SCHEMA_TYPE_IDC_KEYREF:
1180 	    return(BAD_CAST "keyref identity-constraint");
1181 	    /* return(BAD_CAST "IDC (keyref)"); */
1182 	case XML_SCHEMA_TYPE_ANY:
1183 	    return(BAD_CAST "wildcard (any)");
1184 	case XML_SCHEMA_EXTRA_QNAMEREF:
1185 	    return(BAD_CAST "[helper component] QName reference");
1186 	case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
1187 	    return(BAD_CAST "[helper component] attribute use prohibition");
1188 	default:
1189 	    return(BAD_CAST "Not a schema component");
1190     }
1191 }
1192 
1193 /**
1194  * xmlSchemaGetComponentTypeStr:
1195  * @type: the type of the schema item
1196  *
1197  * Returns the component name of a schema item.
1198  */
1199 static const xmlChar *
xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item)1200 xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item)
1201 {
1202     switch (item->type) {
1203 	case XML_SCHEMA_TYPE_BASIC:
1204 	    if (WXS_IS_COMPLEX(WXS_TYPE_CAST item))
1205 		return(BAD_CAST "complex type definition");
1206 	    else
1207 		return(BAD_CAST "simple type definition");
1208 	default:
1209 	    return(xmlSchemaItemTypeToStr(item->type));
1210     }
1211 }
1212 
1213 /**
1214  * xmlSchemaGetComponentNode:
1215  * @item: a schema component
1216  *
1217  * Returns node associated with the schema component.
1218  * NOTE that such a node need not be available; plus, a component's
1219  * node need not to reflect the component directly, since there is no
1220  * one-to-one relationship between the XML Schema representation and
1221  * the component representation.
1222  */
1223 static xmlNodePtr
xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)1224 xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
1225 {
1226     switch (item->type) {
1227 	case XML_SCHEMA_TYPE_ELEMENT:
1228 	    return (((xmlSchemaElementPtr) item)->node);
1229 	case XML_SCHEMA_TYPE_ATTRIBUTE:
1230 	    return (((xmlSchemaAttributePtr) item)->node);
1231 	case XML_SCHEMA_TYPE_COMPLEX:
1232 	case XML_SCHEMA_TYPE_SIMPLE:
1233 	    return (((xmlSchemaTypePtr) item)->node);
1234 	case XML_SCHEMA_TYPE_ANY:
1235 	case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1236 	    return (((xmlSchemaWildcardPtr) item)->node);
1237 	case XML_SCHEMA_TYPE_PARTICLE:
1238 	    return (((xmlSchemaParticlePtr) item)->node);
1239 	case XML_SCHEMA_TYPE_SEQUENCE:
1240 	case XML_SCHEMA_TYPE_CHOICE:
1241 	case XML_SCHEMA_TYPE_ALL:
1242 	    return (((xmlSchemaModelGroupPtr) item)->node);
1243 	case XML_SCHEMA_TYPE_GROUP:
1244 	    return (((xmlSchemaModelGroupDefPtr) item)->node);
1245 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1246 	    return (((xmlSchemaAttributeGroupPtr) item)->node);
1247 	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1248 	case XML_SCHEMA_TYPE_IDC_KEY:
1249 	case XML_SCHEMA_TYPE_IDC_KEYREF:
1250 	    return (((xmlSchemaIDCPtr) item)->node);
1251 	case XML_SCHEMA_EXTRA_QNAMEREF:
1252 	    return(((xmlSchemaQNameRefPtr) item)->node);
1253 	/* TODO: What to do with NOTATIONs?
1254 	case XML_SCHEMA_TYPE_NOTATION:
1255 	    return (((xmlSchemaNotationPtr) item)->node);
1256 	*/
1257 	case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1258 	    return (((xmlSchemaAttributeUsePtr) item)->node);
1259 	default:
1260 	    return (NULL);
1261     }
1262 }
1263 
1264 #if 0
1265 /**
1266  * xmlSchemaGetNextComponent:
1267  * @item: a schema component
1268  *
1269  * Returns the next sibling of the schema component.
1270  */
1271 static xmlSchemaBasicItemPtr
1272 xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
1273 {
1274     switch (item->type) {
1275 	case XML_SCHEMA_TYPE_ELEMENT:
1276 	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
1277 	case XML_SCHEMA_TYPE_ATTRIBUTE:
1278 	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
1279 	case XML_SCHEMA_TYPE_COMPLEX:
1280 	case XML_SCHEMA_TYPE_SIMPLE:
1281 	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
1282 	case XML_SCHEMA_TYPE_ANY:
1283 	case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1284 	    return (NULL);
1285 	case XML_SCHEMA_TYPE_PARTICLE:
1286 	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
1287 	case XML_SCHEMA_TYPE_SEQUENCE:
1288 	case XML_SCHEMA_TYPE_CHOICE:
1289 	case XML_SCHEMA_TYPE_ALL:
1290 	    return (NULL);
1291 	case XML_SCHEMA_TYPE_GROUP:
1292 	    return (NULL);
1293 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1294 	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
1295 	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1296 	case XML_SCHEMA_TYPE_IDC_KEY:
1297 	case XML_SCHEMA_TYPE_IDC_KEYREF:
1298 	    return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
1299 	default:
1300 	    return (NULL);
1301     }
1302 }
1303 #endif
1304 
1305 
1306 /**
1307  * xmlSchemaFormatQName:
1308  * @buf: the string buffer
1309  * @namespaceName:  the namespace name
1310  * @localName: the local name
1311  *
1312  * Returns the given QName in the format "{namespaceName}localName" or
1313  * just "localName" if @namespaceName is NULL.
1314  *
1315  * Returns the localName if @namespaceName is NULL, a formatted
1316  * string otherwise.
1317  */
1318 static const xmlChar*
xmlSchemaFormatQName(xmlChar ** buf,const xmlChar * namespaceName,const xmlChar * localName)1319 xmlSchemaFormatQName(xmlChar **buf,
1320 		     const xmlChar *namespaceName,
1321 		     const xmlChar *localName)
1322 {
1323     FREE_AND_NULL(*buf)
1324     if (namespaceName != NULL) {
1325 	*buf = xmlStrdup(BAD_CAST "{");
1326 	*buf = xmlStrcat(*buf, namespaceName);
1327 	*buf = xmlStrcat(*buf, BAD_CAST "}");
1328     }
1329     if (localName != NULL) {
1330 	if (namespaceName == NULL)
1331 	    return(localName);
1332 	*buf = xmlStrcat(*buf, localName);
1333     } else {
1334 	*buf = xmlStrcat(*buf, BAD_CAST "(NULL)");
1335     }
1336     return ((const xmlChar *) *buf);
1337 }
1338 
1339 static const xmlChar*
xmlSchemaFormatQNameNs(xmlChar ** buf,xmlNsPtr ns,const xmlChar * localName)1340 xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName)
1341 {
1342     if (ns != NULL)
1343 	return (xmlSchemaFormatQName(buf, ns->href, localName));
1344     else
1345 	return (xmlSchemaFormatQName(buf, NULL, localName));
1346 }
1347 
1348 static const xmlChar *
xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)1349 xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
1350 {
1351     if (item == NULL) {
1352         return (NULL);
1353     }
1354     switch (item->type) {
1355 	case XML_SCHEMA_TYPE_ELEMENT:
1356 	    return (((xmlSchemaElementPtr) item)->name);
1357 	case XML_SCHEMA_TYPE_ATTRIBUTE:
1358 	    return (((xmlSchemaAttributePtr) item)->name);
1359 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1360 	    return (((xmlSchemaAttributeGroupPtr) item)->name);
1361 	case XML_SCHEMA_TYPE_BASIC:
1362 	case XML_SCHEMA_TYPE_SIMPLE:
1363 	case XML_SCHEMA_TYPE_COMPLEX:
1364 	    return (((xmlSchemaTypePtr) item)->name);
1365 	case XML_SCHEMA_TYPE_GROUP:
1366 	    return (((xmlSchemaModelGroupDefPtr) item)->name);
1367 	case XML_SCHEMA_TYPE_IDC_KEY:
1368 	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1369 	case XML_SCHEMA_TYPE_IDC_KEYREF:
1370 	    return (((xmlSchemaIDCPtr) item)->name);
1371 	case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1372 	    if (WXS_ATTRUSE_DECL(item) != NULL) {
1373 		return(xmlSchemaGetComponentName(
1374 		    WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1375 	    } else
1376 		return(NULL);
1377 	case XML_SCHEMA_EXTRA_QNAMEREF:
1378 	    return (((xmlSchemaQNameRefPtr) item)->name);
1379 	case XML_SCHEMA_TYPE_NOTATION:
1380 	    return (((xmlSchemaNotationPtr) item)->name);
1381 	default:
1382 	    /*
1383 	    * Other components cannot have names.
1384 	    */
1385 	    break;
1386     }
1387     return (NULL);
1388 }
1389 
1390 #define xmlSchemaGetQNameRefName(r) (WXS_QNAME_CAST (r))->name
1391 #define xmlSchemaGetQNameRefTargetNs(r) (WXS_QNAME_CAST (r))->targetNamespace
1392 /*
1393 static const xmlChar *
1394 xmlSchemaGetQNameRefName(void *ref)
1395 {
1396     return(((xmlSchemaQNameRefPtr) ref)->name);
1397 }
1398 
1399 static const xmlChar *
1400 xmlSchemaGetQNameRefTargetNs(void *ref)
1401 {
1402     return(((xmlSchemaQNameRefPtr) ref)->targetNamespace);
1403 }
1404 */
1405 
1406 static const xmlChar *
xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)1407 xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
1408 {
1409     if (item == NULL) {
1410         return (NULL);
1411     }
1412     switch (item->type) {
1413 	case XML_SCHEMA_TYPE_ELEMENT:
1414 	    return (((xmlSchemaElementPtr) item)->targetNamespace);
1415 	case XML_SCHEMA_TYPE_ATTRIBUTE:
1416 	    return (((xmlSchemaAttributePtr) item)->targetNamespace);
1417 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1418 	    return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
1419 	case XML_SCHEMA_TYPE_BASIC:
1420 	    return (BAD_CAST "http://www.w3.org/2001/XMLSchema");
1421 	case XML_SCHEMA_TYPE_SIMPLE:
1422 	case XML_SCHEMA_TYPE_COMPLEX:
1423 	    return (((xmlSchemaTypePtr) item)->targetNamespace);
1424 	case XML_SCHEMA_TYPE_GROUP:
1425 	    return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1426 	case XML_SCHEMA_TYPE_IDC_KEY:
1427 	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1428 	case XML_SCHEMA_TYPE_IDC_KEYREF:
1429 	    return (((xmlSchemaIDCPtr) item)->targetNamespace);
1430 	case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1431 	    if (WXS_ATTRUSE_DECL(item) != NULL) {
1432 		return(xmlSchemaGetComponentTargetNs(
1433 		    WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1434 	    }
1435 	    /* TODO: Will returning NULL break something? */
1436 	    break;
1437 	case XML_SCHEMA_EXTRA_QNAMEREF:
1438 	    return (((xmlSchemaQNameRefPtr) item)->targetNamespace);
1439 	case XML_SCHEMA_TYPE_NOTATION:
1440 	    return (((xmlSchemaNotationPtr) item)->targetNamespace);
1441 	default:
1442 	    /*
1443 	    * Other components cannot have names.
1444 	    */
1445 	    break;
1446     }
1447     return (NULL);
1448 }
1449 
1450 static const xmlChar*
xmlSchemaGetComponentQName(xmlChar ** buf,void * item)1451 xmlSchemaGetComponentQName(xmlChar **buf,
1452 			   void *item)
1453 {
1454     return (xmlSchemaFormatQName(buf,
1455 	xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1456 	xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1457 }
1458 
1459 static const xmlChar*
xmlSchemaGetComponentDesignation(xmlChar ** buf,void * item)1460 xmlSchemaGetComponentDesignation(xmlChar **buf, void *item)
1461 {
1462     xmlChar *str = NULL;
1463 
1464     *buf = xmlStrcat(*buf, WXS_ITEM_TYPE_NAME(item));
1465     *buf = xmlStrcat(*buf, BAD_CAST " '");
1466     *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str,
1467 	(xmlSchemaBasicItemPtr) item));
1468     *buf = xmlStrcat(*buf, BAD_CAST "'");
1469     FREE_AND_NULL(str);
1470     return(*buf);
1471 }
1472 
1473 static const xmlChar*
xmlSchemaGetIDCDesignation(xmlChar ** buf,xmlSchemaIDCPtr idc)1474 xmlSchemaGetIDCDesignation(xmlChar **buf, xmlSchemaIDCPtr idc)
1475 {
1476     return(xmlSchemaGetComponentDesignation(buf, idc));
1477 }
1478 
1479 /**
1480  * xmlSchemaWildcardPCToString:
1481  * @pc: the type of processContents
1482  *
1483  * Returns a string representation of the type of
1484  * processContents.
1485  */
1486 static const xmlChar *
xmlSchemaWildcardPCToString(int pc)1487 xmlSchemaWildcardPCToString(int pc)
1488 {
1489     switch (pc) {
1490 	case XML_SCHEMAS_ANY_SKIP:
1491 	    return (BAD_CAST "skip");
1492 	case XML_SCHEMAS_ANY_LAX:
1493 	    return (BAD_CAST "lax");
1494 	case XML_SCHEMAS_ANY_STRICT:
1495 	    return (BAD_CAST "strict");
1496 	default:
1497 	    return (BAD_CAST "invalid process contents");
1498     }
1499 }
1500 
1501 /**
1502  * xmlSchemaGetCanonValueWhtspExt:
1503  * @val: the precomputed value
1504  * @retValue: the returned value
1505  * @ws: the whitespace type of the value
1506  * @for_hash: non-zero if this is supposed to generate a string for hashing
1507  *
1508  * Get a the canonical representation of the value.
1509  * The caller has to free the returned retValue.
1510  *
1511  * Returns 0 if the value could be built and -1 in case of
1512  *         API errors or if the value type is not supported yet.
1513  */
1514 static int
xmlSchemaGetCanonValueWhtspExt_1(xmlSchemaValPtr val,xmlSchemaWhitespaceValueType ws,xmlChar ** retValue,int for_hash)1515 xmlSchemaGetCanonValueWhtspExt_1(xmlSchemaValPtr val,
1516 			         xmlSchemaWhitespaceValueType ws,
1517 			         xmlChar **retValue,
1518 				 int for_hash)
1519 {
1520     int list;
1521     xmlSchemaValType valType;
1522     const xmlChar *value, *value2 = NULL;
1523 
1524 
1525     if ((retValue == NULL) || (val == NULL))
1526 	return (-1);
1527     list = xmlSchemaValueGetNext(val) ? 1 : 0;
1528     *retValue = NULL;
1529     do {
1530 	value = NULL;
1531 	valType = xmlSchemaGetValType(val);
1532 	switch (valType) {
1533 	    case XML_SCHEMAS_STRING:
1534 	    case XML_SCHEMAS_NORMSTRING:
1535 	    case XML_SCHEMAS_ANYSIMPLETYPE:
1536 		value = xmlSchemaValueGetAsString(val);
1537 		if (value != NULL) {
1538 		    if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1539 			value2 = xmlSchemaCollapseString(value);
1540 		    else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1541 			value2 = xmlSchemaWhiteSpaceReplace(value);
1542 		    if (value2 != NULL)
1543 			value = value2;
1544 		}
1545 		break;
1546 	    default:
1547 		if (xmlSchemaGetCanonValue(val, &value2) == -1) {
1548 		    if (value2 != NULL)
1549 			xmlFree((xmlChar *) value2);
1550 		    goto internal_error;
1551 		}
1552 		if (for_hash && valType == XML_SCHEMAS_DECIMAL) {
1553 		    /* We can mostly use the canonical value for hashing,
1554 		       except in the case of decimal.  There the canonical
1555 		       representation requires a trailing '.0' even for
1556 		       non-fractional numbers, but for the derived integer
1557 		       types it forbids any decimal point.  Nevertheless they
1558 		       compare equal if the value is equal.  We need to generate
1559 		       the same hash value for this to work, and it's easiest
1560 		       to just cut off the useless '.0' suffix for the
1561 		       decimal type.  */
1562 		    int len = xmlStrlen(value2);
1563 		    if (len > 2 && value2[len-1] == '0' && value2[len-2] == '.')
1564 		      ((xmlChar*)value2)[len-2] = 0;
1565 		}
1566 		value = value2;
1567 	}
1568 	if (*retValue == NULL)
1569 	    if (value == NULL) {
1570 		if (! list)
1571 		    *retValue = xmlStrdup(BAD_CAST "");
1572 	    } else
1573 		*retValue = xmlStrdup(value);
1574 	else if (value != NULL) {
1575 	    /* List. */
1576 	    *retValue = xmlStrcat((xmlChar *) *retValue, BAD_CAST " ");
1577 	    *retValue = xmlStrcat((xmlChar *) *retValue, value);
1578 	}
1579 	FREE_AND_NULL(value2)
1580 	val = xmlSchemaValueGetNext(val);
1581     } while (val != NULL);
1582 
1583     return (0);
1584 internal_error:
1585     if (*retValue != NULL)
1586 	xmlFree((xmlChar *) (*retValue));
1587     if (value2 != NULL)
1588 	xmlFree((xmlChar *) value2);
1589     return (-1);
1590 }
1591 
1592 static int
xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,xmlSchemaWhitespaceValueType ws,xmlChar ** retValue)1593 xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
1594 			       xmlSchemaWhitespaceValueType ws,
1595 			       xmlChar **retValue)
1596 {
1597     return xmlSchemaGetCanonValueWhtspExt_1(val, ws, retValue, 0);
1598 }
1599 
1600 static int
xmlSchemaGetCanonValueHash(xmlSchemaValPtr val,xmlChar ** retValue)1601 xmlSchemaGetCanonValueHash(xmlSchemaValPtr val,
1602 			   xmlChar **retValue)
1603 {
1604     return xmlSchemaGetCanonValueWhtspExt_1(val, XML_SCHEMA_WHITESPACE_COLLAPSE,
1605 					    retValue, 1);
1606 }
1607 
1608 /**
1609  * xmlSchemaFormatItemForReport:
1610  * @buf: the string buffer
1611  * @itemDes: the designation of the item
1612  * @itemName: the name of the item
1613  * @item: the item as an object
1614  * @itemNode: the node of the item
1615  * @local: the local name
1616  * @parsing: if the function is used during the parse
1617  *
1618  * Returns a representation of the given item used
1619  * for error reports.
1620  *
1621  * The following order is used to build the resulting
1622  * designation if the arguments are not NULL:
1623  * 1a. If itemDes not NULL -> itemDes
1624  * 1b. If (itemDes not NULL) and (itemName not NULL)
1625  *     -> itemDes + itemName
1626  * 2. If the preceding was NULL and (item not NULL) -> item
1627  * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
1628  *
1629  * If the itemNode is an attribute node, the name of the attribute
1630  * will be appended to the result.
1631  *
1632  * Returns the formatted string and sets @buf to the resulting value.
1633  */
1634 static xmlChar*
xmlSchemaFormatItemForReport(xmlChar ** buf,const xmlChar * itemDes,xmlSchemaBasicItemPtr item,xmlNodePtr itemNode)1635 xmlSchemaFormatItemForReport(xmlChar **buf,
1636 		     const xmlChar *itemDes,
1637 		     xmlSchemaBasicItemPtr item,
1638 		     xmlNodePtr itemNode)
1639 {
1640     xmlChar *str = NULL;
1641     int named = 1;
1642 
1643     if (*buf != NULL) {
1644 	xmlFree(*buf);
1645 	*buf = NULL;
1646     }
1647 
1648     if (itemDes != NULL) {
1649 	*buf = xmlStrdup(itemDes);
1650     } else if (item != NULL) {
1651 	switch (item->type) {
1652 	case XML_SCHEMA_TYPE_BASIC: {
1653 	    xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1654 
1655 	    if (WXS_IS_ATOMIC(type))
1656 		*buf = xmlStrdup(BAD_CAST "atomic type 'xs:");
1657 	    else if (WXS_IS_LIST(type))
1658 		*buf = xmlStrdup(BAD_CAST "list type 'xs:");
1659 	    else if (WXS_IS_UNION(type))
1660 		*buf = xmlStrdup(BAD_CAST "union type 'xs:");
1661 	    else
1662 		*buf = xmlStrdup(BAD_CAST "simple type 'xs:");
1663 	    *buf = xmlStrcat(*buf, type->name);
1664 	    *buf = xmlStrcat(*buf, BAD_CAST "'");
1665 	    }
1666 	    break;
1667 	case XML_SCHEMA_TYPE_SIMPLE: {
1668 	    xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1669 
1670 	    if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1671 		*buf = xmlStrdup(BAD_CAST"");
1672 	    } else {
1673 		*buf = xmlStrdup(BAD_CAST "local ");
1674 	    }
1675 	    if (WXS_IS_ATOMIC(type))
1676 		*buf = xmlStrcat(*buf, BAD_CAST "atomic type");
1677 	    else if (WXS_IS_LIST(type))
1678 		*buf = xmlStrcat(*buf, BAD_CAST "list type");
1679 	    else if (WXS_IS_UNION(type))
1680 		*buf = xmlStrcat(*buf, BAD_CAST "union type");
1681 	    else
1682 		*buf = xmlStrcat(*buf, BAD_CAST "simple type");
1683 	    if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1684 		*buf = xmlStrcat(*buf, BAD_CAST " '");
1685 		*buf = xmlStrcat(*buf, type->name);
1686 		*buf = xmlStrcat(*buf, BAD_CAST "'");
1687 	    }
1688 	    }
1689 	    break;
1690 	case XML_SCHEMA_TYPE_COMPLEX: {
1691 	    xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1692 
1693 	    if (type->flags & XML_SCHEMAS_TYPE_GLOBAL)
1694 		*buf = xmlStrdup(BAD_CAST "");
1695 	    else
1696 		*buf = xmlStrdup(BAD_CAST "local ");
1697 	    *buf = xmlStrcat(*buf, BAD_CAST "complex type");
1698 	    if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1699 		*buf = xmlStrcat(*buf, BAD_CAST " '");
1700 		*buf = xmlStrcat(*buf, type->name);
1701 		*buf = xmlStrcat(*buf, BAD_CAST "'");
1702 	    }
1703 	    }
1704 	    break;
1705 	case XML_SCHEMA_TYPE_ATTRIBUTE_USE: {
1706 		xmlSchemaAttributeUsePtr ause;
1707 
1708 		ause = WXS_ATTR_USE_CAST item;
1709 		*buf = xmlStrdup(BAD_CAST "attribute use ");
1710 		if (WXS_ATTRUSE_DECL(ause) != NULL) {
1711 		    *buf = xmlStrcat(*buf, BAD_CAST "'");
1712 		    *buf = xmlStrcat(*buf,
1713 			xmlSchemaGetComponentQName(&str, WXS_ATTRUSE_DECL(ause)));
1714 		    FREE_AND_NULL(str)
1715 			*buf = xmlStrcat(*buf, BAD_CAST "'");
1716 		} else {
1717 		    *buf = xmlStrcat(*buf, BAD_CAST "(unknown)");
1718 		}
1719 	    }
1720 	    break;
1721 	case XML_SCHEMA_TYPE_ATTRIBUTE: {
1722 		xmlSchemaAttributePtr attr;
1723 
1724 		attr = (xmlSchemaAttributePtr) item;
1725 		*buf = xmlStrdup(BAD_CAST "attribute decl.");
1726 		*buf = xmlStrcat(*buf, BAD_CAST " '");
1727 		*buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1728 		    attr->targetNamespace, attr->name));
1729 		FREE_AND_NULL(str)
1730 		    *buf = xmlStrcat(*buf, BAD_CAST "'");
1731 	    }
1732 	    break;
1733 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1734 	    xmlSchemaGetComponentDesignation(buf, item);
1735 	    break;
1736 	case XML_SCHEMA_TYPE_ELEMENT: {
1737 		xmlSchemaElementPtr elem;
1738 
1739 		elem = (xmlSchemaElementPtr) item;
1740 		*buf = xmlStrdup(BAD_CAST "element decl.");
1741 		*buf = xmlStrcat(*buf, BAD_CAST " '");
1742 		*buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1743 		    elem->targetNamespace, elem->name));
1744 		*buf = xmlStrcat(*buf, BAD_CAST "'");
1745 	    }
1746 	    break;
1747 	case XML_SCHEMA_TYPE_IDC_UNIQUE:
1748 	case XML_SCHEMA_TYPE_IDC_KEY:
1749 	case XML_SCHEMA_TYPE_IDC_KEYREF:
1750 	    if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1751 		*buf = xmlStrdup(BAD_CAST "unique '");
1752 	    else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1753 		*buf = xmlStrdup(BAD_CAST "key '");
1754 	    else
1755 		*buf = xmlStrdup(BAD_CAST "keyRef '");
1756 	    *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1757 	    *buf = xmlStrcat(*buf, BAD_CAST "'");
1758 	    break;
1759 	case XML_SCHEMA_TYPE_ANY:
1760 	case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1761 	    *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1762 		    ((xmlSchemaWildcardPtr) item)->processContents));
1763 	    *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1764 	    break;
1765 	case XML_SCHEMA_FACET_MININCLUSIVE:
1766 	case XML_SCHEMA_FACET_MINEXCLUSIVE:
1767 	case XML_SCHEMA_FACET_MAXINCLUSIVE:
1768 	case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1769 	case XML_SCHEMA_FACET_TOTALDIGITS:
1770 	case XML_SCHEMA_FACET_FRACTIONDIGITS:
1771 	case XML_SCHEMA_FACET_PATTERN:
1772 	case XML_SCHEMA_FACET_ENUMERATION:
1773 	case XML_SCHEMA_FACET_WHITESPACE:
1774 	case XML_SCHEMA_FACET_LENGTH:
1775 	case XML_SCHEMA_FACET_MAXLENGTH:
1776 	case XML_SCHEMA_FACET_MINLENGTH:
1777 	    *buf = xmlStrdup(BAD_CAST "facet '");
1778 	    *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1779 	    *buf = xmlStrcat(*buf, BAD_CAST "'");
1780 	    break;
1781 	case XML_SCHEMA_TYPE_GROUP: {
1782 		*buf = xmlStrdup(BAD_CAST "model group def.");
1783 		*buf = xmlStrcat(*buf, BAD_CAST " '");
1784 		*buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1785 		*buf = xmlStrcat(*buf, BAD_CAST "'");
1786 		FREE_AND_NULL(str)
1787 	    }
1788 	    break;
1789 	case XML_SCHEMA_TYPE_SEQUENCE:
1790 	case XML_SCHEMA_TYPE_CHOICE:
1791 	case XML_SCHEMA_TYPE_ALL:
1792 	case XML_SCHEMA_TYPE_PARTICLE:
1793 	    *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1794 	    break;
1795 	case XML_SCHEMA_TYPE_NOTATION: {
1796 		*buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1797 		*buf = xmlStrcat(*buf, BAD_CAST " '");
1798 		*buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1799 		*buf = xmlStrcat(*buf, BAD_CAST "'");
1800 		FREE_AND_NULL(str);
1801 	    }
1802             /* Falls through. */
1803 	default:
1804 	    named = 0;
1805 	}
1806     } else
1807 	named = 0;
1808 
1809     if ((named == 0) && (itemNode != NULL)) {
1810 	xmlNodePtr elem;
1811 
1812 	if (itemNode->type == XML_ATTRIBUTE_NODE)
1813 	    elem = itemNode->parent;
1814 	else
1815 	    elem = itemNode;
1816 	*buf = xmlStrdup(BAD_CAST "Element '");
1817 	if (elem->ns != NULL) {
1818 	    *buf = xmlStrcat(*buf,
1819 		xmlSchemaFormatQName(&str, elem->ns->href, elem->name));
1820 	    FREE_AND_NULL(str)
1821 	} else
1822 	    *buf = xmlStrcat(*buf, elem->name);
1823 	*buf = xmlStrcat(*buf, BAD_CAST "'");
1824 
1825     }
1826     if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1827 	*buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1828 	if (itemNode->ns != NULL) {
1829 	    *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1830 		itemNode->ns->href, itemNode->name));
1831 	    FREE_AND_NULL(str)
1832 	} else
1833 	    *buf = xmlStrcat(*buf, itemNode->name);
1834 	*buf = xmlStrcat(*buf, BAD_CAST "'");
1835     }
1836     FREE_AND_NULL(str)
1837 
1838     return (xmlEscapeFormatString(buf));
1839 }
1840 
1841 /**
1842  * xmlSchemaFormatFacetEnumSet:
1843  * @buf: the string buffer
1844  * @type: the type holding the enumeration facets
1845  *
1846  * Builds a string consisting of all enumeration elements.
1847  *
1848  * Returns a string of all enumeration elements.
1849  */
1850 static const xmlChar *
xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,xmlChar ** buf,xmlSchemaTypePtr type)1851 xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,
1852 			    xmlChar **buf, xmlSchemaTypePtr type)
1853 {
1854     xmlSchemaFacetPtr facet;
1855     xmlSchemaWhitespaceValueType ws;
1856     xmlChar *value = NULL;
1857     int res, found = 0;
1858 
1859     if (*buf != NULL)
1860 	xmlFree(*buf);
1861     *buf = NULL;
1862 
1863     do {
1864 	/*
1865 	* Use the whitespace type of the base type.
1866 	*/
1867 	ws = xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
1868 	for (facet = type->facets; facet != NULL; facet = facet->next) {
1869 	    if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1870 		continue;
1871 	    found = 1;
1872 	    res = xmlSchemaGetCanonValueWhtspExt(facet->val,
1873 		ws, &value);
1874 	    if (res == -1) {
1875 		xmlSchemaInternalErr(actxt,
1876 		    "xmlSchemaFormatFacetEnumSet",
1877 		    "compute the canonical lexical representation");
1878 		if (*buf != NULL)
1879 		    xmlFree(*buf);
1880 		*buf = NULL;
1881 		return (NULL);
1882 	    }
1883 	    if (*buf == NULL)
1884 		*buf = xmlStrdup(BAD_CAST "'");
1885 	    else
1886 		*buf = xmlStrcat(*buf, BAD_CAST ", '");
1887 	    *buf = xmlStrcat(*buf, BAD_CAST value);
1888 	    *buf = xmlStrcat(*buf, BAD_CAST "'");
1889 	    if (value != NULL) {
1890 		xmlFree((xmlChar *)value);
1891 		value = NULL;
1892 	    }
1893 	}
1894 	/*
1895 	* The enumeration facet of a type restricts the enumeration
1896 	* facet of the ancestor type; i.e., such restricted enumerations
1897 	* do not belong to the set of the given type. Thus we break
1898 	* on the first found enumeration.
1899 	*/
1900 	if (found)
1901 	    break;
1902 	type = type->baseType;
1903     } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
1904 
1905     return ((const xmlChar *) *buf);
1906 }
1907 
1908 /************************************************************************
1909  *									*
1910  *			Error functions				        *
1911  *									*
1912  ************************************************************************/
1913 
1914 /**
1915  * xmlSchemaPErrMemory:
1916  * @node: a context node
1917  * @extra:  extra information
1918  *
1919  * Handle an out of memory condition
1920  */
1921 static void
xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt)1922 xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt)
1923 {
1924     xmlGenericErrorFunc channel = NULL;
1925     xmlStructuredErrorFunc schannel = NULL;
1926     void *data = NULL;
1927 
1928     if (ctxt != NULL) {
1929         ctxt->nberrors++;
1930         ctxt->err = XML_ERR_NO_MEMORY;
1931         channel = ctxt->error;
1932         schannel = ctxt->serror;
1933         data = ctxt->errCtxt;
1934     }
1935 
1936     xmlRaiseMemoryError(schannel, channel, data, XML_FROM_SCHEMASP, NULL);
1937 }
1938 
1939 static void LIBXML_ATTR_FORMAT(11,12)
xmlSchemaPErrFull(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int code,xmlErrorLevel level,const char * file,int line,const xmlChar * str1,const xmlChar * str2,const xmlChar * str3,int col,const char * msg,...)1940 xmlSchemaPErrFull(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int code,
1941                   xmlErrorLevel level, const char *file, int line,
1942                   const xmlChar *str1, const xmlChar *str2, const xmlChar *str3,
1943                   int col, const char *msg, ...) {
1944     xmlGenericErrorFunc channel = NULL;
1945     xmlStructuredErrorFunc schannel = NULL;
1946     void *data = NULL;
1947     int res;
1948     va_list ap;
1949 
1950     if (ctxt != NULL) {
1951         /* Don't overwrite memory errors */
1952         if (ctxt->err == XML_ERR_NO_MEMORY)
1953             return;
1954 
1955         if (level == XML_ERR_WARNING) {
1956             channel = ctxt->warning;
1957         } else {
1958             ctxt->nberrors++;
1959             ctxt->err = code;
1960             channel = ctxt->error;
1961         }
1962         data = ctxt->errCtxt;
1963         schannel = ctxt->serror;
1964     }
1965 
1966     if ((channel == NULL) && (schannel == NULL)) {
1967         channel = xmlGenericError;
1968         data = xmlGenericErrorContext;
1969     }
1970 
1971     va_start(ap, msg);
1972     res = xmlVRaiseError(schannel, channel, data, ctxt, node,
1973                          XML_FROM_SCHEMASP, code, level, file, line,
1974                          (const char *) str1,
1975                          (const char *) str2,
1976                          (const char *) str3,
1977                          0, col, msg, ap);
1978     va_end(ap);
1979 
1980     if (res < 0)
1981         xmlSchemaPErrMemory(ctxt);
1982 }
1983 
1984 /**
1985  * xmlSchemaPErr:
1986  * @ctxt: the parsing context
1987  * @node: the context node
1988  * @error: the error code
1989  * @msg: the error message
1990  * @str1: extra data
1991  * @str2: extra data
1992  *
1993  * Handle a parser error
1994  */
1995 static void LIBXML_ATTR_FORMAT(4,0)
xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int code,const char * msg,const xmlChar * str1,const xmlChar * str2)1996 xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int code,
1997               const char *msg, const xmlChar * str1, const xmlChar * str2)
1998 {
1999     xmlSchemaPErrFull(ctxt, node, code, XML_ERR_ERROR, NULL, 0,
2000                       str1, str2, NULL, 0, msg, str1, str2);
2001 }
2002 
2003 /**
2004  * xmlSchemaPErr2:
2005  * @ctxt: the parsing context
2006  * @node: the context node
2007  * @node: the current child
2008  * @error: the error code
2009  * @msg: the error message
2010  * @str1: extra data
2011  * @str2: extra data
2012  *
2013  * Handle a parser error
2014  */
2015 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)2016 xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
2017                xmlNodePtr child, int error,
2018                const char *msg, const xmlChar * str1, const xmlChar * str2)
2019 {
2020     if (child != NULL)
2021         xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
2022     else
2023         xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
2024 }
2025 
2026 
2027 /**
2028  * xmlSchemaPErrExt:
2029  * @ctxt: the parsing context
2030  * @node: the context node
2031  * @error: the error code
2032  * @strData1: extra data
2033  * @strData2: extra data
2034  * @strData3: extra data
2035  * @msg: the message
2036  * @str1:  extra parameter for the message display
2037  * @str2:  extra parameter for the message display
2038  * @str3:  extra parameter for the message display
2039  * @str4:  extra parameter for the message display
2040  * @str5:  extra parameter for the message display
2041  *
2042  * Handle a parser error
2043  */
2044 static void LIBXML_ATTR_FORMAT(7,0)
xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int code,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)2045 xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int code,
2046 		const xmlChar * strData1, const xmlChar * strData2,
2047 		const xmlChar * strData3, const char *msg, const xmlChar * str1,
2048 		const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
2049 		const xmlChar * str5)
2050 {
2051     xmlSchemaPErrFull(ctxt, node, code, XML_ERR_ERROR, NULL, 0,
2052                       strData1, strData2, strData3, 0,
2053                       msg, str1, str2, str3, str4, str5);
2054 }
2055 
2056 /************************************************************************
2057  *									*
2058  *			Allround error functions			*
2059  *									*
2060  ************************************************************************/
2061 
2062 /**
2063  * xmlSchemaVTypeErrMemory:
2064  * @node: a context node
2065  * @extra:  extra information
2066  *
2067  * Handle an out of memory condition
2068  */
2069 static void
xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt)2070 xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt)
2071 {
2072     xmlGenericErrorFunc channel = NULL;
2073     xmlStructuredErrorFunc schannel = NULL;
2074     void *data = NULL;
2075 
2076     if (ctxt != NULL) {
2077         ctxt->nberrors++;
2078         ctxt->err = XML_ERR_NO_MEMORY;
2079         channel = ctxt->error;
2080         schannel = ctxt->serror;
2081         data = ctxt->errCtxt;
2082     }
2083 
2084     xmlRaiseMemoryError(schannel, channel, data, XML_FROM_SCHEMASV, NULL);
2085 }
2086 
2087 static void LIBXML_ATTR_FORMAT(11,12)
xmlSchemaVErrFull(xmlSchemaValidCtxtPtr ctxt,xmlNodePtr node,int code,xmlErrorLevel level,const char * file,int line,const xmlChar * str1,const xmlChar * str2,const xmlChar * str3,int col,const char * msg,...)2088 xmlSchemaVErrFull(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int code,
2089                   xmlErrorLevel level, const char *file, int line,
2090                   const xmlChar *str1, const xmlChar *str2, const xmlChar *str3,
2091                   int col, const char *msg, ...) {
2092     xmlGenericErrorFunc channel = NULL;
2093     xmlStructuredErrorFunc schannel = NULL;
2094     void *data = NULL;
2095     int res;
2096     va_list ap;
2097 
2098     if (ctxt != NULL) {
2099         /* Don't overwrite memory errors */
2100         if (ctxt->err == XML_ERR_NO_MEMORY)
2101             return;
2102 
2103         if (level == XML_ERR_WARNING) {
2104             channel = ctxt->warning;
2105         } else {
2106             ctxt->nberrors++;
2107             ctxt->err = code;
2108             channel = ctxt->error;
2109         }
2110         data = ctxt->errCtxt;
2111         schannel = ctxt->serror;
2112     }
2113 
2114     if ((channel == NULL) && (schannel == NULL)) {
2115         channel = xmlGenericError;
2116         data = xmlGenericErrorContext;
2117     }
2118 
2119     va_start(ap, msg);
2120     res = xmlVRaiseError(schannel, channel, data, ctxt, node,
2121                          XML_FROM_SCHEMASV, code, level, file, line,
2122                          (const char *) str1,
2123                          (const char *) str2,
2124                          (const char *) str3,
2125                          0, col, msg, ap);
2126     va_end(ap);
2127 
2128     if (res < 0)
2129         xmlSchemaVErrMemory(ctxt);
2130 }
2131 
2132 #define WXS_ERROR_TYPE_ERROR 1
2133 #define WXS_ERROR_TYPE_WARNING 2
2134 /**
2135  * xmlSchemaErr4Line:
2136  * @ctxt: the validation context
2137  * @errorLevel: the error level
2138  * @error: the error code
2139  * @node: the context node
2140  * @line: the line number
2141  * @msg: the error message
2142  * @str1: extra data
2143  * @str2: extra data
2144  * @str3: extra data
2145  * @str4: extra data
2146  *
2147  * Handle a validation error
2148  */
2149 static void LIBXML_ATTR_FORMAT(6,0)
xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt,xmlErrorLevel errorLevel,int code,xmlNodePtr node,int line,const char * msg,const xmlChar * str1,const xmlChar * str2,const xmlChar * str3,const xmlChar * str4)2150 xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt,
2151 		  xmlErrorLevel errorLevel,
2152 		  int code, xmlNodePtr node, int line, const char *msg,
2153 		  const xmlChar *str1, const xmlChar *str2,
2154 		  const xmlChar *str3, const xmlChar *str4)
2155 {
2156     if (ctxt != NULL) {
2157 	if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2158 	    xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
2159 	    const char *file = NULL;
2160 	    int col = 0;
2161 
2162 	    /*
2163 	    * Error node. If we specify a line number, then
2164 	    * do not channel any node to the error function.
2165 	    */
2166 	    if (line == 0) {
2167 		if ((node == NULL) &&
2168 		    (vctxt->depth >= 0) &&
2169 		    (vctxt->inode != NULL)) {
2170 		    node = vctxt->inode->node;
2171 		}
2172 		/*
2173 		* Get filename and line if no node-tree.
2174 		*/
2175 		if ((node == NULL) &&
2176 		    (vctxt->parserCtxt != NULL) &&
2177 		    (vctxt->parserCtxt->input != NULL)) {
2178 		    file = vctxt->parserCtxt->input->filename;
2179                     if (vctxt->inode != NULL) {
2180 		        line = vctxt->inode->nodeLine;
2181                         col = 0;
2182                     } else {
2183                         /* This is inaccurate. */
2184 		        line = vctxt->parserCtxt->input->line;
2185 		        col = vctxt->parserCtxt->input->col;
2186                     }
2187 		}
2188 	    } else {
2189 		/*
2190 		* Override the given node's (if any) position
2191 		* and channel only the given line number.
2192 		*/
2193 		node = NULL;
2194 		/*
2195 		* Get filename.
2196 		*/
2197 		if (vctxt->doc != NULL)
2198 		    file = (const char *) vctxt->doc->URL;
2199 		else if ((vctxt->parserCtxt != NULL) &&
2200 		    (vctxt->parserCtxt->input != NULL))
2201 		    file = vctxt->parserCtxt->input->filename;
2202 	    }
2203 	    if (vctxt->locFunc != NULL) {
2204 	        if ((file == NULL) || (line == 0)) {
2205 		    unsigned long l;
2206 		    const char *f;
2207 		    vctxt->locFunc(vctxt->locCtxt, &f, &l);
2208 		    if (file == NULL)
2209 		        file = f;
2210 		    if (line == 0)
2211 		        line = (int) l;
2212 		}
2213 	    }
2214 	    if ((file == NULL) && (vctxt->filename != NULL))
2215 	        file = vctxt->filename;
2216 
2217             xmlSchemaVErrFull(vctxt, node, code, errorLevel,
2218                               file, line, str1, str2, str3, col,
2219                               msg, str1, str2, str3, str4);
2220 	} else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
2221 	    xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
2222 
2223             xmlSchemaPErrFull(pctxt, node, code, errorLevel,
2224                               NULL, 0, str1, str2, str3, 0,
2225                               msg, str1, str2, str3, str4);
2226 	}
2227     }
2228 }
2229 
2230 /**
2231  * xmlSchemaErr3:
2232  * @ctxt: the validation context
2233  * @node: the context node
2234  * @error: the error code
2235  * @msg: the error message
2236  * @str1: extra data
2237  * @str2: extra data
2238  * @str3: extra data
2239  *
2240  * Handle a validation error
2241  */
2242 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)2243 xmlSchemaErr3(xmlSchemaAbstractCtxtPtr actxt,
2244 	      int error, xmlNodePtr node, const char *msg,
2245 	      const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
2246 {
2247     xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2248 	msg, str1, str2, str3, NULL);
2249 }
2250 
2251 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)2252 xmlSchemaErr4(xmlSchemaAbstractCtxtPtr actxt,
2253 	      int error, xmlNodePtr node, const char *msg,
2254 	      const xmlChar *str1, const xmlChar *str2,
2255 	      const xmlChar *str3, const xmlChar *str4)
2256 {
2257     xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2258 	msg, str1, str2, str3, str4);
2259 }
2260 
2261 static void LIBXML_ATTR_FORMAT(4,0)
xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,int error,xmlNodePtr node,const char * msg,const xmlChar * str1,const xmlChar * str2)2262 xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
2263 	     int error, xmlNodePtr node, const char *msg,
2264 	     const xmlChar *str1, const xmlChar *str2)
2265 {
2266     xmlSchemaErr4(actxt, error, node, msg, str1, str2, NULL, NULL);
2267 }
2268 
2269 static xmlChar *
xmlSchemaFormatNodeForError(xmlChar ** msg,xmlSchemaAbstractCtxtPtr actxt,xmlNodePtr node)2270 xmlSchemaFormatNodeForError(xmlChar ** msg,
2271 			    xmlSchemaAbstractCtxtPtr actxt,
2272 			    xmlNodePtr node)
2273 {
2274     xmlChar *str = NULL;
2275 
2276     *msg = NULL;
2277     if ((node != NULL) &&
2278 	(node->type != XML_ELEMENT_NODE) &&
2279 	(node->type != XML_ATTRIBUTE_NODE))
2280     {
2281 	/*
2282 	* Don't try to format other nodes than element and
2283 	* attribute nodes.
2284 	* Play safe and return an empty string.
2285 	*/
2286 	*msg = xmlStrdup(BAD_CAST "");
2287 	return(*msg);
2288     }
2289     if (node != NULL) {
2290 	/*
2291 	* Work on tree nodes.
2292 	*/
2293 	if (node->type == XML_ATTRIBUTE_NODE) {
2294 	    xmlNodePtr elem = node->parent;
2295 
2296 	    *msg = xmlStrdup(BAD_CAST "Element '");
2297 	    if (elem->ns != NULL)
2298 		*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2299 		    elem->ns->href, elem->name));
2300 	    else
2301 		*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2302 		    NULL, elem->name));
2303 	    FREE_AND_NULL(str);
2304 	    *msg = xmlStrcat(*msg, BAD_CAST "', ");
2305 	    *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2306 	} else {
2307 	    *msg = xmlStrdup(BAD_CAST "Element '");
2308 	}
2309 	if (node->ns != NULL)
2310 	    *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2311 	    node->ns->href, node->name));
2312 	else
2313 	    *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2314 	    NULL, node->name));
2315 	FREE_AND_NULL(str);
2316 	*msg = xmlStrcat(*msg, BAD_CAST "': ");
2317     } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2318 	xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
2319 	/*
2320 	* Work on node infos.
2321 	*/
2322 	if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
2323 	    xmlSchemaNodeInfoPtr ielem =
2324 		vctxt->elemInfos[vctxt->depth];
2325 
2326 	    *msg = xmlStrdup(BAD_CAST "Element '");
2327 	    *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2328 		ielem->nsName, ielem->localName));
2329 	    FREE_AND_NULL(str);
2330 	    *msg = xmlStrcat(*msg, BAD_CAST "', ");
2331 	    *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2332 	} else {
2333 	    *msg = xmlStrdup(BAD_CAST "Element '");
2334 	}
2335 	*msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2336 	    vctxt->inode->nsName, vctxt->inode->localName));
2337 	FREE_AND_NULL(str);
2338 	*msg = xmlStrcat(*msg, BAD_CAST "': ");
2339     } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
2340 	/*
2341 	* Hmm, no node while parsing?
2342 	* Return an empty string, in case NULL will break something.
2343 	*/
2344 	*msg = xmlStrdup(BAD_CAST "");
2345     } else {
2346 	/* TODO */
2347 	return (NULL);
2348     }
2349 
2350     /*
2351      * xmlSchemaFormatItemForReport() also returns an escaped format
2352      * string, so do this before calling it below (in the future).
2353      */
2354     xmlEscapeFormatString(msg);
2355 
2356     /*
2357     * VAL TODO: The output of the given schema component is currently
2358     * disabled.
2359     */
2360 #if 0
2361     if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
2362 	*msg = xmlStrcat(*msg, BAD_CAST " [");
2363 	*msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
2364 	    NULL, type, NULL, 0));
2365 	FREE_AND_NULL(str)
2366 	*msg = xmlStrcat(*msg, BAD_CAST "]");
2367     }
2368 #endif
2369     return (*msg);
2370 }
2371 
2372 static void LIBXML_ATTR_FORMAT(3,0)
xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,const char * funcName,const char * message,const xmlChar * str1,const xmlChar * str2)2373 xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,
2374 		     const char *funcName,
2375 		     const char *message,
2376 		     const xmlChar *str1,
2377 		     const xmlChar *str2)
2378 {
2379     xmlChar *msg = NULL;
2380 
2381     if (actxt == NULL)
2382         return;
2383     msg = xmlStrdup(BAD_CAST "Internal error: %s, ");
2384     msg = xmlStrcat(msg, BAD_CAST message);
2385     msg = xmlStrcat(msg, BAD_CAST ".\n");
2386 
2387     if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
2388 	xmlSchemaErr3(actxt, XML_SCHEMAV_INTERNAL, NULL,
2389 	    (const char *) msg, (const xmlChar *) funcName, str1, str2);
2390     else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
2391 	xmlSchemaErr3(actxt, XML_SCHEMAP_INTERNAL, NULL,
2392 	    (const char *) msg, (const xmlChar *) funcName, str1, str2);
2393 
2394     FREE_AND_NULL(msg)
2395 }
2396 
2397 static void LIBXML_ATTR_FORMAT(3,0)
xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,const char * funcName,const char * message)2398 xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
2399 		     const char *funcName,
2400 		     const char *message)
2401 {
2402     xmlSchemaInternalErr2(actxt, funcName, message, NULL, NULL);
2403 }
2404 
2405 #if 0
2406 static void LIBXML_ATTR_FORMAT(3,0)
2407 xmlSchemaPInternalErr(xmlSchemaParserCtxtPtr pctxt,
2408 		     const char *funcName,
2409 		     const char *message,
2410 		     const xmlChar *str1,
2411 		     const xmlChar *str2)
2412 {
2413     xmlSchemaInternalErr2(ACTXT_CAST pctxt, funcName, message,
2414 	str1, str2);
2415 }
2416 #endif
2417 
2418 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)2419 xmlSchemaCustomErr4(xmlSchemaAbstractCtxtPtr actxt,
2420 		   xmlParserErrors error,
2421 		   xmlNodePtr node,
2422 		   xmlSchemaBasicItemPtr item,
2423 		   const char *message,
2424 		   const xmlChar *str1, const xmlChar *str2,
2425 		   const xmlChar *str3, const xmlChar *str4)
2426 {
2427     xmlChar *msg = NULL;
2428 
2429     if ((node == NULL) && (item != NULL) &&
2430 	(actxt->type == XML_SCHEMA_CTXT_PARSER)) {
2431 	node = WXS_ITEM_NODE(item);
2432 	xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2433 	msg = xmlStrcat(msg, BAD_CAST ": ");
2434     } else
2435 	xmlSchemaFormatNodeForError(&msg, actxt, node);
2436     msg = xmlStrcat(msg, (const xmlChar *) message);
2437     msg = xmlStrcat(msg, BAD_CAST ".\n");
2438     xmlSchemaErr4(actxt, error, node,
2439 	(const char *) msg, str1, str2, str3, str4);
2440     FREE_AND_NULL(msg)
2441 }
2442 
2443 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)2444 xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
2445 		   xmlParserErrors error,
2446 		   xmlNodePtr node,
2447 		   xmlSchemaBasicItemPtr item,
2448 		   const char *message,
2449 		   const xmlChar *str1,
2450 		   const xmlChar *str2)
2451 {
2452     xmlSchemaCustomErr4(actxt, error, node, item,
2453 	message, str1, str2, NULL, NULL);
2454 }
2455 
2456 
2457 
2458 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)2459 xmlSchemaCustomWarning(xmlSchemaAbstractCtxtPtr actxt,
2460 		   xmlParserErrors error,
2461 		   xmlNodePtr node,
2462 		   xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2463 		   const char *message,
2464 		   const xmlChar *str1,
2465 		   const xmlChar *str2,
2466 		   const xmlChar *str3)
2467 {
2468     xmlChar *msg = NULL;
2469 
2470     xmlSchemaFormatNodeForError(&msg, actxt, node);
2471     msg = xmlStrcat(msg, (const xmlChar *) message);
2472     msg = xmlStrcat(msg, BAD_CAST ".\n");
2473 
2474     /* URGENT TODO: Set the error code to something sane. */
2475     xmlSchemaErr4Line(actxt, XML_ERR_WARNING, error, node, 0,
2476 	(const char *) msg, str1, str2, str3, NULL);
2477 
2478     FREE_AND_NULL(msg)
2479 }
2480 
2481 
2482 
2483 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)2484 xmlSchemaKeyrefErr(xmlSchemaValidCtxtPtr vctxt,
2485 		   xmlParserErrors error,
2486 		   xmlSchemaPSVIIDCNodePtr idcNode,
2487 		   xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2488 		   const char *message,
2489 		   const xmlChar *str1,
2490 		   const xmlChar *str2)
2491 {
2492     xmlChar *msg = NULL, *qname = NULL;
2493 
2494     msg = xmlStrdup(BAD_CAST "Element '%s': ");
2495     msg = xmlStrcat(msg, (const xmlChar *) message);
2496     msg = xmlStrcat(msg, BAD_CAST ".\n");
2497     xmlSchemaErr4Line(ACTXT_CAST vctxt, XML_ERR_ERROR,
2498 	error, NULL, idcNode->nodeLine, (const char *) msg,
2499 	xmlSchemaFormatQName(&qname,
2500 	    vctxt->nodeQNames->items[idcNode->nodeQNameID +1],
2501 	    vctxt->nodeQNames->items[idcNode->nodeQNameID]),
2502 	str1, str2, NULL);
2503     FREE_AND_NULL(qname);
2504     FREE_AND_NULL(msg);
2505 }
2506 
2507 static int
xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,xmlNodePtr node)2508 xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
2509 			   xmlNodePtr node)
2510 {
2511     if (node != NULL)
2512 	return (node->type);
2513     if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
2514 	(((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
2515 	return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
2516     return (-1);
2517 }
2518 
2519 static int
xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)2520 xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
2521 {
2522     switch (item->type) {
2523 	case XML_SCHEMA_TYPE_COMPLEX:
2524 	case XML_SCHEMA_TYPE_SIMPLE:
2525 	    if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2526 		return(1);
2527 	    break;
2528 	case XML_SCHEMA_TYPE_GROUP:
2529 	    return (1);
2530 	case XML_SCHEMA_TYPE_ELEMENT:
2531 	    if ( ((xmlSchemaElementPtr) item)->flags &
2532 		XML_SCHEMAS_ELEM_GLOBAL)
2533 		return(1);
2534 	    break;
2535 	case XML_SCHEMA_TYPE_ATTRIBUTE:
2536 	    if ( ((xmlSchemaAttributePtr) item)->flags &
2537 		XML_SCHEMAS_ATTR_GLOBAL)
2538 		return(1);
2539 	    break;
2540 	/* Note that attribute groups are always global. */
2541 	default:
2542 	    return(1);
2543     }
2544     return (0);
2545 }
2546 
2547 static void
xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,xmlParserErrors error,xmlNodePtr node,const xmlChar * value,xmlSchemaTypePtr type,int displayValue)2548 xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2549 		       xmlParserErrors error,
2550 		       xmlNodePtr node,
2551 		       const xmlChar *value,
2552 		       xmlSchemaTypePtr type,
2553 		       int displayValue)
2554 {
2555     xmlChar *msg = NULL;
2556 
2557     xmlSchemaFormatNodeForError(&msg, actxt, node);
2558 
2559     if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2560 	    XML_ATTRIBUTE_NODE))
2561 	msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2562     else
2563 	msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
2564 	    "value of ");
2565 
2566     if (! xmlSchemaIsGlobalItem(type))
2567 	msg = xmlStrcat(msg, BAD_CAST "the local ");
2568     else
2569 	msg = xmlStrcat(msg, BAD_CAST "the ");
2570 
2571     if (WXS_IS_ATOMIC(type))
2572 	msg = xmlStrcat(msg, BAD_CAST "atomic type");
2573     else if (WXS_IS_LIST(type))
2574 	msg = xmlStrcat(msg, BAD_CAST "list type");
2575     else if (WXS_IS_UNION(type))
2576 	msg = xmlStrcat(msg, BAD_CAST "union type");
2577 
2578     if (xmlSchemaIsGlobalItem(type)) {
2579 	xmlChar *str = NULL;
2580 	msg = xmlStrcat(msg, BAD_CAST " '");
2581 	if (type->builtInType != 0) {
2582 	    msg = xmlStrcat(msg, BAD_CAST "xs:");
2583 	    str = xmlStrdup(type->name);
2584 	} else {
2585 	    const xmlChar *qName = xmlSchemaFormatQName(&str, type->targetNamespace, type->name);
2586 	    if (!str)
2587 		str = xmlStrdup(qName);
2588 	}
2589 	msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
2590 	msg = xmlStrcat(msg, BAD_CAST "'");
2591 	FREE_AND_NULL(str);
2592     }
2593     msg = xmlStrcat(msg, BAD_CAST ".\n");
2594     if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2595 	    XML_ATTRIBUTE_NODE))
2596 	xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2597     else
2598 	xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2599     FREE_AND_NULL(msg)
2600 }
2601 
2602 static const xmlChar *
xmlSchemaFormatErrorNodeQName(xmlChar ** str,xmlSchemaNodeInfoPtr ni,xmlNodePtr node)2603 xmlSchemaFormatErrorNodeQName(xmlChar ** str,
2604 			      xmlSchemaNodeInfoPtr ni,
2605 			      xmlNodePtr node)
2606 {
2607     if (node != NULL) {
2608 	if (node->ns != NULL)
2609 	    return (xmlSchemaFormatQName(str, node->ns->href, node->name));
2610 	else
2611 	    return (xmlSchemaFormatQName(str, NULL, node->name));
2612     } else if (ni != NULL)
2613 	return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
2614     return (NULL);
2615 }
2616 
2617 static void
xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,xmlParserErrors error,xmlSchemaAttrInfoPtr ni,xmlNodePtr node)2618 xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
2619 			xmlParserErrors error,
2620 			xmlSchemaAttrInfoPtr ni,
2621 			xmlNodePtr node)
2622 {
2623     xmlChar *msg = NULL, *str = NULL;
2624 
2625     xmlSchemaFormatNodeForError(&msg, actxt, node);
2626     msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
2627     xmlSchemaErr(actxt, error, node, (const char *) msg,
2628 	xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
2629 	NULL);
2630     FREE_AND_NULL(str)
2631     FREE_AND_NULL(msg)
2632 }
2633 
2634 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)2635 xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2636 		        xmlParserErrors error,
2637 		        xmlNodePtr node,
2638 			xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2639 			const char *message,
2640 			int nbval,
2641 			int nbneg,
2642 			xmlChar **values)
2643 {
2644     xmlChar *str = NULL, *msg = NULL;
2645     xmlChar *localName, *nsName;
2646     const xmlChar *cur, *end;
2647     int i;
2648 
2649     xmlSchemaFormatNodeForError(&msg, actxt, node);
2650     msg = xmlStrcat(msg, (const xmlChar *) message);
2651     msg = xmlStrcat(msg, BAD_CAST ".");
2652     /*
2653     * Note that is does not make sense to report that we have a
2654     * wildcard here, since the wildcard might be unfolded into
2655     * multiple transitions.
2656     */
2657     if (nbval + nbneg > 0) {
2658 	if (nbval + nbneg > 1) {
2659 	    str = xmlStrdup(BAD_CAST " Expected is one of ( ");
2660 	} else
2661 	    str = xmlStrdup(BAD_CAST " Expected is ( ");
2662 	nsName = NULL;
2663 
2664 	for (i = 0; i < nbval + nbneg; i++) {
2665 	    cur = values[i];
2666 	    if (cur == NULL)
2667 	        continue;
2668 	    if ((cur[0] == 'n') && (cur[1] == 'o') && (cur[2] == 't') &&
2669 	        (cur[3] == ' ')) {
2670 		cur += 4;
2671 		str = xmlStrcat(str, BAD_CAST "##other");
2672 	    }
2673 	    /*
2674 	    * Get the local name.
2675 	    */
2676 	    localName = NULL;
2677 
2678 	    end = cur;
2679 	    if (*end == '*') {
2680 		localName = xmlStrdup(BAD_CAST "*");
2681 		end++;
2682 	    } else {
2683 		while ((*end != 0) && (*end != '|'))
2684 		    end++;
2685 		localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
2686 	    }
2687 	    if (*end != 0) {
2688 		end++;
2689 		/*
2690 		* Skip "*|*" if they come with negated expressions, since
2691 		* they represent the same negated wildcard.
2692 		*/
2693 		if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
2694 		    /*
2695 		    * Get the namespace name.
2696 		    */
2697 		    cur = end;
2698 		    if (*end == '*') {
2699 			nsName = xmlStrdup(BAD_CAST "{*}");
2700 		    } else {
2701 			while (*end != 0)
2702 			    end++;
2703 
2704 			if (i >= nbval)
2705 			    nsName = xmlStrdup(BAD_CAST "{##other:");
2706 			else
2707 			    nsName = xmlStrdup(BAD_CAST "{");
2708 
2709 			nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
2710 			nsName = xmlStrcat(nsName, BAD_CAST "}");
2711 		    }
2712 		    str = xmlStrcat(str, BAD_CAST nsName);
2713 		    FREE_AND_NULL(nsName)
2714 		} else {
2715 		    FREE_AND_NULL(localName);
2716 		    continue;
2717 		}
2718 	    }
2719 	    str = xmlStrcat(str, BAD_CAST localName);
2720 	    FREE_AND_NULL(localName);
2721 
2722 	    if (i < nbval + nbneg -1)
2723 		str = xmlStrcat(str, BAD_CAST ", ");
2724 	}
2725 	str = xmlStrcat(str, BAD_CAST " ).\n");
2726 	msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
2727 	FREE_AND_NULL(str)
2728     } else
2729       msg = xmlStrcat(msg, BAD_CAST "\n");
2730     xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2731     xmlFree(msg);
2732 }
2733 
2734 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)2735 xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
2736 		  xmlParserErrors error,
2737 		  xmlNodePtr node,
2738 		  const xmlChar *value,
2739 		  unsigned long length,
2740 		  xmlSchemaTypePtr type,
2741 		  xmlSchemaFacetPtr facet,
2742 		  const char *message,
2743 		  const xmlChar *str1,
2744 		  const xmlChar *str2)
2745 {
2746     xmlChar *str = NULL, *msg = NULL;
2747     xmlSchemaTypeType facetType;
2748     int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
2749 
2750     xmlSchemaFormatNodeForError(&msg, actxt, node);
2751     if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
2752 	facetType = XML_SCHEMA_FACET_ENUMERATION;
2753 	/*
2754 	* If enumerations are validated, one must not expect the
2755 	* facet to be given.
2756 	*/
2757     } else
2758 	facetType = facet->type;
2759     msg = xmlStrcat(msg, BAD_CAST "[");
2760     msg = xmlStrcat(msg, BAD_CAST "facet '");
2761     msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
2762     msg = xmlStrcat(msg, BAD_CAST "'] ");
2763     if (message == NULL) {
2764 	/*
2765 	* Use a default message.
2766 	*/
2767 	if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
2768 	    (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
2769 	    (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
2770 
2771 	    char len[25], actLen[25];
2772 
2773 	    /* FIXME, TODO: What is the max expected string length of the
2774 	    * this value?
2775 	    */
2776 	    if (nodeType == XML_ATTRIBUTE_NODE)
2777 		msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
2778 	    else
2779 		msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
2780 
2781 	    snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
2782 	    snprintf(actLen, 24, "%lu", length);
2783 
2784 	    if (facetType == XML_SCHEMA_FACET_LENGTH)
2785 		msg = xmlStrcat(msg,
2786 		BAD_CAST "this differs from the allowed length of '%s'.\n");
2787 	    else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
2788 		msg = xmlStrcat(msg,
2789 		BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2790 	    else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
2791 		msg = xmlStrcat(msg,
2792 		BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
2793 
2794 	    if (nodeType == XML_ATTRIBUTE_NODE)
2795 		xmlSchemaErr3(actxt, error, node, (const char *) msg,
2796 		    value, (const xmlChar *) actLen, (const xmlChar *) len);
2797 	    else
2798 		xmlSchemaErr(actxt, error, node, (const char *) msg,
2799 		    (const xmlChar *) actLen, (const xmlChar *) len);
2800 
2801 	} else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2802 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2803 		"of the set {%s}.\n");
2804 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2805 		xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2806 	} else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2807 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2808 		"by the pattern '%s'.\n");
2809 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2810 		facet->value);
2811 	} else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2812 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2813 		"minimum value allowed ('%s').\n");
2814 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2815 		facet->value);
2816 	} else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2817 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2818 		"maximum value allowed ('%s').\n");
2819 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2820 		facet->value);
2821 	} else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
2822 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be greater than "
2823 		"'%s'.\n");
2824 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2825 		facet->value);
2826 	} else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
2827 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
2828 		"'%s'.\n");
2829 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2830 		facet->value);
2831 	} else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2832 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2833 		"digits than are allowed ('%s').\n");
2834 	    xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2835 		facet->value);
2836 	} else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2837 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2838 		"digits than are allowed ('%s').\n");
2839 	    xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2840 		facet->value);
2841 	} else if (nodeType == XML_ATTRIBUTE_NODE) {
2842 	    msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
2843 	    xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2844 	} else {
2845 	    msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2846 	    xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2847 	}
2848     } else {
2849 	msg = xmlStrcat(msg, (const xmlChar *) message);
2850 	msg = xmlStrcat(msg, BAD_CAST ".\n");
2851 	xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
2852     }
2853     FREE_AND_NULL(str)
2854     xmlFree(msg);
2855 }
2856 
2857 #define VERROR(err, type, msg) \
2858     xmlSchemaCustomErr(ACTXT_CAST vctxt, err, NULL, type, msg, NULL, NULL);
2859 
2860 #define VERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST vctxt, func, msg);
2861 
2862 #define PERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST pctxt, func, msg);
2863 #define PERROR_INT2(func, msg) xmlSchemaInternalErr(ACTXT_CAST ctxt, func, msg);
2864 
2865 #define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2866 
2867 
2868 /**
2869  * xmlSchemaPMissingAttrErr:
2870  * @ctxt: the schema validation context
2871  * @ownerItem: the owner as a schema object
2872  * @ownerElem: the owner as an element node
2873  * @node: the parent element node of the missing attribute node
2874  * @type: the corresponding type of the attribute node
2875  *
2876  * Reports an illegal attribute.
2877  */
2878 static void
xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr ownerItem,xmlNodePtr ownerElem,const char * name,const char * message)2879 xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
2880 			 xmlParserErrors error,
2881 			 xmlSchemaBasicItemPtr ownerItem,
2882 			 xmlNodePtr ownerElem,
2883 			 const char *name,
2884 			 const char *message)
2885 {
2886     xmlChar *des = NULL;
2887 
2888     xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2889 
2890     if (message != NULL)
2891 	xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
2892     else
2893 	xmlSchemaPErr(ctxt, ownerElem, error,
2894 	    "%s: The attribute '%s' is required but missing.\n",
2895 	    BAD_CAST des, BAD_CAST name);
2896     FREE_AND_NULL(des);
2897 }
2898 
2899 
2900 /**
2901  * xmlSchemaPResCompAttrErr:
2902  * @ctxt: the schema validation context
2903  * @error: the error code
2904  * @ownerItem: the owner as a schema object
2905  * @ownerElem: the owner as an element node
2906  * @name: the name of the attribute holding the QName
2907  * @refName: the referenced local name
2908  * @refURI: the referenced namespace URI
2909  * @message: optional message
2910  *
2911  * Used to report QName attribute values that failed to resolve
2912  * to schema components.
2913  */
2914 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)2915 xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
2916 			 xmlParserErrors error,
2917 			 xmlSchemaBasicItemPtr ownerItem,
2918 			 xmlNodePtr ownerElem,
2919 			 const char *name,
2920 			 const xmlChar *refName,
2921 			 const xmlChar *refURI,
2922 			 xmlSchemaTypeType refType,
2923 			 const char *refTypeStr)
2924 {
2925     xmlChar *des = NULL, *strA = NULL;
2926 
2927     xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2928     if (refTypeStr == NULL)
2929 	refTypeStr = (const char *) xmlSchemaItemTypeToStr(refType);
2930     xmlSchemaPErrExt(ctxt, ownerElem, error,
2931 	    NULL, NULL, NULL,
2932 	    "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2933 	    "%s.\n", BAD_CAST des, BAD_CAST name,
2934 	    xmlSchemaFormatQName(&strA, refURI, refName),
2935 	    BAD_CAST refTypeStr, NULL);
2936     FREE_AND_NULL(des)
2937     FREE_AND_NULL(strA)
2938 }
2939 
2940 /**
2941  * xmlSchemaPCustomAttrErr:
2942  * @ctxt: the schema parser context
2943  * @error: the error code
2944  * @ownerDes: the designation of the owner
2945  * @ownerItem: the owner as a schema object
2946  * @attr: the illegal attribute node
2947  *
2948  * Reports an illegal attribute during the parse.
2949  */
2950 static void
xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlChar ** ownerDes,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,const char * msg)2951 xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
2952 			xmlParserErrors error,
2953 			xmlChar **ownerDes,
2954 			xmlSchemaBasicItemPtr ownerItem,
2955 			xmlAttrPtr attr,
2956 			const char *msg)
2957 {
2958     xmlChar *des = NULL;
2959 
2960     if (ownerDes == NULL)
2961 	xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
2962     else if (*ownerDes == NULL) {
2963 	xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
2964 	des = *ownerDes;
2965     } else
2966 	des = *ownerDes;
2967     if (attr == NULL) {
2968 	xmlSchemaPErrExt(ctxt, NULL, error, NULL, NULL, NULL,
2969 	    "%s, attribute '%s': %s.\n",
2970 	    BAD_CAST des, (const xmlChar *) "Unknown",
2971 	    (const xmlChar *) msg, NULL, NULL);
2972     } else {
2973 	xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
2974 	    "%s, attribute '%s': %s.\n",
2975 	    BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2976     }
2977     if (ownerDes == NULL)
2978 	FREE_AND_NULL(des);
2979 }
2980 
2981 /**
2982  * xmlSchemaPIllegalAttrErr:
2983  * @ctxt: the schema parser context
2984  * @error: the error code
2985  * @ownerItem: the attribute's owner item
2986  * @attr: the illegal attribute node
2987  *
2988  * Reports an illegal attribute during the parse.
2989  */
2990 static void
xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr ownerComp ATTRIBUTE_UNUSED,xmlAttrPtr attr)2991 xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
2992 			 xmlParserErrors error,
2993 			 xmlSchemaBasicItemPtr ownerComp ATTRIBUTE_UNUSED,
2994 			 xmlAttrPtr attr)
2995 {
2996     xmlChar *strA = NULL, *strB = NULL;
2997 
2998     xmlSchemaFormatNodeForError(&strA, ACTXT_CAST ctxt, attr->parent);
2999     xmlSchemaErr4(ACTXT_CAST ctxt, error, (xmlNodePtr) attr,
3000 	"%sThe attribute '%s' is not allowed.\n", BAD_CAST strA,
3001 	xmlSchemaFormatQNameNs(&strB, attr->ns, attr->name),
3002 	NULL, NULL);
3003     FREE_AND_NULL(strA);
3004     FREE_AND_NULL(strB);
3005 }
3006 
3007 /**
3008  * xmlSchemaPCustomErr:
3009  * @ctxt: the schema parser context
3010  * @error: the error code
3011  * @itemDes: the designation of the schema item
3012  * @item: the schema item
3013  * @itemElem: the node of the schema item
3014  * @message: the error message
3015  * @str1: an optional param for the error message
3016  * @str2: an optional param for the error message
3017  * @str3: an optional param for the error message
3018  *
3019  * Reports an error during parsing.
3020  */
3021 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)3022 xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
3023 		    xmlParserErrors error,
3024 		    xmlSchemaBasicItemPtr item,
3025 		    xmlNodePtr itemElem,
3026 		    const char *message,
3027 		    const xmlChar *str1,
3028 		    const xmlChar *str2,
3029 		    const xmlChar *str3)
3030 {
3031     xmlChar *des = NULL, *msg = NULL;
3032 
3033     xmlSchemaFormatItemForReport(&des, NULL, item, itemElem);
3034     msg = xmlStrdup(BAD_CAST "%s: ");
3035     msg = xmlStrcat(msg, (const xmlChar *) message);
3036     msg = xmlStrcat(msg, BAD_CAST ".\n");
3037     if ((itemElem == NULL) && (item != NULL))
3038 	itemElem = WXS_ITEM_NODE(item);
3039     xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
3040 	(const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
3041     FREE_AND_NULL(des);
3042     FREE_AND_NULL(msg);
3043 }
3044 
3045 /**
3046  * xmlSchemaPCustomErr:
3047  * @ctxt: the schema parser context
3048  * @error: the error code
3049  * @itemDes: the designation of the schema item
3050  * @item: the schema item
3051  * @itemElem: the node of the schema item
3052  * @message: the error message
3053  * @str1: the optional param for the error message
3054  *
3055  * Reports an error during parsing.
3056  */
3057 static void LIBXML_ATTR_FORMAT(5,0)
xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr item,xmlNodePtr itemElem,const char * message,const xmlChar * str1)3058 xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
3059 		    xmlParserErrors error,
3060 		    xmlSchemaBasicItemPtr item,
3061 		    xmlNodePtr itemElem,
3062 		    const char *message,
3063 		    const xmlChar *str1)
3064 {
3065     xmlSchemaPCustomErrExt(ctxt, error, item, itemElem, message,
3066 	str1, NULL, NULL);
3067 }
3068 
3069 /**
3070  * xmlSchemaPAttrUseErr:
3071  * @ctxt: the schema parser context
3072  * @error: the error code
3073  * @itemDes: the designation of the schema type
3074  * @item: the schema type
3075  * @itemElem: the node of the schema type
3076  * @attr: the invalid schema attribute
3077  * @message: the error message
3078  * @str1: the optional param for the error message
3079  *
3080  * Reports an attribute use error during parsing.
3081  */
3082 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)3083 xmlSchemaPAttrUseErr4(xmlSchemaParserCtxtPtr ctxt,
3084 		    xmlParserErrors error,
3085 		    xmlNodePtr node,
3086 		    xmlSchemaBasicItemPtr ownerItem,
3087 		    const xmlSchemaAttributeUsePtr attruse,
3088 		    const char *message,
3089 		    const xmlChar *str1, const xmlChar *str2,
3090 		    const xmlChar *str3,const xmlChar *str4)
3091 {
3092     xmlChar *str = NULL, *msg = NULL;
3093 
3094     xmlSchemaFormatItemForReport(&msg, NULL, ownerItem, NULL);
3095     msg = xmlStrcat(msg, BAD_CAST ", ");
3096     msg = xmlStrcat(msg,
3097 	BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
3098 	WXS_BASIC_CAST attruse, NULL));
3099     FREE_AND_NULL(str);
3100     msg = xmlStrcat(msg, BAD_CAST ": ");
3101     msg = xmlStrcat(msg, (const xmlChar *) message);
3102     msg = xmlStrcat(msg, BAD_CAST ".\n");
3103     xmlSchemaErr4(ACTXT_CAST ctxt, error, node,
3104 	(const char *) msg, str1, str2, str3, str4);
3105     xmlFree(msg);
3106 }
3107 
3108 /**
3109  * xmlSchemaPIllegalFacetAtomicErr:
3110  * @ctxt: the schema parser context
3111  * @error: the error code
3112  * @type: the schema type
3113  * @baseType: the base type of type
3114  * @facet: the illegal facet
3115  *
3116  * Reports an illegal facet for atomic simple types.
3117  */
3118 static void
xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaTypePtr type,xmlSchemaTypePtr baseType,xmlSchemaFacetPtr facet)3119 xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
3120 			  xmlParserErrors error,
3121 			  xmlSchemaTypePtr type,
3122 			  xmlSchemaTypePtr baseType,
3123 			  xmlSchemaFacetPtr facet)
3124 {
3125     xmlChar *des = NULL, *strT = NULL;
3126 
3127     xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type, type->node);
3128     xmlSchemaPErrExt(ctxt, type->node, error, NULL, NULL, NULL,
3129 	"%s: The facet '%s' is not allowed on types derived from the "
3130 	"type %s.\n",
3131 	BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
3132 	xmlSchemaFormatItemForReport(&strT, NULL, WXS_BASIC_CAST baseType, NULL),
3133 	NULL, NULL);
3134     FREE_AND_NULL(des);
3135     FREE_AND_NULL(strT);
3136 }
3137 
3138 /**
3139  * xmlSchemaPIllegalFacetListUnionErr:
3140  * @ctxt: the schema parser context
3141  * @error: the error code
3142  * @itemDes: the designation of the schema item involved
3143  * @item: the schema item involved
3144  * @facet: the illegal facet
3145  *
3146  * Reports an illegal facet for <list> and <union>.
3147  */
3148 static void
xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaTypePtr type,xmlSchemaFacetPtr facet)3149 xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
3150 			  xmlParserErrors error,
3151 			  xmlSchemaTypePtr type,
3152 			  xmlSchemaFacetPtr facet)
3153 {
3154     xmlChar *des = NULL;
3155 
3156     xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type,
3157 	type->node);
3158     xmlSchemaPErr(ctxt, type->node, error,
3159 	"%s: The facet '%s' is not allowed.\n",
3160 	BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
3161     FREE_AND_NULL(des);
3162 }
3163 
3164 /**
3165  * xmlSchemaPMutualExclAttrErr:
3166  * @ctxt: the schema validation context
3167  * @error: the error code
3168  * @elemDes: the designation of the parent element node
3169  * @attr: the bad attribute node
3170  * @type: the corresponding type of the attribute node
3171  *
3172  * Reports an illegal attribute.
3173  */
3174 static void
xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,const char * name1,const char * name2)3175 xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
3176 			 xmlParserErrors error,
3177 			 xmlSchemaBasicItemPtr ownerItem,
3178 			 xmlAttrPtr attr,
3179 			 const char *name1,
3180 			 const char *name2)
3181 {
3182     xmlChar *des = NULL;
3183 
3184     xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST ownerItem, attr->parent);
3185     xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
3186 	"%s: The attributes '%s' and '%s' are mutually exclusive.\n",
3187 	BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
3188     FREE_AND_NULL(des);
3189 }
3190 
3191 /**
3192  * xmlSchemaPSimpleTypeErr:
3193  * @ctxt:  the schema validation context
3194  * @error: the error code
3195  * @type: the type specifier
3196  * @ownerItem: the schema object if existent
3197  * @node: the validated node
3198  * @value: the validated value
3199  *
3200  * Reports a simple type validation error.
3201  * TODO: Should this report the value of an element as well?
3202  */
3203 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)3204 xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
3205 			xmlParserErrors error,
3206 			xmlSchemaBasicItemPtr ownerItem ATTRIBUTE_UNUSED,
3207 			xmlNodePtr node,
3208 			xmlSchemaTypePtr type,
3209 			const char *expected,
3210 			const xmlChar *value,
3211 			const char *message,
3212 			const xmlChar *str1,
3213 			const xmlChar *str2)
3214 {
3215     xmlChar *msg = NULL;
3216 
3217     xmlSchemaFormatNodeForError(&msg, ACTXT_CAST ctxt, node);
3218     if (message == NULL) {
3219 	/*
3220 	* Use default messages.
3221 	*/
3222 	if (type != NULL) {
3223 	    if (node->type == XML_ATTRIBUTE_NODE)
3224 		msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
3225 	    else
3226 		msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
3227 		"valid value of ");
3228 	    if (! xmlSchemaIsGlobalItem(type))
3229 		msg = xmlStrcat(msg, BAD_CAST "the local ");
3230 	    else
3231 		msg = xmlStrcat(msg, BAD_CAST "the ");
3232 
3233 	    if (WXS_IS_ATOMIC(type))
3234 		msg = xmlStrcat(msg, BAD_CAST "atomic type");
3235 	    else if (WXS_IS_LIST(type))
3236 		msg = xmlStrcat(msg, BAD_CAST "list type");
3237 	    else if (WXS_IS_UNION(type))
3238 		msg = xmlStrcat(msg, BAD_CAST "union type");
3239 
3240 	    if (xmlSchemaIsGlobalItem(type)) {
3241 		xmlChar *str = NULL;
3242 		msg = xmlStrcat(msg, BAD_CAST " '");
3243 		if (type->builtInType != 0) {
3244 		    msg = xmlStrcat(msg, BAD_CAST "xs:");
3245 		    str = xmlStrdup(type->name);
3246 		} else {
3247 		    const xmlChar *qName = xmlSchemaFormatQName(&str, type->targetNamespace, type->name);
3248 		    if (!str)
3249 			str = xmlStrdup(qName);
3250 		}
3251 		msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
3252 		msg = xmlStrcat(msg, BAD_CAST "'.");
3253 		FREE_AND_NULL(str);
3254 	    }
3255 	} else {
3256 	    if (node->type == XML_ATTRIBUTE_NODE)
3257 		msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
3258 	    else
3259 		msg = xmlStrcat(msg, BAD_CAST "The character content is not "
3260 		"valid.");
3261 	}
3262 	if (expected) {
3263 	    xmlChar *expectedEscaped = xmlCharStrdup(expected);
3264 	    msg = xmlStrcat(msg, BAD_CAST " Expected is '");
3265 	    msg = xmlStrcat(msg, xmlEscapeFormatString(&expectedEscaped));
3266 	    FREE_AND_NULL(expectedEscaped);
3267 	    msg = xmlStrcat(msg, BAD_CAST "'.\n");
3268 	} else
3269 	    msg = xmlStrcat(msg, BAD_CAST "\n");
3270 	if (node->type == XML_ATTRIBUTE_NODE)
3271 	    xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
3272 	else
3273 	    xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
3274     } else {
3275 	msg = xmlStrcat(msg, BAD_CAST message);
3276 	msg = xmlStrcat(msg, BAD_CAST ".\n");
3277 	xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
3278 	     (const char*) msg, str1, str2, NULL, NULL, NULL);
3279     }
3280     /* Cleanup. */
3281     FREE_AND_NULL(msg)
3282 }
3283 
3284 /**
3285  * xmlSchemaPContentErr:
3286  * @ctxt: the schema parser context
3287  * @error: the error code
3288  * @ownerItem: the owner item of the holder of the content
3289  * @ownerElem: the node of the holder of the content
3290  * @child: the invalid child node
3291  * @message: the optional error message
3292  * @content: the optional string describing the correct content
3293  *
3294  * Reports an error concerning the content of a schema element.
3295  */
3296 static void
xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,xmlParserErrors error,xmlSchemaBasicItemPtr ownerItem,xmlNodePtr ownerElem,xmlNodePtr child,const char * message,const char * content)3297 xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
3298 		     xmlParserErrors error,
3299 		     xmlSchemaBasicItemPtr ownerItem,
3300 		     xmlNodePtr ownerElem,
3301 		     xmlNodePtr child,
3302 		     const char *message,
3303 		     const char *content)
3304 {
3305     xmlChar *des = NULL;
3306 
3307     xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
3308     if (message != NULL)
3309 	xmlSchemaPErr2(ctxt, ownerElem, child, error,
3310 	    "%s: %s.\n",
3311 	    BAD_CAST des, BAD_CAST message);
3312     else {
3313 	if (content != NULL) {
3314 	    xmlSchemaPErr2(ctxt, ownerElem, child, error,
3315 		"%s: The content is not valid. Expected is %s.\n",
3316 		BAD_CAST des, BAD_CAST content);
3317 	} else {
3318 	    xmlSchemaPErr2(ctxt, ownerElem, child, error,
3319 		"%s: The content is not valid.\n",
3320 		BAD_CAST des, NULL);
3321 	}
3322     }
3323     FREE_AND_NULL(des)
3324 }
3325 
3326 /************************************************************************
3327  *									*
3328  *			Streamable error functions                      *
3329  *									*
3330  ************************************************************************/
3331 
3332 
3333 
3334 
3335 /************************************************************************
3336  *									*
3337  *			Validation helper functions			*
3338  *									*
3339  ************************************************************************/
3340 
3341 
3342 /************************************************************************
3343  *									*
3344  *			Allocation functions				*
3345  *									*
3346  ************************************************************************/
3347 
3348 /**
3349  * xmlSchemaNewSchemaForParserCtxt:
3350  * @ctxt:  a schema validation context
3351  *
3352  * Allocate a new Schema structure.
3353  *
3354  * Returns the newly allocated structure or NULL in case or error
3355  */
3356 static xmlSchemaPtr
xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)3357 xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
3358 {
3359     xmlSchemaPtr ret;
3360 
3361     ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
3362     if (ret == NULL) {
3363         xmlSchemaPErrMemory(ctxt);
3364         return (NULL);
3365     }
3366     memset(ret, 0, sizeof(xmlSchema));
3367     ret->dict = ctxt->dict;
3368     xmlDictReference(ret->dict);
3369 
3370     return (ret);
3371 }
3372 
3373 /**
3374  * xmlSchemaNewFacet:
3375  *
3376  * Allocate a new Facet structure.
3377  *
3378  * Returns the newly allocated structure or NULL in case or error
3379  */
3380 xmlSchemaFacetPtr
xmlSchemaNewFacet(void)3381 xmlSchemaNewFacet(void)
3382 {
3383     xmlSchemaFacetPtr ret;
3384 
3385     ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
3386     if (ret == NULL) {
3387         return (NULL);
3388     }
3389     memset(ret, 0, sizeof(xmlSchemaFacet));
3390 
3391     return (ret);
3392 }
3393 
3394 /**
3395  * xmlSchemaNewAnnot:
3396  * @ctxt:  a schema validation context
3397  * @node:  a node
3398  *
3399  * Allocate a new annotation structure.
3400  *
3401  * Returns the newly allocated structure or NULL in case or error
3402  */
3403 static xmlSchemaAnnotPtr
xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node)3404 xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3405 {
3406     xmlSchemaAnnotPtr ret;
3407 
3408     ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
3409     if (ret == NULL) {
3410         xmlSchemaPErrMemory(ctxt);
3411         return (NULL);
3412     }
3413     memset(ret, 0, sizeof(xmlSchemaAnnot));
3414     ret->content = node;
3415     return (ret);
3416 }
3417 
3418 static xmlSchemaItemListPtr
xmlSchemaItemListCreate(void)3419 xmlSchemaItemListCreate(void)
3420 {
3421     xmlSchemaItemListPtr ret;
3422 
3423     ret = xmlMalloc(sizeof(xmlSchemaItemList));
3424     if (ret == NULL) {
3425 	xmlSchemaPErrMemory(NULL);
3426 	return (NULL);
3427     }
3428     memset(ret, 0, sizeof(xmlSchemaItemList));
3429     return (ret);
3430 }
3431 
3432 static void
xmlSchemaItemListClear(xmlSchemaItemListPtr list)3433 xmlSchemaItemListClear(xmlSchemaItemListPtr list)
3434 {
3435     if (list->items != NULL) {
3436 	xmlFree(list->items);
3437 	list->items = NULL;
3438     }
3439     list->nbItems = 0;
3440     list->sizeItems = 0;
3441 }
3442 
3443 static int
xmlSchemaItemListGrow(xmlSchemaItemListPtr list,int initialSize)3444 xmlSchemaItemListGrow(xmlSchemaItemListPtr list, int initialSize)
3445 {
3446     void **tmp;
3447     int newSize;
3448 
3449     if (initialSize <= 0)
3450         initialSize = 1;
3451     newSize = xmlGrowCapacity(list->sizeItems, sizeof(tmp[0]),
3452                               initialSize, XML_MAX_ITEMS);
3453     if (newSize < 0)
3454         return(-1);
3455     tmp = xmlRealloc(list->items, newSize * sizeof(tmp[0]));
3456     if (tmp == NULL)
3457         return(-1);
3458 
3459     list->items = tmp;
3460     list->sizeItems = newSize;
3461     return(0);
3462 }
3463 
3464 static int
xmlSchemaItemListAddSize(xmlSchemaItemListPtr list,int initialSize,void * item)3465 xmlSchemaItemListAddSize(xmlSchemaItemListPtr list,
3466 			 int initialSize,
3467 			 void *item)
3468 {
3469     if (list->sizeItems <= list->nbItems) {
3470         if (xmlSchemaItemListGrow(list, initialSize) < 0) {
3471 	    xmlSchemaPErrMemory(NULL);
3472 	    return(-1);
3473         }
3474     }
3475 
3476     list->items[list->nbItems++] = item;
3477     return(0);
3478 }
3479 
3480 static int
xmlSchemaItemListAdd(xmlSchemaItemListPtr list,void * item)3481 xmlSchemaItemListAdd(xmlSchemaItemListPtr list, void *item)
3482 {
3483     return(xmlSchemaItemListAddSize(list, 20, item));
3484 }
3485 
3486 static int
xmlSchemaItemListInsert(xmlSchemaItemListPtr list,void * item,int idx)3487 xmlSchemaItemListInsert(xmlSchemaItemListPtr list, void *item, int idx)
3488 {
3489     if (list->sizeItems <= list->nbItems) {
3490         if (xmlSchemaItemListGrow(list, 20) < 0) {
3491 	    xmlSchemaPErrMemory(NULL);
3492 	    return(-1);
3493         }
3494     }
3495 
3496     /*
3497     * Just append if the index is greater/equal than the item count.
3498     */
3499     if (idx >= list->nbItems) {
3500 	list->items[list->nbItems++] = item;
3501     } else {
3502 	int i;
3503 	for (i = list->nbItems; i > idx; i--)
3504 	    list->items[i] = list->items[i-1];
3505 	list->items[idx] = item;
3506 	list->nbItems++;
3507     }
3508     return(0);
3509 }
3510 
3511 static int
xmlSchemaItemListRemove(xmlSchemaItemListPtr list,int idx)3512 xmlSchemaItemListRemove(xmlSchemaItemListPtr list, int idx)
3513 {
3514     int i;
3515     if ((list->items == NULL) || (idx >= list->nbItems))
3516 	return(-1);
3517 
3518     if (list->nbItems == 1) {
3519 	/* TODO: Really free the list? */
3520 	xmlFree(list->items);
3521 	list->items = NULL;
3522 	list->nbItems = 0;
3523 	list->sizeItems = 0;
3524     } else if (list->nbItems -1 == idx) {
3525 	list->nbItems--;
3526     } else {
3527 	for (i = idx; i < list->nbItems -1; i++)
3528 	    list->items[i] = list->items[i+1];
3529 	list->nbItems--;
3530     }
3531     return(0);
3532 }
3533 
3534 /**
3535  * xmlSchemaItemListFree:
3536  * @annot:  a schema type structure
3537  *
3538  * Deallocate a annotation structure
3539  */
3540 static void
xmlSchemaItemListFree(xmlSchemaItemListPtr list)3541 xmlSchemaItemListFree(xmlSchemaItemListPtr list)
3542 {
3543     if (list == NULL)
3544 	return;
3545     if (list->items != NULL)
3546 	xmlFree(list->items);
3547     xmlFree(list);
3548 }
3549 
3550 static void
xmlSchemaBucketFree(xmlSchemaBucketPtr bucket)3551 xmlSchemaBucketFree(xmlSchemaBucketPtr bucket)
3552 {
3553     if (bucket == NULL)
3554 	return;
3555     if (bucket->globals != NULL) {
3556 	xmlSchemaComponentListFree(bucket->globals);
3557 	xmlSchemaItemListFree(bucket->globals);
3558     }
3559     if (bucket->locals != NULL) {
3560 	xmlSchemaComponentListFree(bucket->locals);
3561 	xmlSchemaItemListFree(bucket->locals);
3562     }
3563     if (bucket->relations != NULL) {
3564 	xmlSchemaSchemaRelationPtr prev, cur = bucket->relations;
3565 	do {
3566 	    prev = cur;
3567 	    cur = cur->next;
3568 	    xmlFree(prev);
3569 	} while (cur != NULL);
3570     }
3571     if ((! bucket->preserveDoc) && (bucket->doc != NULL)) {
3572 	xmlFreeDoc(bucket->doc);
3573     }
3574     if (bucket->type == XML_SCHEMA_SCHEMA_IMPORT) {
3575 	if (WXS_IMPBUCKET(bucket)->schema != NULL)
3576 	    xmlSchemaFree(WXS_IMPBUCKET(bucket)->schema);
3577     }
3578     xmlFree(bucket);
3579 }
3580 
3581 static void
xmlSchemaBucketFreeEntry(void * bucket,const xmlChar * name ATTRIBUTE_UNUSED)3582 xmlSchemaBucketFreeEntry(void *bucket, const xmlChar *name ATTRIBUTE_UNUSED)
3583 {
3584     xmlSchemaBucketFree((xmlSchemaBucketPtr) bucket);
3585 }
3586 
3587 static xmlSchemaBucketPtr
xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,int type,const xmlChar * targetNamespace)3588 xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,
3589 			 int type, const xmlChar *targetNamespace)
3590 {
3591     xmlSchemaBucketPtr ret;
3592     int size;
3593     xmlSchemaPtr mainSchema;
3594 
3595     if (WXS_CONSTRUCTOR(pctxt)->mainSchema == NULL) {
3596 	PERROR_INT("xmlSchemaBucketCreate",
3597 	    "no main schema on constructor");
3598 	return(NULL);
3599     }
3600     mainSchema = WXS_CONSTRUCTOR(pctxt)->mainSchema;
3601     /* Create the schema bucket. */
3602     if (WXS_IS_BUCKET_INCREDEF(type))
3603 	size = sizeof(xmlSchemaInclude);
3604     else
3605 	size = sizeof(xmlSchemaImport);
3606     ret = (xmlSchemaBucketPtr) xmlMalloc(size);
3607     if (ret == NULL) {
3608 	xmlSchemaPErrMemory(NULL);
3609 	return(NULL);
3610     }
3611     memset(ret, 0, size);
3612     ret->targetNamespace = targetNamespace;
3613     ret->type = type;
3614     ret->globals = xmlSchemaItemListCreate();
3615     if (ret->globals == NULL) {
3616 	xmlSchemaBucketFree(ret);
3617 	return(NULL);
3618     }
3619     ret->locals = xmlSchemaItemListCreate();
3620     if (ret->locals == NULL) {
3621 	xmlSchemaBucketFree(ret);
3622 	return(NULL);
3623     }
3624     /*
3625     * The following will assure that only the first bucket is marked as
3626     * XML_SCHEMA_SCHEMA_MAIN and it points to the *main* schema.
3627     * For each following import buckets an xmlSchema will be created.
3628     * An xmlSchema will be created for every distinct targetNamespace.
3629     * We assign the targetNamespace to the schemata here.
3630     */
3631     if (! WXS_HAS_BUCKETS(pctxt)) {
3632 	if (WXS_IS_BUCKET_INCREDEF(type)) {
3633 	    PERROR_INT("xmlSchemaBucketCreate",
3634 		"first bucket but it's an include or redefine");
3635 	    xmlSchemaBucketFree(ret);
3636 	    return(NULL);
3637 	}
3638 	/* Force the type to be XML_SCHEMA_SCHEMA_MAIN. */
3639 	ret->type = XML_SCHEMA_SCHEMA_MAIN;
3640 	/* Point to the *main* schema. */
3641 	WXS_CONSTRUCTOR(pctxt)->mainBucket = ret;
3642 	WXS_IMPBUCKET(ret)->schema = mainSchema;
3643 	/*
3644 	* Ensure that the main schema gets a targetNamespace.
3645 	*/
3646 	mainSchema->targetNamespace = targetNamespace;
3647     } else {
3648 	if (type == XML_SCHEMA_SCHEMA_MAIN) {
3649 	    PERROR_INT("xmlSchemaBucketCreate",
3650 		"main bucket but it's not the first one");
3651 	    xmlSchemaBucketFree(ret);
3652 	    return(NULL);
3653 	} else if (type == XML_SCHEMA_SCHEMA_IMPORT) {
3654 	    /*
3655 	    * Create a schema for imports and assign the
3656 	    * targetNamespace.
3657 	    */
3658 	    WXS_IMPBUCKET(ret)->schema = xmlSchemaNewSchema(pctxt);
3659 	    if (WXS_IMPBUCKET(ret)->schema == NULL) {
3660 		xmlSchemaBucketFree(ret);
3661 		return(NULL);
3662 	    }
3663 	    WXS_IMPBUCKET(ret)->schema->targetNamespace = targetNamespace;
3664 	}
3665     }
3666     if (WXS_IS_BUCKET_IMPMAIN(type)) {
3667 	int res;
3668 	/*
3669 	* Imports go into the "schemasImports" slot of the main *schema*.
3670 	* Note that we create an import entry for the main schema as well; i.e.,
3671 	* even if there's only one schema, we'll get an import.
3672 	*/
3673 	if (mainSchema->schemasImports == NULL) {
3674 	    mainSchema->schemasImports = xmlHashCreateDict(5,
3675 		WXS_CONSTRUCTOR(pctxt)->dict);
3676 	    if (mainSchema->schemasImports == NULL) {
3677 		xmlSchemaBucketFree(ret);
3678 		return(NULL);
3679 	    }
3680 	}
3681 	if (targetNamespace == NULL)
3682 	    res = xmlHashAddEntry(mainSchema->schemasImports,
3683 		XML_SCHEMAS_NO_NAMESPACE, ret);
3684 	else
3685 	    res = xmlHashAddEntry(mainSchema->schemasImports,
3686 		targetNamespace, ret);
3687 	if (res != 0) {
3688 	    PERROR_INT("xmlSchemaBucketCreate",
3689 		"failed to add the schema bucket to the hash");
3690 	    xmlSchemaBucketFree(ret);
3691 	    return(NULL);
3692 	}
3693     } else {
3694 	/* Set the @ownerImport of an include bucket. */
3695 	if (WXS_IS_BUCKET_IMPMAIN(WXS_CONSTRUCTOR(pctxt)->bucket->type))
3696 	    WXS_INCBUCKET(ret)->ownerImport =
3697 		WXS_IMPBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket);
3698 	else
3699 	    WXS_INCBUCKET(ret)->ownerImport =
3700 		WXS_INCBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket)->ownerImport;
3701 
3702 	/* Includes got into the "includes" slot of the *main* schema. */
3703 	if (mainSchema->includes == NULL) {
3704 	    mainSchema->includes = xmlSchemaItemListCreate();
3705 	    if (mainSchema->includes == NULL) {
3706 		xmlSchemaBucketFree(ret);
3707 		return(NULL);
3708 	    }
3709 	}
3710 	if (xmlSchemaItemListAdd(mainSchema->includes, ret) < 0) {
3711 	    xmlSchemaBucketFree(ret);
3712 	    return(NULL);
3713         }
3714     }
3715     /*
3716     * Add to list of all buckets; this is used for lookup
3717     * during schema construction time only.
3718     */
3719     if (xmlSchemaItemListAdd(WXS_CONSTRUCTOR(pctxt)->buckets, ret) == -1)
3720 	return(NULL);
3721     return(ret);
3722 }
3723 
3724 static int
xmlSchemaAddItemSize(xmlSchemaItemListPtr * list,int initialSize,void * item)3725 xmlSchemaAddItemSize(xmlSchemaItemListPtr *list, int initialSize, void *item)
3726 {
3727     if (*list == NULL) {
3728 	*list = xmlSchemaItemListCreate();
3729 	if (*list == NULL)
3730 	    return(-1);
3731     }
3732     return(xmlSchemaItemListAddSize(*list, initialSize, item));
3733 }
3734 
3735 /**
3736  * xmlSchemaFreeAnnot:
3737  * @annot:  a schema type structure
3738  *
3739  * Deallocate a annotation structure
3740  */
3741 static void
xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)3742 xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
3743 {
3744     if (annot == NULL)
3745         return;
3746     if (annot->next == NULL) {
3747 	xmlFree(annot);
3748     } else {
3749 	xmlSchemaAnnotPtr prev;
3750 
3751 	do {
3752 	    prev = annot;
3753 	    annot = annot->next;
3754 	    xmlFree(prev);
3755 	} while (annot != NULL);
3756     }
3757 }
3758 
3759 /**
3760  * xmlSchemaFreeNotation:
3761  * @schema:  a schema notation structure
3762  *
3763  * Deallocate a Schema Notation structure.
3764  */
3765 static void
xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)3766 xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
3767 {
3768     if (nota == NULL)
3769         return;
3770     if (nota->annot != NULL)
3771 	xmlSchemaFreeAnnot(nota->annot);
3772     xmlFree(nota);
3773 }
3774 
3775 /**
3776  * xmlSchemaFreeAttribute:
3777  * @attr:  an attribute declaration
3778  *
3779  * Deallocates an attribute declaration structure.
3780  */
3781 static void
xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)3782 xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
3783 {
3784     if (attr == NULL)
3785         return;
3786     if (attr->annot != NULL)
3787 	xmlSchemaFreeAnnot(attr->annot);
3788     if (attr->defVal != NULL)
3789 	xmlSchemaFreeValue(attr->defVal);
3790     xmlFree(attr);
3791 }
3792 
3793 /**
3794  * xmlSchemaFreeAttributeUse:
3795  * @use:  an attribute use
3796  *
3797  * Deallocates an attribute use structure.
3798  */
3799 static void
xmlSchemaFreeAttributeUse(xmlSchemaAttributeUsePtr use)3800 xmlSchemaFreeAttributeUse(xmlSchemaAttributeUsePtr use)
3801 {
3802     if (use == NULL)
3803         return;
3804     if (use->annot != NULL)
3805 	xmlSchemaFreeAnnot(use->annot);
3806     if (use->defVal != NULL)
3807 	xmlSchemaFreeValue(use->defVal);
3808     xmlFree(use);
3809 }
3810 
3811 /**
3812  * xmlSchemaFreeAttributeUseProhib:
3813  * @prohib:  an attribute use prohibition
3814  *
3815  * Deallocates an attribute use structure.
3816  */
3817 static void
xmlSchemaFreeAttributeUseProhib(xmlSchemaAttributeUseProhibPtr prohib)3818 xmlSchemaFreeAttributeUseProhib(xmlSchemaAttributeUseProhibPtr prohib)
3819 {
3820     if (prohib == NULL)
3821         return;
3822     xmlFree(prohib);
3823 }
3824 
3825 /**
3826  * xmlSchemaFreeWildcardNsSet:
3827  * set:  a schema wildcard namespace
3828  *
3829  * Deallocates a list of wildcard constraint structures.
3830  */
3831 static void
xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)3832 xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
3833 {
3834     xmlSchemaWildcardNsPtr next;
3835 
3836     while (set != NULL) {
3837 	next = set->next;
3838 	xmlFree(set);
3839 	set = next;
3840     }
3841 }
3842 
3843 /**
3844  * xmlSchemaFreeWildcard:
3845  * @wildcard:  a wildcard structure
3846  *
3847  * Deallocates a wildcard structure.
3848  */
3849 void
xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)3850 xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
3851 {
3852     if (wildcard == NULL)
3853         return;
3854     if (wildcard->annot != NULL)
3855         xmlSchemaFreeAnnot(wildcard->annot);
3856     if (wildcard->nsSet != NULL)
3857 	xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
3858     if (wildcard->negNsSet != NULL)
3859 	xmlFree(wildcard->negNsSet);
3860     xmlFree(wildcard);
3861 }
3862 
3863 /**
3864  * xmlSchemaFreeAttributeGroup:
3865  * @schema:  a schema attribute group structure
3866  *
3867  * Deallocate a Schema Attribute Group structure.
3868  */
3869 static void
xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attrGr)3870 xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attrGr)
3871 {
3872     if (attrGr == NULL)
3873         return;
3874     if (attrGr->annot != NULL)
3875         xmlSchemaFreeAnnot(attrGr->annot);
3876     if (attrGr->attrUses != NULL)
3877 	xmlSchemaItemListFree(WXS_LIST_CAST attrGr->attrUses);
3878     xmlFree(attrGr);
3879 }
3880 
3881 /**
3882  * xmlSchemaFreeQNameRef:
3883  * @item: a QName reference structure
3884  *
3885  * Deallocatea a QName reference structure.
3886  */
3887 static void
xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)3888 xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3889 {
3890     xmlFree(item);
3891 }
3892 
3893 /**
3894  * xmlSchemaFreeTypeLinkList:
3895  * @alink: a type link
3896  *
3897  * Deallocate a list of types.
3898  */
3899 static void
xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)3900 xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3901 {
3902     xmlSchemaTypeLinkPtr next;
3903 
3904     while (link != NULL) {
3905 	next = link->next;
3906 	xmlFree(link);
3907 	link = next;
3908     }
3909 }
3910 
3911 static void
xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)3912 xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3913 {
3914     xmlSchemaIDCStateObjPtr next;
3915     while (sto != NULL) {
3916 	next = sto->next;
3917 	if (sto->history != NULL)
3918 	    xmlFree(sto->history);
3919 	if (sto->xpathCtxt != NULL)
3920 	    xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3921 	xmlFree(sto);
3922 	sto = next;
3923     }
3924 }
3925 
3926 /**
3927  * xmlSchemaFreeIDC:
3928  * @idc: a identity-constraint definition
3929  *
3930  * Deallocates an identity-constraint definition.
3931  */
3932 static void
xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)3933 xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3934 {
3935     xmlSchemaIDCSelectPtr cur, prev;
3936 
3937     if (idcDef == NULL)
3938 	return;
3939     if (idcDef->annot != NULL)
3940         xmlSchemaFreeAnnot(idcDef->annot);
3941     /* Selector */
3942     if (idcDef->selector != NULL) {
3943 	if (idcDef->selector->xpathComp != NULL)
3944 	    xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3945 	xmlFree(idcDef->selector);
3946     }
3947     /* Fields */
3948     if (idcDef->fields != NULL) {
3949 	cur = idcDef->fields;
3950 	do {
3951 	    prev = cur;
3952 	    cur = cur->next;
3953 	    if (prev->xpathComp != NULL)
3954 		xmlFreePattern((xmlPatternPtr) prev->xpathComp);
3955 	    xmlFree(prev);
3956 	} while (cur != NULL);
3957     }
3958     xmlFree(idcDef);
3959 }
3960 
3961 /**
3962  * xmlSchemaFreeElement:
3963  * @schema:  a schema element structure
3964  *
3965  * Deallocate a Schema Element structure.
3966  */
3967 static void
xmlSchemaFreeElement(xmlSchemaElementPtr elem)3968 xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3969 {
3970     if (elem == NULL)
3971         return;
3972     if (elem->annot != NULL)
3973         xmlSchemaFreeAnnot(elem->annot);
3974     if (elem->contModel != NULL)
3975         xmlRegFreeRegexp(elem->contModel);
3976     if (elem->defVal != NULL)
3977 	xmlSchemaFreeValue(elem->defVal);
3978     xmlFree(elem);
3979 }
3980 
3981 /**
3982  * xmlSchemaFreeFacet:
3983  * @facet:  a schema facet structure
3984  *
3985  * Deallocate a Schema Facet structure.
3986  */
3987 void
xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)3988 xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
3989 {
3990     if (facet == NULL)
3991         return;
3992     if (facet->val != NULL)
3993         xmlSchemaFreeValue(facet->val);
3994     if (facet->regexp != NULL)
3995         xmlRegFreeRegexp(facet->regexp);
3996     if (facet->annot != NULL)
3997         xmlSchemaFreeAnnot(facet->annot);
3998     xmlFree(facet);
3999 }
4000 
4001 /**
4002  * xmlSchemaFreeType:
4003  * @type:  a schema type structure
4004  *
4005  * Deallocate a Schema Type structure.
4006  */
4007 void
xmlSchemaFreeType(xmlSchemaTypePtr type)4008 xmlSchemaFreeType(xmlSchemaTypePtr type)
4009 {
4010     if (type == NULL)
4011         return;
4012     if (type->annot != NULL)
4013         xmlSchemaFreeAnnot(type->annot);
4014     if (type->facets != NULL) {
4015         xmlSchemaFacetPtr facet, next;
4016 
4017         facet = type->facets;
4018         while (facet != NULL) {
4019             next = facet->next;
4020             xmlSchemaFreeFacet(facet);
4021             facet = next;
4022         }
4023     }
4024     if (type->attrUses != NULL)
4025 	xmlSchemaItemListFree((xmlSchemaItemListPtr) type->attrUses);
4026     if (type->memberTypes != NULL)
4027 	xmlSchemaFreeTypeLinkList(type->memberTypes);
4028     if (type->facetSet != NULL) {
4029 	xmlSchemaFacetLinkPtr next, link;
4030 
4031 	link = type->facetSet;
4032 	do {
4033 	    next = link->next;
4034 	    xmlFree(link);
4035 	    link = next;
4036 	} while (link != NULL);
4037     }
4038     if (type->contModel != NULL)
4039         xmlRegFreeRegexp(type->contModel);
4040     xmlFree(type);
4041 }
4042 
4043 /**
4044  * xmlSchemaFreeModelGroupDef:
4045  * @item:  a schema model group definition
4046  *
4047  * Deallocates a schema model group definition.
4048  */
4049 static void
xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)4050 xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
4051 {
4052     if (item->annot != NULL)
4053 	xmlSchemaFreeAnnot(item->annot);
4054     xmlFree(item);
4055 }
4056 
4057 /**
4058  * xmlSchemaFreeModelGroup:
4059  * @item:  a schema model group
4060  *
4061  * Deallocates a schema model group structure.
4062  */
4063 static void
xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)4064 xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
4065 {
4066     if (item->annot != NULL)
4067 	xmlSchemaFreeAnnot(item->annot);
4068     xmlFree(item);
4069 }
4070 
4071 static void
xmlSchemaComponentListFree(xmlSchemaItemListPtr list)4072 xmlSchemaComponentListFree(xmlSchemaItemListPtr list)
4073 {
4074     if ((list == NULL) || (list->nbItems == 0))
4075 	return;
4076     {
4077 	xmlSchemaTreeItemPtr item;
4078 	xmlSchemaTreeItemPtr *items = (xmlSchemaTreeItemPtr *) list->items;
4079 	int i;
4080 
4081 	for (i = 0; i < list->nbItems; i++) {
4082 	    item = items[i];
4083 	    if (item == NULL)
4084 		continue;
4085 	    switch (item->type) {
4086 		case XML_SCHEMA_TYPE_SIMPLE:
4087 		case XML_SCHEMA_TYPE_COMPLEX:
4088 		    xmlSchemaFreeType((xmlSchemaTypePtr) item);
4089 		    break;
4090 		case XML_SCHEMA_TYPE_ATTRIBUTE:
4091 		    xmlSchemaFreeAttribute((xmlSchemaAttributePtr) item);
4092 		    break;
4093 		case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
4094 		    xmlSchemaFreeAttributeUse((xmlSchemaAttributeUsePtr) item);
4095 		    break;
4096 		case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
4097 		    xmlSchemaFreeAttributeUseProhib(
4098 			(xmlSchemaAttributeUseProhibPtr) item);
4099 		    break;
4100 		case XML_SCHEMA_TYPE_ELEMENT:
4101 		    xmlSchemaFreeElement((xmlSchemaElementPtr) item);
4102 		    break;
4103 		case XML_SCHEMA_TYPE_PARTICLE:
4104 		    if (item->annot != NULL)
4105 			xmlSchemaFreeAnnot(item->annot);
4106 		    xmlFree(item);
4107 		    break;
4108 		case XML_SCHEMA_TYPE_SEQUENCE:
4109 		case XML_SCHEMA_TYPE_CHOICE:
4110 		case XML_SCHEMA_TYPE_ALL:
4111 		    xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
4112 		    break;
4113 		case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
4114 		    xmlSchemaFreeAttributeGroup(
4115 			(xmlSchemaAttributeGroupPtr) item);
4116 		    break;
4117 		case XML_SCHEMA_TYPE_GROUP:
4118 		    xmlSchemaFreeModelGroupDef(
4119 			(xmlSchemaModelGroupDefPtr) item);
4120 		    break;
4121 		case XML_SCHEMA_TYPE_ANY:
4122 		case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
4123 		    xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
4124 		    break;
4125 		case XML_SCHEMA_TYPE_IDC_KEY:
4126 		case XML_SCHEMA_TYPE_IDC_UNIQUE:
4127 		case XML_SCHEMA_TYPE_IDC_KEYREF:
4128 		    xmlSchemaFreeIDC((xmlSchemaIDCPtr) item);
4129 		    break;
4130 		case XML_SCHEMA_TYPE_NOTATION:
4131 		    xmlSchemaFreeNotation((xmlSchemaNotationPtr) item);
4132 		    break;
4133 		case XML_SCHEMA_EXTRA_QNAMEREF:
4134 		    xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
4135 		    break;
4136 		default:
4137 		    /* TODO: This should never be hit. */
4138 		    break;
4139 	    }
4140 	}
4141 	list->nbItems = 0;
4142     }
4143 }
4144 
4145 /**
4146  * xmlSchemaFree:
4147  * @schema:  a schema structure
4148  *
4149  * Deallocate a Schema structure.
4150  */
4151 void
xmlSchemaFree(xmlSchemaPtr schema)4152 xmlSchemaFree(xmlSchemaPtr schema)
4153 {
4154     if (schema == NULL)
4155         return;
4156     /*
4157     * Note that those slots are not responsible for freeing
4158     * schema components anymore; this will now be done by
4159     * the schema buckets.
4160     */
4161     if (schema->notaDecl != NULL)
4162         xmlHashFree(schema->notaDecl, NULL);
4163     if (schema->attrDecl != NULL)
4164         xmlHashFree(schema->attrDecl, NULL);
4165     if (schema->attrgrpDecl != NULL)
4166         xmlHashFree(schema->attrgrpDecl, NULL);
4167     if (schema->elemDecl != NULL)
4168         xmlHashFree(schema->elemDecl, NULL);
4169     if (schema->typeDecl != NULL)
4170         xmlHashFree(schema->typeDecl, NULL);
4171     if (schema->groupDecl != NULL)
4172         xmlHashFree(schema->groupDecl, NULL);
4173     if (schema->idcDef != NULL)
4174         xmlHashFree(schema->idcDef, NULL);
4175 
4176     if (schema->schemasImports != NULL)
4177 	xmlHashFree(schema->schemasImports, xmlSchemaBucketFreeEntry);
4178     if (schema->includes != NULL) {
4179 	xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->includes;
4180 	int i;
4181 	for (i = 0; i < list->nbItems; i++) {
4182 	    xmlSchemaBucketFree((xmlSchemaBucketPtr) list->items[i]);
4183 	}
4184 	xmlSchemaItemListFree(list);
4185     }
4186     if (schema->annot != NULL)
4187         xmlSchemaFreeAnnot(schema->annot);
4188     /* Never free the doc here, since this will be done by the buckets. */
4189 
4190     xmlDictFree(schema->dict);
4191     xmlFree(schema);
4192 }
4193 
4194 /************************************************************************
4195  *									*
4196  *			Debug functions					*
4197  *									*
4198  ************************************************************************/
4199 
4200 #ifdef LIBXML_OUTPUT_ENABLED
4201 
4202 static void
4203 xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output); /* forward */
4204 
4205 /**
4206  * xmlSchemaElementDump:
4207  * @elem:  an element
4208  * @output:  the file output
4209  *
4210  * Dump the element
4211  */
4212 static void
xmlSchemaElementDump(void * payload,void * data,const xmlChar * name ATTRIBUTE_UNUSED,const xmlChar * namespace ATTRIBUTE_UNUSED,const xmlChar * context ATTRIBUTE_UNUSED)4213 xmlSchemaElementDump(void *payload, void *data,
4214                      const xmlChar * name ATTRIBUTE_UNUSED,
4215 		     const xmlChar * namespace ATTRIBUTE_UNUSED,
4216                      const xmlChar * context ATTRIBUTE_UNUSED)
4217 {
4218     xmlSchemaElementPtr elem = (xmlSchemaElementPtr) payload;
4219     FILE *output = (FILE *) data;
4220     if (elem == NULL)
4221         return;
4222 
4223 
4224     fprintf(output, "Element");
4225     if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
4226 	fprintf(output, " (global)");
4227     fprintf(output, ": '%s' ", elem->name);
4228     if (namespace != NULL)
4229 	fprintf(output, "ns '%s'", namespace);
4230     fprintf(output, "\n");
4231 #if 0
4232     if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
4233 	fprintf(output, "  min %d ", elem->minOccurs);
4234         if (elem->maxOccurs >= UNBOUNDED)
4235             fprintf(output, "max: unbounded\n");
4236         else if (elem->maxOccurs != 1)
4237             fprintf(output, "max: %d\n", elem->maxOccurs);
4238         else
4239             fprintf(output, "\n");
4240     }
4241 #endif
4242     /*
4243     * Misc other properties.
4244     */
4245     if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
4246 	(elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
4247 	(elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
4248 	(elem->flags & XML_SCHEMAS_ELEM_DEFAULT)) {
4249 	fprintf(output, "  props: ");
4250 	if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
4251 	    fprintf(output, "[fixed] ");
4252 	if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
4253 	    fprintf(output, "[default] ");
4254 	if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
4255 	    fprintf(output, "[abstract] ");
4256 	if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
4257 	    fprintf(output, "[nillable] ");
4258 	fprintf(output, "\n");
4259     }
4260     /*
4261     * Default/fixed value.
4262     */
4263     if (elem->value != NULL)
4264 	fprintf(output, "  value: '%s'\n", elem->value);
4265     /*
4266     * Type.
4267     */
4268     if (elem->namedType != NULL) {
4269 	fprintf(output, "  type: '%s' ", elem->namedType);
4270 	if (elem->namedTypeNs != NULL)
4271 	    fprintf(output, "ns '%s'\n", elem->namedTypeNs);
4272 	else
4273 	    fprintf(output, "\n");
4274     } else if (elem->subtypes != NULL) {
4275 	/*
4276 	* Dump local types.
4277 	*/
4278 	xmlSchemaTypeDump(elem->subtypes, output);
4279     }
4280     /*
4281     * Substitution group.
4282     */
4283     if (elem->substGroup != NULL) {
4284 	fprintf(output, "  substitutionGroup: '%s' ", elem->substGroup);
4285 	if (elem->substGroupNs != NULL)
4286 	    fprintf(output, "ns '%s'\n", elem->substGroupNs);
4287 	else
4288 	    fprintf(output, "\n");
4289     }
4290 }
4291 
4292 /**
4293  * xmlSchemaAnnotDump:
4294  * @output:  the file output
4295  * @annot:  a annotation
4296  *
4297  * Dump the annotation
4298  */
4299 static void
xmlSchemaAnnotDump(FILE * output,xmlSchemaAnnotPtr annot)4300 xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
4301 {
4302     xmlChar *content;
4303 
4304     if (annot == NULL)
4305         return;
4306 
4307     content = xmlNodeGetContent(annot->content);
4308     if (content != NULL) {
4309         fprintf(output, "  Annot: %s\n", content);
4310         xmlFree(content);
4311     } else
4312         fprintf(output, "  Annot: empty\n");
4313 }
4314 
4315 /**
4316  * xmlSchemaContentModelDump:
4317  * @particle: the schema particle
4318  * @output: the file output
4319  * @depth: the depth used for indentation
4320  *
4321  * Dump a SchemaType structure
4322  */
4323 static void
xmlSchemaContentModelDump(xmlSchemaParticlePtr particle,FILE * output,int depth)4324 xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
4325 {
4326     xmlChar *str = NULL;
4327     xmlSchemaTreeItemPtr term;
4328     char shift[100];
4329     int i;
4330 
4331     if (particle == NULL)
4332 	return;
4333     for (i = 0;((i < depth) && (i < 25));i++)
4334         shift[2 * i] = shift[2 * i + 1] = ' ';
4335     shift[2 * i] = shift[2 * i + 1] = 0;
4336     fprintf(output, "%s", shift);
4337     if (particle->children == NULL) {
4338 	fprintf(output, "MISSING particle term\n");
4339 	return;
4340     }
4341     term = particle->children;
4342     if (term == NULL) {
4343 	fprintf(output, "(NULL)");
4344     } else {
4345 	switch (term->type) {
4346 	    case XML_SCHEMA_TYPE_ELEMENT:
4347 		fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
4348 		    ((xmlSchemaElementPtr)term)->targetNamespace,
4349 		    ((xmlSchemaElementPtr)term)->name));
4350 		FREE_AND_NULL(str);
4351 		break;
4352 	    case XML_SCHEMA_TYPE_SEQUENCE:
4353 		fprintf(output, "SEQUENCE");
4354 		break;
4355 	    case XML_SCHEMA_TYPE_CHOICE:
4356 		fprintf(output, "CHOICE");
4357 		break;
4358 	    case XML_SCHEMA_TYPE_ALL:
4359 		fprintf(output, "ALL");
4360 		break;
4361 	    case XML_SCHEMA_TYPE_ANY:
4362 		fprintf(output, "ANY");
4363 		break;
4364 	    default:
4365 		fprintf(output, "UNKNOWN\n");
4366 		return;
4367 	}
4368     }
4369     if (particle->minOccurs != 1)
4370 	fprintf(output, " min: %d", particle->minOccurs);
4371     if (particle->maxOccurs >= UNBOUNDED)
4372 	fprintf(output, " max: unbounded");
4373     else if (particle->maxOccurs != 1)
4374 	fprintf(output, " max: %d", particle->maxOccurs);
4375     fprintf(output, "\n");
4376     if (term &&
4377 	((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
4378 	 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
4379 	 (term->type == XML_SCHEMA_TYPE_ALL)) &&
4380 	 (term->children != NULL)) {
4381 	xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
4382 	    output, depth +1);
4383     }
4384     if (particle->next != NULL)
4385 	xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
4386 		output, depth);
4387 }
4388 
4389 /**
4390  * xmlSchemaAttrUsesDump:
4391  * @uses:  attribute uses list
4392  * @output:  the file output
4393  *
4394  * Dumps a list of attribute use components.
4395  */
4396 static void
xmlSchemaAttrUsesDump(xmlSchemaItemListPtr uses,FILE * output)4397 xmlSchemaAttrUsesDump(xmlSchemaItemListPtr uses, FILE * output)
4398 {
4399     xmlSchemaAttributeUsePtr use;
4400     xmlSchemaAttributeUseProhibPtr prohib;
4401     xmlSchemaQNameRefPtr ref;
4402     const xmlChar *name, *tns;
4403     xmlChar *str = NULL;
4404     int i;
4405 
4406     if ((uses == NULL) || (uses->nbItems == 0))
4407         return;
4408 
4409     fprintf(output, "  attributes:\n");
4410     for (i = 0; i < uses->nbItems; i++) {
4411 	use = uses->items[i];
4412 	if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
4413 	    fprintf(output, "  [prohibition] ");
4414 	    prohib = (xmlSchemaAttributeUseProhibPtr) use;
4415 	    name = prohib->name;
4416 	    tns = prohib->targetNamespace;
4417 	} else if (use->type == XML_SCHEMA_EXTRA_QNAMEREF) {
4418 	    fprintf(output, "  [reference] ");
4419 	    ref = (xmlSchemaQNameRefPtr) use;
4420 	    name = ref->name;
4421 	    tns = ref->targetNamespace;
4422 	} else {
4423 	    fprintf(output, "  [use] ");
4424 	    name = WXS_ATTRUSE_DECL_NAME(use);
4425 	    tns = WXS_ATTRUSE_DECL_TNS(use);
4426 	}
4427 	fprintf(output, "'%s'\n",
4428 	    (const char *) xmlSchemaFormatQName(&str, tns, name));
4429 	FREE_AND_NULL(str);
4430     }
4431 }
4432 
4433 /**
4434  * xmlSchemaTypeDump:
4435  * @output:  the file output
4436  * @type:  a type structure
4437  *
4438  * Dump a SchemaType structure
4439  */
4440 static void
xmlSchemaTypeDump(xmlSchemaTypePtr type,FILE * output)4441 xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
4442 {
4443     if (type == NULL) {
4444         fprintf(output, "Type: NULL\n");
4445         return;
4446     }
4447     fprintf(output, "Type: ");
4448     if (type->name != NULL)
4449         fprintf(output, "'%s' ", type->name);
4450     else
4451         fprintf(output, "(no name) ");
4452     if (type->targetNamespace != NULL)
4453 	fprintf(output, "ns '%s' ", type->targetNamespace);
4454     switch (type->type) {
4455         case XML_SCHEMA_TYPE_BASIC:
4456             fprintf(output, "[basic] ");
4457             break;
4458         case XML_SCHEMA_TYPE_SIMPLE:
4459             fprintf(output, "[simple] ");
4460             break;
4461         case XML_SCHEMA_TYPE_COMPLEX:
4462             fprintf(output, "[complex] ");
4463             break;
4464         case XML_SCHEMA_TYPE_SEQUENCE:
4465             fprintf(output, "[sequence] ");
4466             break;
4467         case XML_SCHEMA_TYPE_CHOICE:
4468             fprintf(output, "[choice] ");
4469             break;
4470         case XML_SCHEMA_TYPE_ALL:
4471             fprintf(output, "[all] ");
4472             break;
4473         case XML_SCHEMA_TYPE_UR:
4474             fprintf(output, "[ur] ");
4475             break;
4476         case XML_SCHEMA_TYPE_RESTRICTION:
4477             fprintf(output, "[restriction] ");
4478             break;
4479         case XML_SCHEMA_TYPE_EXTENSION:
4480             fprintf(output, "[extension] ");
4481             break;
4482         default:
4483             fprintf(output, "[unknown type %d] ", type->type);
4484             break;
4485     }
4486     fprintf(output, "content: ");
4487     switch (type->contentType) {
4488         case XML_SCHEMA_CONTENT_UNKNOWN:
4489             fprintf(output, "[unknown] ");
4490             break;
4491         case XML_SCHEMA_CONTENT_EMPTY:
4492             fprintf(output, "[empty] ");
4493             break;
4494         case XML_SCHEMA_CONTENT_ELEMENTS:
4495             fprintf(output, "[element] ");
4496             break;
4497         case XML_SCHEMA_CONTENT_MIXED:
4498             fprintf(output, "[mixed] ");
4499             break;
4500         case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
4501 	/* not used. */
4502             break;
4503         case XML_SCHEMA_CONTENT_BASIC:
4504             fprintf(output, "[basic] ");
4505             break;
4506         case XML_SCHEMA_CONTENT_SIMPLE:
4507             fprintf(output, "[simple] ");
4508             break;
4509         case XML_SCHEMA_CONTENT_ANY:
4510             fprintf(output, "[any] ");
4511             break;
4512     }
4513     fprintf(output, "\n");
4514     if (type->base != NULL) {
4515         fprintf(output, "  base type: '%s'", type->base);
4516 	if (type->baseNs != NULL)
4517 	    fprintf(output, " ns '%s'\n", type->baseNs);
4518 	else
4519 	    fprintf(output, "\n");
4520     }
4521     if (type->attrUses != NULL)
4522 	xmlSchemaAttrUsesDump(type->attrUses, output);
4523     if (type->annot != NULL)
4524         xmlSchemaAnnotDump(output, type->annot);
4525 #ifdef DUMP_CONTENT_MODEL
4526     if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
4527 	(type->subtypes != NULL)) {
4528 	xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
4529 	    output, 1);
4530     }
4531 #endif
4532 }
4533 
4534 static void
xmlSchemaTypeDumpEntry(void * type,void * output,const xmlChar * name ATTRIBUTE_UNUSED)4535 xmlSchemaTypeDumpEntry(void *type, void *output,
4536                        const xmlChar *name ATTRIBUTE_UNUSED)
4537 {
4538     xmlSchemaTypeDump((xmlSchemaTypePtr) type, (FILE *) output);
4539 }
4540 
4541 /**
4542  * xmlSchemaDump:
4543  * @output:  the file output
4544  * @schema:  a schema structure
4545  *
4546  * Dump a Schema structure.
4547  */
4548 void
xmlSchemaDump(FILE * output,xmlSchemaPtr schema)4549 xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
4550 {
4551     if (output == NULL)
4552         return;
4553     if (schema == NULL) {
4554         fprintf(output, "Schemas: NULL\n");
4555         return;
4556     }
4557     fprintf(output, "Schemas: ");
4558     if (schema->name != NULL)
4559         fprintf(output, "%s, ", schema->name);
4560     else
4561         fprintf(output, "no name, ");
4562     if (schema->targetNamespace != NULL)
4563         fprintf(output, "%s", (const char *) schema->targetNamespace);
4564     else
4565         fprintf(output, "no target namespace");
4566     fprintf(output, "\n");
4567     if (schema->annot != NULL)
4568         xmlSchemaAnnotDump(output, schema->annot);
4569     xmlHashScan(schema->typeDecl, xmlSchemaTypeDumpEntry, output);
4570     xmlHashScanFull(schema->elemDecl, xmlSchemaElementDump, output);
4571 }
4572 
4573 #endif /* LIBXML_OUTPUT_ENABLED */
4574 
4575 /************************************************************************
4576  *									*
4577  *			Utilities					*
4578  *									*
4579  ************************************************************************/
4580 
4581 /**
4582  * xmlSchemaGetPropNode:
4583  * @node: the element node
4584  * @name: the name of the attribute
4585  *
4586  * Seeks an attribute with a name of @name in
4587  * no namespace.
4588  *
4589  * Returns the attribute or NULL if not present.
4590  */
4591 static xmlAttrPtr
xmlSchemaGetPropNode(xmlNodePtr node,const char * name)4592 xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
4593 {
4594     xmlAttrPtr prop;
4595 
4596     if ((node == NULL) || (name == NULL))
4597 	return(NULL);
4598     prop = node->properties;
4599     while (prop != NULL) {
4600         if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
4601 	    return(prop);
4602 	prop = prop->next;
4603     }
4604     return (NULL);
4605 }
4606 
4607 /**
4608  * xmlSchemaGetPropNodeNs:
4609  * @node: the element node
4610  * @uri: the uri
4611  * @name: the name of the attribute
4612  *
4613  * Seeks an attribute with a local name of @name and
4614  * a namespace URI of @uri.
4615  *
4616  * Returns the attribute or NULL if not present.
4617  */
4618 static xmlAttrPtr
xmlSchemaGetPropNodeNs(xmlNodePtr node,const char * uri,const char * name)4619 xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
4620 {
4621     xmlAttrPtr prop;
4622 
4623     if ((node == NULL) || (name == NULL))
4624 	return(NULL);
4625     prop = node->properties;
4626     while (prop != NULL) {
4627 	if ((prop->ns != NULL) &&
4628 	    xmlStrEqual(prop->name, BAD_CAST name) &&
4629 	    xmlStrEqual(prop->ns->href, BAD_CAST uri))
4630 	    return(prop);
4631 	prop = prop->next;
4632     }
4633     return (NULL);
4634 }
4635 
4636 static const xmlChar *
xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node)4637 xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
4638 {
4639     xmlChar *val;
4640     const xmlChar *ret;
4641 
4642     val = xmlNodeGetContent(node);
4643     if (val == NULL)
4644 	val = xmlStrdup((xmlChar *)"");
4645     ret = xmlDictLookup(ctxt->dict, val, -1);
4646     xmlFree(val);
4647     if (ret == NULL)
4648         xmlSchemaPErrMemory(ctxt);
4649     return(ret);
4650 }
4651 
4652 static const xmlChar *
xmlSchemaGetNodeContentNoDict(xmlNodePtr node)4653 xmlSchemaGetNodeContentNoDict(xmlNodePtr node)
4654 {
4655     return((const xmlChar*) xmlNodeGetContent(node));
4656 }
4657 
4658 /**
4659  * xmlSchemaGetProp:
4660  * @ctxt: the parser context
4661  * @node: the node
4662  * @name: the property name
4663  *
4664  * Read a attribute value and internalize the string
4665  *
4666  * Returns the string or NULL if not present.
4667  */
4668 static const xmlChar *
xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,const char * name)4669 xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4670                  const char *name)
4671 {
4672     xmlChar *val;
4673     const xmlChar *ret;
4674 
4675     val = xmlGetNoNsProp(node, BAD_CAST name);
4676     if (val == NULL)
4677         return(NULL);
4678     ret = xmlDictLookup(ctxt->dict, val, -1);
4679     xmlFree(val);
4680     return(ret);
4681 }
4682 
4683 /************************************************************************
4684  *									*
4685  *			Parsing functions				*
4686  *									*
4687  ************************************************************************/
4688 
4689 #define WXS_FIND_GLOBAL_ITEM(slot)			\
4690     if (xmlStrEqual(nsName, schema->targetNamespace)) { \
4691 	ret = xmlHashLookup(schema->slot, name); \
4692 	if (ret != NULL) goto exit; \
4693     } \
4694     if (xmlHashSize(schema->schemasImports) > 1) { \
4695 	xmlSchemaImportPtr import; \
4696 	if (nsName == NULL) \
4697 	    import = xmlHashLookup(schema->schemasImports, \
4698 		XML_SCHEMAS_NO_NAMESPACE); \
4699 	else \
4700 	    import = xmlHashLookup(schema->schemasImports, nsName); \
4701 	if (import == NULL) \
4702 	    goto exit; \
4703 	ret = xmlHashLookup(import->schema->slot, name); \
4704     }
4705 
4706 /**
4707  * xmlSchemaGetElem:
4708  * @schema:  the schema context
4709  * @name:  the element name
4710  * @ns:  the element namespace
4711  *
4712  * Lookup a global element declaration in the schema.
4713  *
4714  * Returns the element declaration or NULL if not found.
4715  */
4716 static xmlSchemaElementPtr
xmlSchemaGetElem(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4717 xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
4718                  const xmlChar * nsName)
4719 {
4720     xmlSchemaElementPtr ret = NULL;
4721 
4722     if ((name == NULL) || (schema == NULL))
4723         return(NULL);
4724     if (schema != NULL) {
4725 	WXS_FIND_GLOBAL_ITEM(elemDecl)
4726     }
4727 exit:
4728     return (ret);
4729 }
4730 
4731 /**
4732  * xmlSchemaGetType:
4733  * @schema:  the main schema
4734  * @name:  the type's name
4735  * nsName:  the type's namespace
4736  *
4737  * Lookup a type in the schemas or the predefined types
4738  *
4739  * Returns the group definition or NULL if not found.
4740  */
4741 static xmlSchemaTypePtr
xmlSchemaGetType(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4742 xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
4743                  const xmlChar * nsName)
4744 {
4745     xmlSchemaTypePtr ret = NULL;
4746 
4747     if (name == NULL)
4748         return (NULL);
4749     /* First try the built-in types. */
4750     if ((nsName != NULL) && xmlStrEqual(nsName, xmlSchemaNs)) {
4751 	ret = xmlSchemaGetPredefinedType(name, nsName);
4752 	if (ret != NULL)
4753 	    goto exit;
4754 	/*
4755 	* Note that we try the parsed schemas as well here
4756 	* since one might have parsed the S4S, which contain more
4757 	* than the built-in types.
4758 	* TODO: Can we optimize this?
4759 	*/
4760     }
4761     if (schema != NULL) {
4762 	WXS_FIND_GLOBAL_ITEM(typeDecl)
4763     }
4764 exit:
4765 
4766     return (ret);
4767 }
4768 
4769 /**
4770  * xmlSchemaGetAttributeDecl:
4771  * @schema:  the context of the schema
4772  * @name:  the name of the attribute
4773  * @ns:  the target namespace of the attribute
4774  *
4775  * Lookup a an attribute in the schema or imported schemas
4776  *
4777  * Returns the attribute declaration or NULL if not found.
4778  */
4779 static xmlSchemaAttributePtr
xmlSchemaGetAttributeDecl(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4780 xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
4781                  const xmlChar * nsName)
4782 {
4783     xmlSchemaAttributePtr ret = NULL;
4784 
4785     if ((name == NULL) || (schema == NULL))
4786         return (NULL);
4787     if (schema != NULL) {
4788 	WXS_FIND_GLOBAL_ITEM(attrDecl)
4789     }
4790 exit:
4791     return (ret);
4792 }
4793 
4794 /**
4795  * xmlSchemaGetAttributeGroup:
4796  * @schema:  the context of the schema
4797  * @name:  the name of the attribute group
4798  * @ns:  the target namespace of the attribute group
4799  *
4800  * Lookup a an attribute group in the schema or imported schemas
4801  *
4802  * Returns the attribute group definition or NULL if not found.
4803  */
4804 static xmlSchemaAttributeGroupPtr
xmlSchemaGetAttributeGroup(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4805 xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
4806                  const xmlChar * nsName)
4807 {
4808     xmlSchemaAttributeGroupPtr ret = NULL;
4809 
4810     if ((name == NULL) || (schema == NULL))
4811         return (NULL);
4812     if (schema != NULL) {
4813 	WXS_FIND_GLOBAL_ITEM(attrgrpDecl)
4814     }
4815 exit:
4816     /* TODO:
4817     if ((ret != NULL) && (ret->redef != NULL)) {
4818 	* Return the last redefinition. *
4819 	ret = ret->redef;
4820     }
4821     */
4822     return (ret);
4823 }
4824 
4825 /**
4826  * xmlSchemaGetGroup:
4827  * @schema:  the context of the schema
4828  * @name:  the name of the group
4829  * @ns:  the target namespace of the group
4830  *
4831  * Lookup a group in the schema or imported schemas
4832  *
4833  * Returns the group definition or NULL if not found.
4834  */
4835 static xmlSchemaModelGroupDefPtr
xmlSchemaGetGroup(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4836 xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
4837                  const xmlChar * nsName)
4838 {
4839     xmlSchemaModelGroupDefPtr ret = NULL;
4840 
4841     if ((name == NULL) || (schema == NULL))
4842         return (NULL);
4843     if (schema != NULL) {
4844 	WXS_FIND_GLOBAL_ITEM(groupDecl)
4845     }
4846 exit:
4847 
4848     return (ret);
4849 }
4850 
4851 static xmlSchemaNotationPtr
xmlSchemaGetNotation(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4852 xmlSchemaGetNotation(xmlSchemaPtr schema,
4853 		     const xmlChar *name,
4854 		     const xmlChar *nsName)
4855 {
4856     xmlSchemaNotationPtr ret = NULL;
4857 
4858     if ((name == NULL) || (schema == NULL))
4859         return (NULL);
4860     if (schema != NULL) {
4861 	WXS_FIND_GLOBAL_ITEM(notaDecl)
4862     }
4863 exit:
4864     return (ret);
4865 }
4866 
4867 static xmlSchemaIDCPtr
xmlSchemaGetIDC(xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName)4868 xmlSchemaGetIDC(xmlSchemaPtr schema,
4869 		const xmlChar *name,
4870 		const xmlChar *nsName)
4871 {
4872     xmlSchemaIDCPtr ret = NULL;
4873 
4874     if ((name == NULL) || (schema == NULL))
4875         return (NULL);
4876     if (schema != NULL) {
4877 	WXS_FIND_GLOBAL_ITEM(idcDef)
4878     }
4879 exit:
4880     return (ret);
4881 }
4882 
4883 /**
4884  * xmlSchemaGetNamedComponent:
4885  * @schema:  the schema
4886  * @name:  the name of the group
4887  * @ns:  the target namespace of the group
4888  *
4889  * Lookup a group in the schema or imported schemas
4890  *
4891  * Returns the group definition or NULL if not found.
4892  */
4893 static xmlSchemaBasicItemPtr
xmlSchemaGetNamedComponent(xmlSchemaPtr schema,xmlSchemaTypeType itemType,const xmlChar * name,const xmlChar * targetNs)4894 xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
4895 			   xmlSchemaTypeType itemType,
4896 			   const xmlChar *name,
4897 			   const xmlChar *targetNs)
4898 {
4899     switch (itemType) {
4900 	case XML_SCHEMA_TYPE_GROUP:
4901 	    return ((xmlSchemaBasicItemPtr) xmlSchemaGetGroup(schema,
4902 		name, targetNs));
4903 	case XML_SCHEMA_TYPE_ELEMENT:
4904 	    return ((xmlSchemaBasicItemPtr) xmlSchemaGetElem(schema,
4905 		name, targetNs));
4906 	default:
4907 	    /* TODO */
4908 	    return (NULL);
4909     }
4910 }
4911 
4912 /************************************************************************
4913  *									*
4914  *			Parsing functions				*
4915  *									*
4916  ************************************************************************/
4917 
4918 #define IS_BLANK_NODE(n)						\
4919     (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
4920 
4921 /**
4922  * xmlSchemaIsBlank:
4923  * @str:  a string
4924  * @len: the length of the string or -1
4925  *
4926  * Check if a string is ignorable
4927  *
4928  * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
4929  */
4930 static int
xmlSchemaIsBlank(xmlChar * str,int len)4931 xmlSchemaIsBlank(xmlChar * str, int len)
4932 {
4933     if (str == NULL)
4934         return (1);
4935     if (len < 0) {
4936 	while (*str != 0) {
4937 	    if (!(IS_BLANK_CH(*str)))
4938 		return (0);
4939 	    str++;
4940 	}
4941     } else while ((*str != 0) && (len != 0)) {
4942 	if (!(IS_BLANK_CH(*str)))
4943 	    return (0);
4944 	str++;
4945 	len--;
4946     }
4947 
4948     return (1);
4949 }
4950 
4951 #define WXS_COMP_NAME(c, t) ((t) (c))->name
4952 #define WXS_COMP_TNS(c, t) ((t) (c))->targetNamespace
4953 /*
4954 * xmlSchemaFindRedefCompInGraph:
4955 * ATTENTION TODO: This uses pointer comp. for strings.
4956 */
4957 static xmlSchemaBasicItemPtr
xmlSchemaFindRedefCompInGraph(xmlSchemaBucketPtr bucket,xmlSchemaTypeType type,const xmlChar * name,const xmlChar * nsName)4958 xmlSchemaFindRedefCompInGraph(xmlSchemaBucketPtr bucket,
4959 			      xmlSchemaTypeType type,
4960 			      const xmlChar *name,
4961 			      const xmlChar *nsName)
4962 {
4963     xmlSchemaBasicItemPtr ret;
4964     int i;
4965 
4966     if ((bucket == NULL) || (name == NULL))
4967 	return(NULL);
4968     if ((bucket->globals == NULL) ||
4969 	(bucket->globals->nbItems == 0))
4970 	goto subschemas;
4971     /*
4972     * Search in global components.
4973     */
4974     for (i = 0; i < bucket->globals->nbItems; i++) {
4975 	ret = bucket->globals->items[i];
4976 	if (ret->type == type) {
4977 	    switch (type) {
4978 		case XML_SCHEMA_TYPE_COMPLEX:
4979 		case XML_SCHEMA_TYPE_SIMPLE:
4980 		    if ((WXS_COMP_NAME(ret, xmlSchemaTypePtr) == name) &&
4981 			(WXS_COMP_TNS(ret, xmlSchemaTypePtr) ==
4982 			nsName))
4983 		    {
4984 			return(ret);
4985 		    }
4986 		    break;
4987 		case XML_SCHEMA_TYPE_GROUP:
4988 		    if ((WXS_COMP_NAME(ret,
4989 			    xmlSchemaModelGroupDefPtr) == name) &&
4990 			(WXS_COMP_TNS(ret,
4991 			    xmlSchemaModelGroupDefPtr) == nsName))
4992 		    {
4993 			return(ret);
4994 		    }
4995 		    break;
4996 		case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
4997 		    if ((WXS_COMP_NAME(ret,
4998 			    xmlSchemaAttributeGroupPtr) == name) &&
4999 			(WXS_COMP_TNS(ret,
5000 			    xmlSchemaAttributeGroupPtr) == nsName))
5001 		    {
5002 			return(ret);
5003 		    }
5004 		    break;
5005 		default:
5006 		    /* Should not be hit. */
5007 		    return(NULL);
5008 	    }
5009 	}
5010     }
5011 subschemas:
5012     /*
5013     * Process imported/included schemas.
5014     */
5015     if (bucket->relations != NULL) {
5016 	xmlSchemaSchemaRelationPtr rel = bucket->relations;
5017 
5018 	/*
5019 	* TODO: Marking the bucket will not avoid multiple searches
5020 	* in the same schema, but avoids at least circularity.
5021 	*/
5022 	bucket->flags |= XML_SCHEMA_BUCKET_MARKED;
5023 	do {
5024 	    if ((rel->bucket != NULL) &&
5025 		((rel->bucket->flags & XML_SCHEMA_BUCKET_MARKED) == 0)) {
5026 		ret = xmlSchemaFindRedefCompInGraph(rel->bucket,
5027 		    type, name, nsName);
5028 		if (ret != NULL)
5029 		    return(ret);
5030 	    }
5031 	    rel = rel->next;
5032 	} while (rel != NULL);
5033 	 bucket->flags ^= XML_SCHEMA_BUCKET_MARKED;
5034     }
5035     return(NULL);
5036 }
5037 
5038 /**
5039  * xmlSchemaAddNotation:
5040  * @ctxt:  a schema parser context
5041  * @schema:  the schema being built
5042  * @name:  the item name
5043  *
5044  * Add an XML schema annotation declaration
5045  * *WARNING* this interface is highly subject to change
5046  *
5047  * Returns the new structure or NULL in case of error
5048  */
5049 static xmlSchemaNotationPtr
xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node ATTRIBUTE_UNUSED)5050 xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5051                      const xmlChar *name, const xmlChar *nsName,
5052 		     xmlNodePtr node ATTRIBUTE_UNUSED)
5053 {
5054     xmlSchemaNotationPtr ret = NULL;
5055 
5056     if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5057         return (NULL);
5058 
5059     ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
5060     if (ret == NULL) {
5061         xmlSchemaPErrMemory(ctxt);
5062         return (NULL);
5063     }
5064     memset(ret, 0, sizeof(xmlSchemaNotation));
5065     ret->type = XML_SCHEMA_TYPE_NOTATION;
5066     ret->name = name;
5067     ret->targetNamespace = nsName;
5068     /* TODO: do we need the node to be set?
5069     * ret->node = node;*/
5070     WXS_ADD_GLOBAL(ctxt, ret);
5071     return (ret);
5072 }
5073 
5074 /**
5075  * xmlSchemaAddAttribute:
5076  * @ctxt:  a schema parser context
5077  * @schema:  the schema being built
5078  * @name:  the item name
5079  * @namespace:  the namespace
5080  *
5081  * Add an XML schema Attribute declaration
5082  * *WARNING* this interface is highly subject to change
5083  *
5084  * Returns the new structure or NULL in case of error
5085  */
5086 static xmlSchemaAttributePtr
xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node,int topLevel)5087 xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5088                       const xmlChar * name, const xmlChar * nsName,
5089 		      xmlNodePtr node, int topLevel)
5090 {
5091     xmlSchemaAttributePtr ret = NULL;
5092 
5093     if ((ctxt == NULL) || (schema == NULL))
5094         return (NULL);
5095 
5096     ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
5097     if (ret == NULL) {
5098         xmlSchemaPErrMemory(ctxt);
5099         return (NULL);
5100     }
5101     memset(ret, 0, sizeof(xmlSchemaAttribute));
5102     ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
5103     ret->node = node;
5104     ret->name = name;
5105     ret->targetNamespace = nsName;
5106 
5107     if (topLevel)
5108 	WXS_ADD_GLOBAL(ctxt, ret);
5109     else
5110 	WXS_ADD_LOCAL(ctxt, ret);
5111     WXS_ADD_PENDING(ctxt, ret);
5112     return (ret);
5113 }
5114 
5115 /**
5116  * xmlSchemaAddAttributeUse:
5117  * @ctxt:  a schema parser context
5118  * @schema:  the schema being built
5119  * @name:  the item name
5120  * @namespace:  the namespace
5121  *
5122  * Add an XML schema Attribute declaration
5123  * *WARNING* this interface is highly subject to change
5124  *
5125  * Returns the new structure or NULL in case of error
5126  */
5127 static xmlSchemaAttributeUsePtr
xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt,xmlNodePtr node)5128 xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt,
5129 			 xmlNodePtr node)
5130 {
5131     xmlSchemaAttributeUsePtr ret = NULL;
5132 
5133     if (pctxt == NULL)
5134         return (NULL);
5135 
5136     ret = (xmlSchemaAttributeUsePtr) xmlMalloc(sizeof(xmlSchemaAttributeUse));
5137     if (ret == NULL) {
5138         xmlSchemaPErrMemory(pctxt);
5139         return (NULL);
5140     }
5141     memset(ret, 0, sizeof(xmlSchemaAttributeUse));
5142     ret->type = XML_SCHEMA_TYPE_ATTRIBUTE_USE;
5143     ret->node = node;
5144 
5145     WXS_ADD_LOCAL(pctxt, ret);
5146     return (ret);
5147 }
5148 
5149 /*
5150 * xmlSchemaAddRedef:
5151 *
5152 * Adds a redefinition information. This is used at a later stage to:
5153 * resolve references to the redefined components and to check constraints.
5154 */
5155 static xmlSchemaRedefPtr
xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBucketPtr targetBucket,void * item,const xmlChar * refName,const xmlChar * refTargetNs)5156 xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt,
5157 		  xmlSchemaBucketPtr targetBucket,
5158 		  void *item,
5159 		  const xmlChar *refName,
5160 		  const xmlChar *refTargetNs)
5161 {
5162     xmlSchemaRedefPtr ret;
5163 
5164     ret = (xmlSchemaRedefPtr)
5165 	xmlMalloc(sizeof(xmlSchemaRedef));
5166     if (ret == NULL) {
5167 	xmlSchemaPErrMemory(pctxt);
5168 	return (NULL);
5169     }
5170     memset(ret, 0, sizeof(xmlSchemaRedef));
5171     ret->item = item;
5172     ret->targetBucket = targetBucket;
5173     ret->refName = refName;
5174     ret->refTargetNs = refTargetNs;
5175     if (WXS_CONSTRUCTOR(pctxt)->redefs == NULL)
5176 	WXS_CONSTRUCTOR(pctxt)->redefs = ret;
5177     else
5178 	WXS_CONSTRUCTOR(pctxt)->lastRedef->next = ret;
5179     WXS_CONSTRUCTOR(pctxt)->lastRedef = ret;
5180 
5181     return (ret);
5182 }
5183 
5184 /**
5185  * xmlSchemaAddAttributeGroupDefinition:
5186  * @ctxt:  a schema parser context
5187  * @schema:  the schema being built
5188  * @name:  the item name
5189  * @nsName:  the target namespace
5190  * @node: the corresponding node
5191  *
5192  * Add an XML schema Attribute Group definition.
5193  *
5194  * Returns the new structure or NULL in case of error
5195  */
5196 static xmlSchemaAttributeGroupPtr
xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema ATTRIBUTE_UNUSED,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node)5197 xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
5198                            xmlSchemaPtr schema ATTRIBUTE_UNUSED,
5199 			   const xmlChar *name,
5200 			   const xmlChar *nsName,
5201 			   xmlNodePtr node)
5202 {
5203     xmlSchemaAttributeGroupPtr ret = NULL;
5204 
5205     if ((pctxt == NULL) || (name == NULL))
5206         return (NULL);
5207 
5208     ret = (xmlSchemaAttributeGroupPtr)
5209         xmlMalloc(sizeof(xmlSchemaAttributeGroup));
5210     if (ret == NULL) {
5211 	xmlSchemaPErrMemory(pctxt);
5212 	return (NULL);
5213     }
5214     memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
5215     ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5216     ret->name = name;
5217     ret->targetNamespace = nsName;
5218     ret->node = node;
5219 
5220     /* TODO: Remove the flag. */
5221     ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5222     if (pctxt->isRedefine) {
5223 	pctxt->redef = xmlSchemaAddRedef(pctxt, pctxt->redefined,
5224 	    ret, name, nsName);
5225 	if (pctxt->redef == NULL) {
5226 	    xmlFree(ret);
5227 	    return(NULL);
5228 	}
5229 	pctxt->redefCounter = 0;
5230     }
5231     WXS_ADD_GLOBAL(pctxt, ret);
5232     WXS_ADD_PENDING(pctxt, ret);
5233     return (ret);
5234 }
5235 
5236 /**
5237  * xmlSchemaAddElement:
5238  * @ctxt:  a schema parser context
5239  * @schema:  the schema being built
5240  * @name:  the type name
5241  * @namespace:  the type namespace
5242  *
5243  * Add an XML schema Element declaration
5244  * *WARNING* this interface is highly subject to change
5245  *
5246  * Returns the new structure or NULL in case of error
5247  */
5248 static xmlSchemaElementPtr
xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node,int topLevel)5249 xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt,
5250                     const xmlChar * name, const xmlChar * nsName,
5251 		    xmlNodePtr node, int topLevel)
5252 {
5253     xmlSchemaElementPtr ret = NULL;
5254 
5255     if ((ctxt == NULL) || (name == NULL))
5256         return (NULL);
5257 
5258     ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
5259     if (ret == NULL) {
5260         xmlSchemaPErrMemory(ctxt);
5261         return (NULL);
5262     }
5263     memset(ret, 0, sizeof(xmlSchemaElement));
5264     ret->type = XML_SCHEMA_TYPE_ELEMENT;
5265     ret->name = name;
5266     ret->targetNamespace = nsName;
5267     ret->node = node;
5268 
5269     if (topLevel)
5270 	WXS_ADD_GLOBAL(ctxt, ret);
5271     else
5272 	WXS_ADD_LOCAL(ctxt, ret);
5273     WXS_ADD_PENDING(ctxt, ret);
5274     return (ret);
5275 }
5276 
5277 /**
5278  * xmlSchemaAddType:
5279  * @ctxt:  a schema parser context
5280  * @schema:  the schema being built
5281  * @name:  the item name
5282  * @namespace:  the namespace
5283  *
5284  * Add an XML schema item
5285  * *WARNING* this interface is highly subject to change
5286  *
5287  * Returns the new structure or NULL in case of error
5288  */
5289 static xmlSchemaTypePtr
xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaTypeType type,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node,int topLevel)5290 xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5291 		 xmlSchemaTypeType type,
5292                  const xmlChar * name, const xmlChar * nsName,
5293 		 xmlNodePtr node, int topLevel)
5294 {
5295     xmlSchemaTypePtr ret = NULL;
5296 
5297     if ((ctxt == NULL) || (schema == NULL))
5298         return (NULL);
5299 
5300     ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
5301     if (ret == NULL) {
5302         xmlSchemaPErrMemory(ctxt);
5303         return (NULL);
5304     }
5305     memset(ret, 0, sizeof(xmlSchemaType));
5306     ret->type = type;
5307     ret->name = name;
5308     ret->targetNamespace = nsName;
5309     ret->node = node;
5310     if (topLevel) {
5311 	if (ctxt->isRedefine) {
5312 	    ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5313 		ret, name, nsName);
5314 	    if (ctxt->redef == NULL) {
5315 		xmlFree(ret);
5316 		return(NULL);
5317 	    }
5318 	    ctxt->redefCounter = 0;
5319 	}
5320 	WXS_ADD_GLOBAL(ctxt, ret);
5321     } else
5322 	WXS_ADD_LOCAL(ctxt, ret);
5323     WXS_ADD_PENDING(ctxt, ret);
5324     return (ret);
5325 }
5326 
5327 static xmlSchemaQNameRefPtr
xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypeType refType,const xmlChar * refName,const xmlChar * refNs)5328 xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt,
5329 		     xmlSchemaTypeType refType,
5330 		     const xmlChar *refName,
5331 		     const xmlChar *refNs)
5332 {
5333     xmlSchemaQNameRefPtr ret;
5334 
5335     ret = (xmlSchemaQNameRefPtr)
5336 	xmlMalloc(sizeof(xmlSchemaQNameRef));
5337     if (ret == NULL) {
5338 	xmlSchemaPErrMemory(pctxt);
5339 	return (NULL);
5340     }
5341     ret->node = NULL;
5342     ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
5343     ret->name = refName;
5344     ret->targetNamespace = refNs;
5345     ret->item = NULL;
5346     ret->itemType = refType;
5347     /*
5348     * Store the reference item in the schema.
5349     */
5350     WXS_ADD_LOCAL(pctxt, ret);
5351     return (ret);
5352 }
5353 
5354 static xmlSchemaAttributeUseProhibPtr
xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt)5355 xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt)
5356 {
5357     xmlSchemaAttributeUseProhibPtr ret;
5358 
5359     ret = (xmlSchemaAttributeUseProhibPtr)
5360 	xmlMalloc(sizeof(xmlSchemaAttributeUseProhib));
5361     if (ret == NULL) {
5362 	xmlSchemaPErrMemory(pctxt);
5363 	return (NULL);
5364     }
5365     memset(ret, 0, sizeof(xmlSchemaAttributeUseProhib));
5366     ret->type = XML_SCHEMA_EXTRA_ATTR_USE_PROHIB;
5367     WXS_ADD_LOCAL(pctxt, ret);
5368     return (ret);
5369 }
5370 
5371 
5372 /**
5373  * xmlSchemaAddModelGroup:
5374  * @ctxt:  a schema parser context
5375  * @schema:  the schema being built
5376  * @type: the "compositor" type of the model group
5377  * @node: the node in the schema doc
5378  *
5379  * Adds a schema model group
5380  * *WARNING* this interface is highly subject to change
5381  *
5382  * Returns the new structure or NULL in case of error
5383  */
5384 static xmlSchemaModelGroupPtr
xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaTypeType type,xmlNodePtr node)5385 xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt,
5386 		       xmlSchemaPtr schema,
5387 		       xmlSchemaTypeType type,
5388 		       xmlNodePtr node)
5389 {
5390     xmlSchemaModelGroupPtr ret = NULL;
5391 
5392     if ((ctxt == NULL) || (schema == NULL))
5393         return (NULL);
5394 
5395     ret = (xmlSchemaModelGroupPtr)
5396 	xmlMalloc(sizeof(xmlSchemaModelGroup));
5397     if (ret == NULL) {
5398 	xmlSchemaPErrMemory(ctxt);
5399 	return (NULL);
5400     }
5401     memset(ret, 0, sizeof(xmlSchemaModelGroup));
5402     ret->type = type;
5403     ret->node = node;
5404     WXS_ADD_LOCAL(ctxt, ret);
5405     if ((type == XML_SCHEMA_TYPE_SEQUENCE) ||
5406 	(type == XML_SCHEMA_TYPE_CHOICE))
5407 	WXS_ADD_PENDING(ctxt, ret);
5408     return (ret);
5409 }
5410 
5411 
5412 /**
5413  * xmlSchemaAddParticle:
5414  * @ctxt:  a schema parser context
5415  * @schema:  the schema being built
5416  * @node: the corresponding node in the schema doc
5417  * @min: the minOccurs
5418  * @max: the maxOccurs
5419  *
5420  * Adds an XML schema particle component.
5421  * *WARNING* this interface is highly subject to change
5422  *
5423  * Returns the new structure or NULL in case of error
5424  */
5425 static xmlSchemaParticlePtr
xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int min,int max)5426 xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt,
5427 		     xmlNodePtr node, int min, int max)
5428 {
5429     xmlSchemaParticlePtr ret = NULL;
5430     if (ctxt == NULL)
5431         return (NULL);
5432 
5433     ret = (xmlSchemaParticlePtr)
5434 	xmlMalloc(sizeof(xmlSchemaParticle));
5435     if (ret == NULL) {
5436 	xmlSchemaPErrMemory(ctxt);
5437 	return (NULL);
5438     }
5439     ret->type = XML_SCHEMA_TYPE_PARTICLE;
5440     ret->annot = NULL;
5441     ret->node = node;
5442     ret->minOccurs = min;
5443     ret->maxOccurs = max;
5444     ret->next = NULL;
5445     ret->children = NULL;
5446 
5447     WXS_ADD_LOCAL(ctxt, ret);
5448     /*
5449     * Note that addition to pending components will be done locally
5450     * to the specific parsing function, since the most particles
5451     * need not to be fixed up (i.e. the reference to be resolved).
5452     * REMOVED: WXS_ADD_PENDING(ctxt, ret);
5453     */
5454     return (ret);
5455 }
5456 
5457 /**
5458  * xmlSchemaAddModelGroupDefinition:
5459  * @ctxt:  a schema validation context
5460  * @schema:  the schema being built
5461  * @name:  the group name
5462  *
5463  * Add an XML schema Group definition
5464  *
5465  * Returns the new structure or NULL in case of error
5466  */
5467 static xmlSchemaModelGroupDefPtr
xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName,xmlNodePtr node)5468 xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
5469 				 xmlSchemaPtr schema,
5470 				 const xmlChar *name,
5471 				 const xmlChar *nsName,
5472 				 xmlNodePtr node)
5473 {
5474     xmlSchemaModelGroupDefPtr ret = NULL;
5475 
5476     if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5477         return (NULL);
5478 
5479     ret = (xmlSchemaModelGroupDefPtr)
5480 	xmlMalloc(sizeof(xmlSchemaModelGroupDef));
5481     if (ret == NULL) {
5482         xmlSchemaPErrMemory(ctxt);
5483         return (NULL);
5484     }
5485     memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
5486     ret->name = name;
5487     ret->type = XML_SCHEMA_TYPE_GROUP;
5488     ret->node = node;
5489     ret->targetNamespace = nsName;
5490 
5491     if (ctxt->isRedefine) {
5492 	ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5493 	    ret, name, nsName);
5494 	if (ctxt->redef == NULL) {
5495 	    xmlFree(ret);
5496 	    return(NULL);
5497 	}
5498 	ctxt->redefCounter = 0;
5499     }
5500     WXS_ADD_GLOBAL(ctxt, ret);
5501     WXS_ADD_PENDING(ctxt, ret);
5502     return (ret);
5503 }
5504 
5505 /**
5506  * xmlSchemaNewWildcardNs:
5507  * @ctxt:  a schema validation context
5508  *
5509  * Creates a new wildcard namespace constraint.
5510  *
5511  * Returns the new structure or NULL in case of error
5512  */
5513 static xmlSchemaWildcardNsPtr
xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)5514 xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
5515 {
5516     xmlSchemaWildcardNsPtr ret;
5517 
5518     ret = (xmlSchemaWildcardNsPtr)
5519 	xmlMalloc(sizeof(xmlSchemaWildcardNs));
5520     if (ret == NULL) {
5521 	xmlSchemaPErrMemory(ctxt);
5522 	return (NULL);
5523     }
5524     ret->value = NULL;
5525     ret->next = NULL;
5526     return (ret);
5527 }
5528 
5529 static xmlSchemaIDCPtr
xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,const xmlChar * name,const xmlChar * nsName,int category,xmlNodePtr node)5530 xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5531                   const xmlChar *name, const xmlChar *nsName,
5532 		  int category, xmlNodePtr node)
5533 {
5534     xmlSchemaIDCPtr ret = NULL;
5535 
5536     if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5537         return (NULL);
5538 
5539     ret = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
5540     if (ret == NULL) {
5541         xmlSchemaPErrMemory(ctxt);
5542         return (NULL);
5543     }
5544     memset(ret, 0, sizeof(xmlSchemaIDC));
5545     /* The target namespace of the parent element declaration. */
5546     ret->targetNamespace = nsName;
5547     ret->name = name;
5548     ret->type = category;
5549     ret->node = node;
5550 
5551     WXS_ADD_GLOBAL(ctxt, ret);
5552     /*
5553     * Only keyrefs need to be fixup up.
5554     */
5555     if (category == XML_SCHEMA_TYPE_IDC_KEYREF)
5556 	WXS_ADD_PENDING(ctxt, ret);
5557     return (ret);
5558 }
5559 
5560 /**
5561  * xmlSchemaAddWildcard:
5562  * @ctxt:  a schema validation context
5563  * @schema: a schema
5564  *
5565  * Adds a wildcard.
5566  * It corresponds to a xsd:anyAttribute and xsd:any.
5567  *
5568  * Returns the new structure or NULL in case of error
5569  */
5570 static xmlSchemaWildcardPtr
xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaTypeType type,xmlNodePtr node)5571 xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5572 		     xmlSchemaTypeType type, xmlNodePtr node)
5573 {
5574     xmlSchemaWildcardPtr ret = NULL;
5575 
5576     if ((ctxt == NULL) || (schema == NULL))
5577         return (NULL);
5578 
5579     ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
5580     if (ret == NULL) {
5581         xmlSchemaPErrMemory(ctxt);
5582         return (NULL);
5583     }
5584     memset(ret, 0, sizeof(xmlSchemaWildcard));
5585     ret->type = type;
5586     ret->node = node;
5587     WXS_ADD_LOCAL(ctxt, ret);
5588     return (ret);
5589 }
5590 
5591 static void
xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group)5592 xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group)
5593 {
5594     if (group == NULL)
5595 	return;
5596     if (group->members != NULL)
5597 	xmlSchemaItemListFree(group->members);
5598     xmlFree(group);
5599 }
5600 
5601 static void
xmlSchemaSubstGroupFreeEntry(void * group,const xmlChar * name ATTRIBUTE_UNUSED)5602 xmlSchemaSubstGroupFreeEntry(void *group, const xmlChar *name ATTRIBUTE_UNUSED)
5603 {
5604     xmlSchemaSubstGroupFree((xmlSchemaSubstGroupPtr) group);
5605 }
5606 
5607 static xmlSchemaSubstGroupPtr
xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt,xmlSchemaElementPtr head)5608 xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt,
5609 		       xmlSchemaElementPtr head)
5610 {
5611     xmlSchemaSubstGroupPtr ret;
5612 
5613     /* Init subst group hash. */
5614     if (WXS_SUBST_GROUPS(pctxt) == NULL) {
5615 	WXS_SUBST_GROUPS(pctxt) = xmlHashCreateDict(10, pctxt->dict);
5616 	if (WXS_SUBST_GROUPS(pctxt) == NULL)
5617 	    return(NULL);
5618     }
5619     /* Create a new substitution group. */
5620     ret = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
5621     if (ret == NULL) {
5622 	xmlSchemaPErrMemory(NULL);
5623 	return(NULL);
5624     }
5625     memset(ret, 0, sizeof(xmlSchemaSubstGroup));
5626     ret->head = head;
5627     /* Create list of members. */
5628     ret->members = xmlSchemaItemListCreate();
5629     if (ret->members == NULL) {
5630 	xmlSchemaSubstGroupFree(ret);
5631 	return(NULL);
5632     }
5633     /* Add subst group to hash. */
5634     if (xmlHashAddEntry2(WXS_SUBST_GROUPS(pctxt),
5635 	head->name, head->targetNamespace, ret) != 0) {
5636 	PERROR_INT("xmlSchemaSubstGroupAdd",
5637 	    "failed to add a new substitution container");
5638 	xmlSchemaSubstGroupFree(ret);
5639 	return(NULL);
5640     }
5641     return(ret);
5642 }
5643 
5644 static xmlSchemaSubstGroupPtr
xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt,xmlSchemaElementPtr head)5645 xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt,
5646 		       xmlSchemaElementPtr head)
5647 {
5648     if (WXS_SUBST_GROUPS(pctxt) == NULL)
5649 	return(NULL);
5650     return(xmlHashLookup2(WXS_SUBST_GROUPS(pctxt),
5651 	head->name, head->targetNamespace));
5652 
5653 }
5654 
5655 /**
5656  * xmlSchemaAddElementSubstitutionMember:
5657  * @pctxt:  a schema parser context
5658  * @head:  the head of the substitution group
5659  * @member: the new member of the substitution group
5660  *
5661  * Allocate a new annotation structure.
5662  *
5663  * Returns the newly allocated structure or NULL in case or error
5664  */
5665 static int
xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,xmlSchemaElementPtr head,xmlSchemaElementPtr member)5666 xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
5667 				      xmlSchemaElementPtr head,
5668 				      xmlSchemaElementPtr member)
5669 {
5670     xmlSchemaSubstGroupPtr substGroup = NULL;
5671 
5672     if ((pctxt == NULL) || (head == NULL) || (member == NULL))
5673 	return (-1);
5674 
5675     substGroup = xmlSchemaSubstGroupGet(pctxt, head);
5676     if (substGroup == NULL)
5677 	substGroup = xmlSchemaSubstGroupAdd(pctxt, head);
5678     if (substGroup == NULL)
5679 	return(-1);
5680     if (xmlSchemaItemListAdd(substGroup->members, member) == -1)
5681 	return(-1);
5682     return(0);
5683 }
5684 
5685 /************************************************************************
5686  *									*
5687  *		Utilities for parsing					*
5688  *									*
5689  ************************************************************************/
5690 
5691 /**
5692  * xmlSchemaPValAttrNodeQNameValue:
5693  * @ctxt:  a schema parser context
5694  * @schema: the schema context
5695  * @ownerItem: the parent as a schema object
5696  * @value:  the QName value
5697  * @uri:  the resulting namespace URI if found
5698  * @local: the resulting local part if found, the attribute value otherwise
5699  *
5700  * Extracts the local name and the URI of a QName value and validates it.
5701  * This one is intended to be used on attribute values that
5702  * should resolve to schema components.
5703  *
5704  * Returns 0, in case the QName is valid, a positive error code
5705  * if not valid and -1 if an internal error occurs.
5706  */
5707 static int
xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,const xmlChar * value,const xmlChar ** uri,const xmlChar ** local)5708 xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
5709 				       xmlSchemaPtr schema,
5710 				       xmlSchemaBasicItemPtr ownerItem,
5711 				       xmlAttrPtr attr,
5712 				       const xmlChar *value,
5713 				       const xmlChar **uri,
5714 				       const xmlChar **local)
5715 {
5716     const xmlChar *pref;
5717     xmlNsPtr ns;
5718     int len, ret;
5719 
5720     *uri = NULL;
5721     *local = NULL;
5722     ret = xmlValidateQName(value, 1);
5723     if (ret > 0) {
5724 	xmlSchemaPSimpleTypeErr(ctxt,
5725 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5726 	    ownerItem, (xmlNodePtr) attr,
5727 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
5728 	    NULL, value, NULL, NULL, NULL);
5729 	*local = value;
5730 	return (ctxt->err);
5731     } else if (ret < 0)
5732 	return (-1);
5733 
5734     if (!strchr((char *) value, ':')) {
5735 	ns = xmlSearchNs(attr->doc, attr->parent, NULL);
5736 	if (ns && ns->href && ns->href[0])
5737 	    *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5738 	else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
5739 	    /* TODO: move XML_SCHEMAS_INCLUDING_CONVERT_NS to the
5740 	    * parser context. */
5741 	    /*
5742 	    * This one takes care of included schemas with no
5743 	    * target namespace.
5744 	    */
5745 	    *uri = ctxt->targetNamespace;
5746 	}
5747 	*local = xmlDictLookup(ctxt->dict, value, -1);
5748 	return (0);
5749     }
5750     /*
5751     * At this point xmlSplitQName3 has to return a local name.
5752     */
5753     *local = xmlSplitQName3(value, &len);
5754     *local = xmlDictLookup(ctxt->dict, *local, -1);
5755     pref = xmlDictLookup(ctxt->dict, value, len);
5756     ns = xmlSearchNs(attr->doc, attr->parent, pref);
5757     if (ns == NULL) {
5758 	xmlSchemaPSimpleTypeErr(ctxt,
5759 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5760 	    ownerItem, (xmlNodePtr) attr,
5761 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
5762 	    "The value '%s' of simple type 'xs:QName' has no "
5763 	    "corresponding namespace declaration in scope", value, NULL);
5764 	return (ctxt->err);
5765     } else {
5766         *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5767     }
5768     return (0);
5769 }
5770 
5771 /**
5772  * xmlSchemaPValAttrNodeQName:
5773  * @ctxt:  a schema parser context
5774  * @schema: the schema context
5775  * @ownerItem: the owner as a schema object
5776  * @attr:  the attribute node
5777  * @uri:  the resulting namespace URI if found
5778  * @local: the resulting local part if found, the attribute value otherwise
5779  *
5780  * Extracts and validates the QName of an attribute value.
5781  * This one is intended to be used on attribute values that
5782  * should resolve to schema components.
5783  *
5784  * Returns 0, in case the QName is valid, a positive error code
5785  * if not valid and -1 if an internal error occurs.
5786  */
5787 static int
xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,const xmlChar ** uri,const xmlChar ** local)5788 xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
5789 				       xmlSchemaPtr schema,
5790 				       xmlSchemaBasicItemPtr ownerItem,
5791 				       xmlAttrPtr attr,
5792 				       const xmlChar **uri,
5793 				       const xmlChar **local)
5794 {
5795     const xmlChar *value;
5796 
5797     value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5798     return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
5799 	ownerItem, attr, value, uri, local));
5800 }
5801 
5802 /**
5803  * xmlSchemaPValAttrQName:
5804  * @ctxt:  a schema parser context
5805  * @schema: the schema context
5806  * @ownerItem: the owner as a schema object
5807  * @ownerElem:  the parent node of the attribute
5808  * @name:  the name of the attribute
5809  * @uri:  the resulting namespace URI if found
5810  * @local: the resulting local part if found, the attribute value otherwise
5811  *
5812  * Extracts and validates the QName of an attribute value.
5813  *
5814  * Returns 0, in case the QName is valid, a positive error code
5815  * if not valid and -1 if an internal error occurs.
5816  */
5817 static int
xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlSchemaBasicItemPtr ownerItem,xmlNodePtr ownerElem,const char * name,const xmlChar ** uri,const xmlChar ** local)5818 xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5819 				   xmlSchemaPtr schema,
5820 				   xmlSchemaBasicItemPtr ownerItem,
5821 				   xmlNodePtr ownerElem,
5822 				   const char *name,
5823 				   const xmlChar **uri,
5824 				   const xmlChar **local)
5825 {
5826     xmlAttrPtr attr;
5827 
5828     attr = xmlSchemaGetPropNode(ownerElem, name);
5829     if (attr == NULL) {
5830 	*local = NULL;
5831 	*uri = NULL;
5832 	return (0);
5833     }
5834     return (xmlSchemaPValAttrNodeQName(ctxt, schema,
5835 	ownerItem, attr, uri, local));
5836 }
5837 
5838 /**
5839  * xmlSchemaPValAttrID:
5840  * @ctxt:  a schema parser context
5841  *
5842  * Extracts and validates the ID of an attribute value.
5843  *
5844  * Returns 0, in case the ID is valid, a positive error code
5845  * if not valid and -1 if an internal error occurs.
5846  */
5847 static int
xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt,xmlAttrPtr attr)5848 xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr)
5849 {
5850     int ret;
5851     const xmlChar *value;
5852 
5853     if (attr == NULL)
5854 	return(0);
5855     value = xmlSchemaGetNodeContentNoDict((xmlNodePtr) attr);
5856     ret = xmlValidateNCName(value, 1);
5857     if (ret == 0) {
5858 	/*
5859 	* NOTE: the IDness might have already be declared in the DTD
5860 	*/
5861 	if (attr->atype != XML_ATTRIBUTE_ID) {
5862 	    xmlChar *strip;
5863             int res;
5864 
5865 	    /*
5866 	    * TODO: Use xmlSchemaStrip here; it's not exported at this
5867 	    * moment.
5868 	    */
5869 	    strip = xmlSchemaCollapseString(value);
5870 	    if (strip != NULL) {
5871 		xmlFree((xmlChar *) value);
5872 		value = strip;
5873 	    }
5874 	    res = xmlAddIDSafe(attr, value);
5875             if (res < 0) {
5876                 xmlSchemaPErrMemory(ctxt);
5877 	    } else if (res == 0) {
5878 		ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
5879 		xmlSchemaPSimpleTypeErr(ctxt,
5880 		    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5881 		    NULL, (xmlNodePtr) attr,
5882 		    xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5883 		    NULL, NULL, "Duplicate value '%s' of simple "
5884 		    "type 'xs:ID'", value, NULL);
5885 	    }
5886 	}
5887     } else if (ret > 0) {
5888 	ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
5889 	xmlSchemaPSimpleTypeErr(ctxt,
5890 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5891 	    NULL, (xmlNodePtr) attr,
5892 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5893 	    NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
5894 	    "not a valid 'xs:NCName'",
5895 	    value, NULL);
5896     }
5897     if (value != NULL)
5898 	xmlFree((xmlChar *)value);
5899 
5900     return (ret);
5901 }
5902 
5903 static int
xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr ownerElem,const xmlChar * name)5904 xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
5905 		    xmlNodePtr ownerElem,
5906 		    const xmlChar *name)
5907 {
5908     xmlAttrPtr attr;
5909 
5910     attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
5911     if (attr == NULL)
5912 	return(0);
5913     return(xmlSchemaPValAttrNodeID(ctxt, attr));
5914 
5915 }
5916 
5917 /**
5918  * xmlGetMaxOccurs:
5919  * @ctxt:  a schema validation context
5920  * @node:  a subtree containing XML Schema information
5921  *
5922  * Get the maxOccurs property
5923  *
5924  * Returns the default if not found, or the value
5925  */
5926 static int
xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int min,int max,int def,const char * expected)5927 xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
5928 		int min, int max, int def, const char *expected)
5929 {
5930     const xmlChar *val, *cur;
5931     int ret = 0;
5932     xmlAttrPtr attr;
5933 
5934     attr = xmlSchemaGetPropNode(node, "maxOccurs");
5935     if (attr == NULL)
5936 	return (def);
5937     val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5938     if (val == NULL)
5939         return (def);
5940 
5941     if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
5942 	if (max != UNBOUNDED) {
5943 	    xmlSchemaPSimpleTypeErr(ctxt,
5944 		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5945 		/* XML_SCHEMAP_INVALID_MINOCCURS, */
5946 		NULL, (xmlNodePtr) attr, NULL, expected,
5947 		val, NULL, NULL, NULL);
5948 	    return (def);
5949 	} else
5950 	    return (UNBOUNDED);  /* encoding it with -1 might be another option */
5951     }
5952 
5953     cur = val;
5954     while (IS_BLANK_CH(*cur))
5955         cur++;
5956     if (*cur == 0) {
5957         xmlSchemaPSimpleTypeErr(ctxt,
5958 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5959 	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
5960 	    NULL, (xmlNodePtr) attr, NULL, expected,
5961 	    val, NULL, NULL, NULL);
5962 	return (def);
5963     }
5964     while ((*cur >= '0') && (*cur <= '9')) {
5965         if (ret > INT_MAX / 10) {
5966             ret = INT_MAX;
5967         } else {
5968             int digit = *cur - '0';
5969             ret *= 10;
5970             if (ret > INT_MAX - digit)
5971                 ret = INT_MAX;
5972             else
5973                 ret += digit;
5974         }
5975         cur++;
5976     }
5977     while (IS_BLANK_CH(*cur))
5978         cur++;
5979     /*
5980     * TODO: Restrict the maximal value to Integer.
5981     */
5982     if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
5983 	xmlSchemaPSimpleTypeErr(ctxt,
5984 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5985 	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
5986 	    NULL, (xmlNodePtr) attr, NULL, expected,
5987 	    val, NULL, NULL, NULL);
5988         return (def);
5989     }
5990     return (ret);
5991 }
5992 
5993 /**
5994  * xmlGetMinOccurs:
5995  * @ctxt:  a schema validation context
5996  * @node:  a subtree containing XML Schema information
5997  *
5998  * Get the minOccurs property
5999  *
6000  * Returns the default if not found, or the value
6001  */
6002 static int
xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int min,int max,int def,const char * expected)6003 xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
6004 		int min, int max, int def, const char *expected)
6005 {
6006     const xmlChar *val, *cur;
6007     int ret = 0;
6008     xmlAttrPtr attr;
6009 
6010     attr = xmlSchemaGetPropNode(node, "minOccurs");
6011     if (attr == NULL)
6012 	return (def);
6013     val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6014     if (val == NULL)
6015 	return (def);
6016     cur = val;
6017     while (IS_BLANK_CH(*cur))
6018         cur++;
6019     if (*cur == 0) {
6020         xmlSchemaPSimpleTypeErr(ctxt,
6021 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6022 	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
6023 	    NULL, (xmlNodePtr) attr, NULL, expected,
6024 	    val, NULL, NULL, NULL);
6025         return (def);
6026     }
6027     while ((*cur >= '0') && (*cur <= '9')) {
6028         if (ret > INT_MAX / 10) {
6029             ret = INT_MAX;
6030         } else {
6031             int digit = *cur - '0';
6032             ret *= 10;
6033             if (ret > INT_MAX - digit)
6034                 ret = INT_MAX;
6035             else
6036                 ret += digit;
6037         }
6038         cur++;
6039     }
6040     while (IS_BLANK_CH(*cur))
6041         cur++;
6042     /*
6043     * TODO: Restrict the maximal value to Integer.
6044     */
6045     if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
6046 	xmlSchemaPSimpleTypeErr(ctxt,
6047 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6048 	    /* XML_SCHEMAP_INVALID_MINOCCURS, */
6049 	    NULL, (xmlNodePtr) attr, NULL, expected,
6050 	    val, NULL, NULL, NULL);
6051         return (def);
6052     }
6053     return (ret);
6054 }
6055 
6056 /**
6057  * xmlSchemaPGetBoolNodeValue:
6058  * @ctxt:  a schema validation context
6059  * @ownerItem:  the owner as a schema item
6060  * @node: the node holding the value
6061  *
6062  * Converts a boolean string value into 1 or 0.
6063  *
6064  * Returns 0 or 1.
6065  */
6066 static int
xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,xmlSchemaBasicItemPtr ownerItem,xmlNodePtr node)6067 xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
6068 			   xmlSchemaBasicItemPtr ownerItem,
6069 			   xmlNodePtr node)
6070 {
6071     xmlChar *value = NULL;
6072     int res = 0;
6073 
6074     value = xmlNodeGetContent(node);
6075     /*
6076     * 3.2.2.1 Lexical representation
6077     * An instance of a datatype that is defined as `boolean`
6078     * can have the following legal literals {true, false, 1, 0}.
6079     */
6080     if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
6081         res = 1;
6082     else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
6083         res = 0;
6084     else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
6085 	res = 1;
6086     else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
6087         res = 0;
6088     else {
6089         xmlSchemaPSimpleTypeErr(ctxt,
6090 	    XML_SCHEMAP_INVALID_BOOLEAN,
6091 	    ownerItem, node,
6092 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6093 	    NULL, BAD_CAST value,
6094 	    NULL, NULL, NULL);
6095     }
6096     if (value != NULL)
6097 	xmlFree(value);
6098     return (res);
6099 }
6100 
6101 /**
6102  * xmlGetBooleanProp:
6103  * @ctxt:  a schema validation context
6104  * @node:  a subtree containing XML Schema information
6105  * @name:  the attribute name
6106  * @def:  the default value
6107  *
6108  * Evaluate if a boolean property is set
6109  *
6110  * Returns the default if not found, 0 if found to be false,
6111  * 1 if found to be true
6112  */
6113 static int
xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,const char * name,int def)6114 xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
6115 		  xmlNodePtr node,
6116                   const char *name, int def)
6117 {
6118     const xmlChar *val;
6119 
6120     val = xmlSchemaGetProp(ctxt, node, name);
6121     if (val == NULL)
6122         return (def);
6123     /*
6124     * 3.2.2.1 Lexical representation
6125     * An instance of a datatype that is defined as `boolean`
6126     * can have the following legal literals {true, false, 1, 0}.
6127     */
6128     if (xmlStrEqual(val, BAD_CAST "true"))
6129         def = 1;
6130     else if (xmlStrEqual(val, BAD_CAST "false"))
6131         def = 0;
6132     else if (xmlStrEqual(val, BAD_CAST "1"))
6133 	def = 1;
6134     else if (xmlStrEqual(val, BAD_CAST "0"))
6135         def = 0;
6136     else {
6137         xmlSchemaPSimpleTypeErr(ctxt,
6138 	    XML_SCHEMAP_INVALID_BOOLEAN,
6139 	    NULL,
6140 	    (xmlNodePtr) xmlSchemaGetPropNode(node, name),
6141 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6142 	    NULL, val, NULL, NULL, NULL);
6143     }
6144     return (def);
6145 }
6146 
6147 /************************************************************************
6148  *									*
6149  *		Schema extraction from an Infoset			*
6150  *									*
6151  ************************************************************************/
6152 static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
6153                                                  ctxt, xmlSchemaPtr schema,
6154                                                  xmlNodePtr node,
6155 						 int topLevel);
6156 static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
6157                                                   ctxt,
6158                                                   xmlSchemaPtr schema,
6159                                                   xmlNodePtr node,
6160 						  int topLevel);
6161 static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
6162                                                   ctxt,
6163                                                   xmlSchemaPtr schema,
6164                                                   xmlNodePtr node,
6165 						  xmlSchemaTypeType parentType);
6166 static xmlSchemaBasicItemPtr
6167 xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
6168 			     xmlSchemaPtr schema,
6169 			     xmlNodePtr node,
6170 			     xmlSchemaItemListPtr uses,
6171 			     int parentType);
6172 static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
6173                                            xmlSchemaPtr schema,
6174                                            xmlNodePtr node);
6175 static xmlSchemaWildcardPtr
6176 xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6177                            xmlSchemaPtr schema, xmlNodePtr node);
6178 
6179 /**
6180  * xmlSchemaPValAttrNodeValue:
6181  *
6182  * @pctxt:  a schema parser context
6183  * @ownerItem: the schema object owner if existent
6184  * @attr:  the schema attribute node being validated
6185  * @value: the value
6186  * @type: the built-in type to be validated against
6187  *
6188  * Validates a value against the given built-in type.
6189  * This one is intended to be used internally for validation
6190  * of schema attribute values during parsing of the schema.
6191  *
6192  * Returns 0 if the value is valid, a positive error code
6193  * number otherwise and -1 in case of an internal or API error.
6194  */
6195 static int
xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,const xmlChar * value,xmlSchemaTypePtr type)6196 xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
6197 			   xmlSchemaBasicItemPtr ownerItem,
6198 			   xmlAttrPtr attr,
6199 			   const xmlChar *value,
6200 			   xmlSchemaTypePtr type)
6201 {
6202 
6203     int ret = 0;
6204 
6205     /*
6206     * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
6207     * one is really meant to be used internally, so better not.
6208     */
6209     if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
6210 	return (-1);
6211     if (type->type != XML_SCHEMA_TYPE_BASIC) {
6212 	PERROR_INT("xmlSchemaPValAttrNodeValue",
6213 	    "the given type is not a built-in type");
6214 	return (-1);
6215     }
6216     switch (type->builtInType) {
6217 	case XML_SCHEMAS_NCNAME:
6218 	case XML_SCHEMAS_QNAME:
6219 	case XML_SCHEMAS_ANYURI:
6220 	case XML_SCHEMAS_TOKEN:
6221 	case XML_SCHEMAS_LANGUAGE:
6222 	    ret = xmlSchemaValPredefTypeNode(type, value, NULL,
6223 		(xmlNodePtr) attr);
6224 	    break;
6225 	default: {
6226 	    PERROR_INT("xmlSchemaPValAttrNodeValue",
6227 		"validation using the given type is not supported while "
6228 		"parsing a schema");
6229 	    return (-1);
6230 	}
6231     }
6232     /*
6233     * TODO: Should we use the S4S error codes instead?
6234     */
6235     if (ret < 0) {
6236 	PERROR_INT("xmlSchemaPValAttrNodeValue",
6237 	    "failed to validate a schema attribute value");
6238 	return (-1);
6239     } else if (ret > 0) {
6240 	if (WXS_IS_LIST(type))
6241 	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
6242 	else
6243 	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
6244 	xmlSchemaPSimpleTypeErr(pctxt,
6245 	    ret, ownerItem, (xmlNodePtr) attr,
6246 	    type, NULL, value, NULL, NULL, NULL);
6247     }
6248     return (ret);
6249 }
6250 
6251 /**
6252  * xmlSchemaPValAttrNode:
6253  *
6254  * @ctxt:  a schema parser context
6255  * @ownerItem: the schema object owner if existent
6256  * @attr:  the schema attribute node being validated
6257  * @type: the built-in type to be validated against
6258  * @value: the resulting value if any
6259  *
6260  * Extracts and validates a value against the given built-in type.
6261  * This one is intended to be used internally for validation
6262  * of schema attribute values during parsing of the schema.
6263  *
6264  * Returns 0 if the value is valid, a positive error code
6265  * number otherwise and -1 in case of an internal or API error.
6266  */
6267 static int
xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,xmlSchemaBasicItemPtr ownerItem,xmlAttrPtr attr,xmlSchemaTypePtr type,const xmlChar ** value)6268 xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
6269 			   xmlSchemaBasicItemPtr ownerItem,
6270 			   xmlAttrPtr attr,
6271 			   xmlSchemaTypePtr type,
6272 			   const xmlChar **value)
6273 {
6274     const xmlChar *val;
6275 
6276     if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
6277 	return (-1);
6278 
6279     val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6280     if (value != NULL)
6281 	*value = val;
6282 
6283     return (xmlSchemaPValAttrNodeValue(ctxt, ownerItem, attr,
6284 	val, type));
6285 }
6286 
6287 /**
6288  * xmlSchemaPValAttr:
6289  *
6290  * @ctxt:  a schema parser context
6291  * @node: the element node of the attribute
6292  * @ownerItem: the schema object owner if existent
6293  * @ownerElem: the owner element node
6294  * @name:  the name of the schema attribute node
6295  * @type: the built-in type to be validated against
6296  * @value: the resulting value if any
6297  *
6298  * Extracts and validates a value against the given built-in type.
6299  * This one is intended to be used internally for validation
6300  * of schema attribute values during parsing of the schema.
6301  *
6302  * Returns 0 if the value is valid, a positive error code
6303  * number otherwise and -1 in case of an internal or API error.
6304  */
6305 static int
xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,xmlSchemaBasicItemPtr ownerItem,xmlNodePtr ownerElem,const char * name,xmlSchemaTypePtr type,const xmlChar ** value)6306 xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
6307 		       xmlSchemaBasicItemPtr ownerItem,
6308 		       xmlNodePtr ownerElem,
6309 		       const char *name,
6310 		       xmlSchemaTypePtr type,
6311 		       const xmlChar **value)
6312 {
6313     xmlAttrPtr attr;
6314 
6315     if ((ctxt == NULL) || (type == NULL)) {
6316 	if (value != NULL)
6317 	    *value = NULL;
6318 	return (-1);
6319     }
6320     if (type->type != XML_SCHEMA_TYPE_BASIC) {
6321 	if (value != NULL)
6322 	    *value = NULL;
6323 	xmlSchemaPErr(ctxt, ownerElem,
6324 	    XML_SCHEMAP_INTERNAL,
6325 	    "Internal error: xmlSchemaPValAttr, the given "
6326 	    "type '%s' is not a built-in type.\n",
6327 	    type->name, NULL);
6328 	return (-1);
6329     }
6330     attr = xmlSchemaGetPropNode(ownerElem, name);
6331     if (attr == NULL) {
6332 	if (value != NULL)
6333 	    *value = NULL;
6334 	return (0);
6335     }
6336     return (xmlSchemaPValAttrNode(ctxt, ownerItem, attr,
6337 	type, value));
6338 }
6339 
6340 static int
xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema ATTRIBUTE_UNUSED,xmlNodePtr node,xmlAttrPtr attr,const xmlChar * namespaceName)6341 xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
6342 		  xmlSchemaPtr schema ATTRIBUTE_UNUSED,
6343 		  xmlNodePtr node,
6344 		  xmlAttrPtr attr,
6345 		  const xmlChar *namespaceName)
6346 {
6347     /* TODO: Pointer comparison instead? */
6348     if (xmlStrEqual(pctxt->targetNamespace, namespaceName))
6349 	return (0);
6350     if (xmlStrEqual(xmlSchemaNs, namespaceName))
6351 	return (0);
6352     /*
6353     * Check if the referenced namespace was <import>ed.
6354     */
6355     if (WXS_BUCKET(pctxt)->relations != NULL) {
6356 	xmlSchemaSchemaRelationPtr rel;
6357 
6358 	rel = WXS_BUCKET(pctxt)->relations;
6359 	do {
6360 	    if (WXS_IS_BUCKET_IMPMAIN(rel->type) &&
6361 		xmlStrEqual(namespaceName, rel->importNamespace))
6362 		return (0);
6363 	    rel = rel->next;
6364 	} while (rel != NULL);
6365     }
6366     /*
6367     * No matching <import>ed namespace found.
6368     */
6369     {
6370 	xmlNodePtr n = (attr != NULL) ? (xmlNodePtr) attr : node;
6371 
6372 	if (namespaceName == NULL)
6373 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
6374 		XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6375 		"References from this schema to components in no "
6376 		"namespace are not allowed, since not indicated by an "
6377 		"import statement", NULL, NULL);
6378 	else
6379 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
6380 		XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6381 		"References from this schema to components in the "
6382 		"namespace '%s' are not allowed, since not indicated by an "
6383 		"import statement", namespaceName, NULL);
6384     }
6385     return (XML_SCHEMAP_SRC_RESOLVE);
6386 }
6387 
6388 /**
6389  * xmlSchemaParseLocalAttributes:
6390  * @ctxt:  a schema validation context
6391  * @schema:  the schema being built
6392  * @node:  a subtree containing XML Schema information
6393  * @type:  the hosting type where the attributes will be anchored
6394  *
6395  * Parses attribute uses and attribute declarations and
6396  * attribute group references.
6397  */
6398 static int
xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr * child,xmlSchemaItemListPtr * list,int parentType,int * hasRefs)6399 xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6400                         xmlNodePtr *child, xmlSchemaItemListPtr *list,
6401 			int parentType, int *hasRefs)
6402 {
6403     void *item;
6404 
6405     while ((IS_SCHEMA((*child), "attribute")) ||
6406            (IS_SCHEMA((*child), "attributeGroup"))) {
6407         if (IS_SCHEMA((*child), "attribute")) {
6408 	    item = xmlSchemaParseLocalAttribute(ctxt, schema, *child,
6409 		*list, parentType);
6410         } else {
6411             item = xmlSchemaParseAttributeGroupRef(ctxt, schema, *child);
6412 	    if ((item != NULL) && (hasRefs != NULL))
6413 		*hasRefs = 1;
6414         }
6415 	if (item != NULL) {
6416 	    if (*list == NULL) {
6417 		/* TODO: Customize grow factor. */
6418 		*list = xmlSchemaItemListCreate();
6419 		if (*list == NULL)
6420 		    return(-1);
6421 	    }
6422 	    if (xmlSchemaItemListAddSize(*list, 2, item) == -1)
6423 		return(-1);
6424 	}
6425         *child = (*child)->next;
6426     }
6427     return (0);
6428 }
6429 
6430 /**
6431  * xmlSchemaParseAnnotation:
6432  * @ctxt:  a schema validation context
6433  * @schema:  the schema being built
6434  * @node:  a subtree containing XML Schema information
6435  *
6436  * parse a XML schema Attribute declaration
6437  * *WARNING* this interface is highly subject to change
6438  *
6439  * Returns -1 in case of error, 0 if the declaration is improper and
6440  *         1 in case of success.
6441  */
6442 static xmlSchemaAnnotPtr
xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr node,int needed)6443 xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int needed)
6444 {
6445     xmlSchemaAnnotPtr ret;
6446     xmlNodePtr child = NULL;
6447     xmlAttrPtr attr;
6448     int barked = 0;
6449 
6450     /*
6451     * INFO: S4S completed.
6452     */
6453     /*
6454     * id = ID
6455     * {any attributes with non-schema namespace . . .}>
6456     * Content: (appinfo | documentation)*
6457     */
6458     if ((ctxt == NULL) || (node == NULL))
6459         return (NULL);
6460     if (needed)
6461 	ret = xmlSchemaNewAnnot(ctxt, node);
6462     else
6463 	ret = NULL;
6464     attr = node->properties;
6465     while (attr != NULL) {
6466 	if (((attr->ns == NULL) &&
6467 	    (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
6468 	    ((attr->ns != NULL) &&
6469 	    xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
6470 
6471 	    xmlSchemaPIllegalAttrErr(ctxt,
6472 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6473 	}
6474 	attr = attr->next;
6475     }
6476     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6477     /*
6478     * And now for the children...
6479     */
6480     child = node->children;
6481     while (child != NULL) {
6482 	if (IS_SCHEMA(child, "appinfo")) {
6483 	    /* TODO: make available the content of "appinfo". */
6484 	    /*
6485 	    * source = anyURI
6486 	    * {any attributes with non-schema namespace . . .}>
6487 	    * Content: ({any})*
6488 	    */
6489 	    attr = child->properties;
6490 	    while (attr != NULL) {
6491 		if (((attr->ns == NULL) &&
6492 		     (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
6493 		     ((attr->ns != NULL) &&
6494 		      xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
6495 
6496 		    xmlSchemaPIllegalAttrErr(ctxt,
6497 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6498 		}
6499 		attr = attr->next;
6500 	    }
6501 	    xmlSchemaPValAttr(ctxt, NULL, child, "source",
6502 		xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
6503 	    child = child->next;
6504 	} else if (IS_SCHEMA(child, "documentation")) {
6505 	    /* TODO: make available the content of "documentation". */
6506 	    /*
6507 	    * source = anyURI
6508 	    * {any attributes with non-schema namespace . . .}>
6509 	    * Content: ({any})*
6510 	    */
6511 	    attr = child->properties;
6512 	    while (attr != NULL) {
6513 		if (attr->ns == NULL) {
6514 		    if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
6515 			xmlSchemaPIllegalAttrErr(ctxt,
6516 			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6517 		    }
6518 		} else {
6519 		    if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
6520 			(xmlStrEqual(attr->name, BAD_CAST "lang") &&
6521 			(!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
6522 
6523 			xmlSchemaPIllegalAttrErr(ctxt,
6524 			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6525 		    }
6526 		}
6527 		attr = attr->next;
6528 	    }
6529 	    /*
6530 	    * Attribute "xml:lang".
6531 	    */
6532 	    attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
6533 	    if (attr != NULL)
6534 		xmlSchemaPValAttrNode(ctxt, NULL, attr,
6535 		xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
6536 	    child = child->next;
6537 	} else {
6538 	    if (!barked)
6539 		xmlSchemaPContentErr(ctxt,
6540 		    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6541 		    NULL, node, child, NULL, "(appinfo | documentation)*");
6542 	    barked = 1;
6543 	    child = child->next;
6544 	}
6545     }
6546 
6547     return (ret);
6548 }
6549 
6550 /**
6551  * xmlSchemaParseFacet:
6552  * @ctxt:  a schema validation context
6553  * @schema:  the schema being built
6554  * @node:  a subtree containing XML Schema information
6555  *
6556  * parse a XML schema Facet declaration
6557  * *WARNING* this interface is highly subject to change
6558  *
6559  * Returns the new type structure or NULL in case of error
6560  */
6561 static xmlSchemaFacetPtr
xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)6562 xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6563                     xmlNodePtr node)
6564 {
6565     xmlSchemaFacetPtr facet;
6566     xmlNodePtr child = NULL;
6567     const xmlChar *value;
6568 
6569     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6570         return (NULL);
6571 
6572     facet = xmlSchemaNewFacet();
6573     if (facet == NULL) {
6574         xmlSchemaPErrMemory(ctxt);
6575         return (NULL);
6576     }
6577     facet->node = node;
6578     value = xmlSchemaGetProp(ctxt, node, "value");
6579     if (value == NULL) {
6580         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
6581                        "Facet %s has no value\n", node->name, NULL);
6582         xmlSchemaFreeFacet(facet);
6583         return (NULL);
6584     }
6585     if (IS_SCHEMA(node, "minInclusive")) {
6586         facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
6587     } else if (IS_SCHEMA(node, "minExclusive")) {
6588         facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
6589     } else if (IS_SCHEMA(node, "maxInclusive")) {
6590         facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
6591     } else if (IS_SCHEMA(node, "maxExclusive")) {
6592         facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
6593     } else if (IS_SCHEMA(node, "totalDigits")) {
6594         facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
6595     } else if (IS_SCHEMA(node, "fractionDigits")) {
6596         facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
6597     } else if (IS_SCHEMA(node, "pattern")) {
6598         facet->type = XML_SCHEMA_FACET_PATTERN;
6599     } else if (IS_SCHEMA(node, "enumeration")) {
6600         facet->type = XML_SCHEMA_FACET_ENUMERATION;
6601     } else if (IS_SCHEMA(node, "whiteSpace")) {
6602         facet->type = XML_SCHEMA_FACET_WHITESPACE;
6603     } else if (IS_SCHEMA(node, "length")) {
6604         facet->type = XML_SCHEMA_FACET_LENGTH;
6605     } else if (IS_SCHEMA(node, "maxLength")) {
6606         facet->type = XML_SCHEMA_FACET_MAXLENGTH;
6607     } else if (IS_SCHEMA(node, "minLength")) {
6608         facet->type = XML_SCHEMA_FACET_MINLENGTH;
6609     } else {
6610         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
6611                        "Unknown facet type %s\n", node->name, NULL);
6612         xmlSchemaFreeFacet(facet);
6613         return (NULL);
6614     }
6615     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6616     facet->value = value;
6617     if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
6618 	(facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
6619 	const xmlChar *fixed;
6620 
6621 	fixed = xmlSchemaGetProp(ctxt, node, "fixed");
6622 	if (fixed != NULL) {
6623 	    if (xmlStrEqual(fixed, BAD_CAST "true"))
6624 		facet->fixed = 1;
6625 	}
6626     }
6627     child = node->children;
6628 
6629     if (IS_SCHEMA(child, "annotation")) {
6630         facet->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6631         child = child->next;
6632     }
6633     if (child != NULL) {
6634         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
6635                        "Facet %s has unexpected child content\n",
6636                        node->name, NULL);
6637     }
6638     return (facet);
6639 }
6640 
6641 /**
6642  * xmlSchemaParseWildcardNs:
6643  * @ctxt:  a schema parser context
6644  * @wildc:  the wildcard, already created
6645  * @node:  a subtree containing XML Schema information
6646  *
6647  * Parses the attribute "processContents" and "namespace"
6648  * of a xsd:anyAttribute and xsd:any.
6649  * *WARNING* this interface is highly subject to change
6650  *
6651  * Returns 0 if everything goes fine, a positive error code
6652  * if something is not valid and -1 if an internal error occurs.
6653  */
6654 static int
xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema ATTRIBUTE_UNUSED,xmlSchemaWildcardPtr wildc,xmlNodePtr node)6655 xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
6656 			 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
6657 			 xmlSchemaWildcardPtr wildc,
6658 			 xmlNodePtr node)
6659 {
6660     const xmlChar *pc, *ns, *dictnsItem;
6661     int ret = 0;
6662     xmlChar *nsItem;
6663     xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
6664     xmlAttrPtr attr;
6665 
6666     pc = xmlSchemaGetProp(ctxt, node, "processContents");
6667     if ((pc == NULL)
6668         || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
6669         wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6670     } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
6671         wildc->processContents = XML_SCHEMAS_ANY_SKIP;
6672     } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
6673         wildc->processContents = XML_SCHEMAS_ANY_LAX;
6674     } else {
6675         xmlSchemaPSimpleTypeErr(ctxt,
6676 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6677 	    NULL, node,
6678 	    NULL, "(strict | skip | lax)", pc,
6679 	    NULL, NULL, NULL);
6680         wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6681 	ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
6682     }
6683     /*
6684      * Build the namespace constraints.
6685      */
6686     attr = xmlSchemaGetPropNode(node, "namespace");
6687     ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6688     if (ns == NULL)
6689         return (-1);
6690     if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
6691 	wildc->any = 1;
6692     else if (xmlStrEqual(ns, BAD_CAST "##other")) {
6693 	wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
6694 	if (wildc->negNsSet == NULL) {
6695 	    return (-1);
6696 	}
6697 	wildc->negNsSet->value = ctxt->targetNamespace;
6698     } else {
6699 	const xmlChar *end, *cur;
6700 
6701 	cur = ns;
6702 	do {
6703 	    while (IS_BLANK_CH(*cur))
6704 		cur++;
6705 	    end = cur;
6706 	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6707 		end++;
6708 	    if (end == cur)
6709 		break;
6710 	    nsItem = xmlStrndup(cur, end - cur);
6711 	    if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
6712 		    (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
6713 		xmlSchemaPSimpleTypeErr(ctxt,
6714 		    XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
6715 		    NULL, (xmlNodePtr) attr,
6716 		    NULL,
6717 		    "((##any | ##other) | List of (xs:anyURI | "
6718 		    "(##targetNamespace | ##local)))",
6719 		    nsItem, NULL, NULL, NULL);
6720 		ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
6721 	    } else {
6722 		if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
6723 		    dictnsItem = ctxt->targetNamespace;
6724 		} else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
6725 		    dictnsItem = NULL;
6726 		} else {
6727 		    /*
6728 		    * Validate the item (anyURI).
6729 		    */
6730 		    xmlSchemaPValAttrNodeValue(ctxt, NULL, attr,
6731 			nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
6732 		    dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
6733 		}
6734 		/*
6735 		* Avoid duplicate namespaces.
6736 		*/
6737 		tmp = wildc->nsSet;
6738 		while (tmp != NULL) {
6739 		    if (dictnsItem == tmp->value)
6740 			break;
6741 		    tmp = tmp->next;
6742 		}
6743 		if (tmp == NULL) {
6744 		    tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
6745 		    if (tmp == NULL) {
6746 			xmlFree(nsItem);
6747 			return (-1);
6748 		    }
6749 		    tmp->value = dictnsItem;
6750 		    tmp->next = NULL;
6751 		    if (wildc->nsSet == NULL)
6752 			wildc->nsSet = tmp;
6753 		    else if (lastNs != NULL)
6754 			lastNs->next = tmp;
6755 		    lastNs = tmp;
6756 		}
6757 
6758 	    }
6759 	    xmlFree(nsItem);
6760 	    cur = end;
6761 	} while (*cur != 0);
6762     }
6763     return (ret);
6764 }
6765 
6766 static int
xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,xmlNodePtr node,int minOccurs,int maxOccurs)6767 xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
6768 				 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
6769 				 xmlNodePtr node,
6770 				 int minOccurs,
6771 				 int maxOccurs) {
6772 
6773     if ((maxOccurs == 0) && ( minOccurs == 0))
6774 	return (0);
6775     if (maxOccurs != UNBOUNDED) {
6776 	/*
6777 	* TODO: Maybe we should better not create the particle,
6778 	* if min/max is invalid, since it could confuse the build of the
6779 	* content model.
6780 	*/
6781 	/*
6782 	* 3.9.6 Schema Component Constraint: Particle Correct
6783 	*
6784 	*/
6785 	if (maxOccurs < 1) {
6786 	    /*
6787 	    * 2.2 {max occurs} must be greater than or equal to 1.
6788 	    */
6789 	    xmlSchemaPCustomAttrErr(ctxt,
6790 		XML_SCHEMAP_P_PROPS_CORRECT_2_2,
6791 		NULL, NULL,
6792 		xmlSchemaGetPropNode(node, "maxOccurs"),
6793 		"The value must be greater than or equal to 1");
6794 	    return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6795 	} else if (minOccurs > maxOccurs) {
6796 	    /*
6797 	    * 2.1 {min occurs} must not be greater than {max occurs}.
6798 	    */
6799 	    xmlSchemaPCustomAttrErr(ctxt,
6800 		XML_SCHEMAP_P_PROPS_CORRECT_2_1,
6801 		NULL, NULL,
6802 		xmlSchemaGetPropNode(node, "minOccurs"),
6803 		"The value must not be greater than the value of 'maxOccurs'");
6804 	    return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6805 	}
6806     }
6807     return (0);
6808 }
6809 
6810 /**
6811  * xmlSchemaParseAny:
6812  * @ctxt:  a schema validation context
6813  * @schema:  the schema being built
6814  * @node:  a subtree containing XML Schema information
6815  *
6816  * Parsea a XML schema <any> element. A particle and wildcard
6817  * will be created (except if minOccurs==maxOccurs==0, in this case
6818  * nothing will be created).
6819  * *WARNING* this interface is highly subject to change
6820  *
6821  * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
6822  */
6823 static xmlSchemaParticlePtr
xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)6824 xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6825                   xmlNodePtr node)
6826 {
6827     xmlSchemaParticlePtr particle;
6828     xmlNodePtr child = NULL;
6829     xmlSchemaWildcardPtr wild;
6830     int min, max;
6831     xmlAttrPtr attr;
6832     xmlSchemaAnnotPtr annot = NULL;
6833 
6834     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6835         return (NULL);
6836     /*
6837     * Check for illegal attributes.
6838     */
6839     attr = node->properties;
6840     while (attr != NULL) {
6841 	if (attr->ns == NULL) {
6842 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6843 		(!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6844 		(!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6845 	        (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6846 		(!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
6847 		xmlSchemaPIllegalAttrErr(ctxt,
6848 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6849 	    }
6850 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6851 	    xmlSchemaPIllegalAttrErr(ctxt,
6852 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6853 	}
6854 	attr = attr->next;
6855     }
6856     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6857     /*
6858     * minOccurs/maxOccurs.
6859     */
6860     max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
6861 	"(xs:nonNegativeInteger | unbounded)");
6862     min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
6863 	"xs:nonNegativeInteger");
6864     xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
6865     /*
6866     * Create & parse the wildcard.
6867     */
6868     wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
6869     if (wild == NULL)
6870 	return (NULL);
6871     xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
6872     /*
6873     * And now for the children...
6874     */
6875     child = node->children;
6876     if (IS_SCHEMA(child, "annotation")) {
6877         annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6878         child = child->next;
6879     }
6880     if (child != NULL) {
6881 	xmlSchemaPContentErr(ctxt,
6882 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6883 	    NULL, node, child,
6884 	    NULL, "(annotation?)");
6885     }
6886     /*
6887     * No component if minOccurs==maxOccurs==0.
6888     */
6889     if ((min == 0) && (max == 0)) {
6890 	/* Don't free the wildcard, since it's already on the list. */
6891 	return (NULL);
6892     }
6893     /*
6894     * Create the particle.
6895     */
6896     particle = xmlSchemaAddParticle(ctxt, node, min, max);
6897     if (particle == NULL)
6898         return (NULL);
6899     particle->annot = annot;
6900     particle->children = (xmlSchemaTreeItemPtr) wild;
6901 
6902     return (particle);
6903 }
6904 
6905 /**
6906  * xmlSchemaParseNotation:
6907  * @ctxt:  a schema validation context
6908  * @schema:  the schema being built
6909  * @node:  a subtree containing XML Schema information
6910  *
6911  * parse a XML schema Notation declaration
6912  *
6913  * Returns the new structure or NULL in case of error
6914  */
6915 static xmlSchemaNotationPtr
xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)6916 xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6917                        xmlNodePtr node)
6918 {
6919     const xmlChar *name;
6920     xmlSchemaNotationPtr ret;
6921     xmlNodePtr child = NULL;
6922 
6923     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6924         return (NULL);
6925     name = xmlSchemaGetProp(ctxt, node, "name");
6926     if (name == NULL) {
6927         xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
6928                        "Notation has no name\n", NULL, NULL);
6929         return (NULL);
6930     }
6931     ret = xmlSchemaAddNotation(ctxt, schema, name,
6932 	ctxt->targetNamespace, node);
6933     if (ret == NULL)
6934         return (NULL);
6935     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6936 
6937     child = node->children;
6938     if (IS_SCHEMA(child, "annotation")) {
6939         ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6940         child = child->next;
6941     }
6942     if (child != NULL) {
6943 	xmlSchemaPContentErr(ctxt,
6944 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6945 	    NULL, node, child,
6946 	    NULL, "(annotation?)");
6947     }
6948 
6949     return (ret);
6950 }
6951 
6952 /**
6953  * xmlSchemaParseAnyAttribute:
6954  * @ctxt:  a schema validation context
6955  * @schema:  the schema being built
6956  * @node:  a subtree containing XML Schema information
6957  *
6958  * parse a XML schema AnyAttribute declaration
6959  * *WARNING* this interface is highly subject to change
6960  *
6961  * Returns a wildcard or NULL.
6962  */
6963 static xmlSchemaWildcardPtr
xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)6964 xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6965                            xmlSchemaPtr schema, xmlNodePtr node)
6966 {
6967     xmlSchemaWildcardPtr ret;
6968     xmlNodePtr child = NULL;
6969     xmlAttrPtr attr;
6970 
6971     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6972         return (NULL);
6973 
6974     ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
6975 	node);
6976     if (ret == NULL) {
6977         return (NULL);
6978     }
6979     /*
6980     * Check for illegal attributes.
6981     */
6982     attr = node->properties;
6983     while (attr != NULL) {
6984 	if (attr->ns == NULL) {
6985 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6986 	        (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6987 		(!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
6988 		xmlSchemaPIllegalAttrErr(ctxt,
6989 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6990 	    }
6991 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6992 	    xmlSchemaPIllegalAttrErr(ctxt,
6993 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6994 	}
6995 	attr = attr->next;
6996     }
6997     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6998     /*
6999     * Parse the namespace list.
7000     */
7001     if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
7002 	return (NULL);
7003     /*
7004     * And now for the children...
7005     */
7006     child = node->children;
7007     if (IS_SCHEMA(child, "annotation")) {
7008         ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
7009         child = child->next;
7010     }
7011     if (child != NULL) {
7012 	xmlSchemaPContentErr(ctxt,
7013 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7014 	    NULL, node, child,
7015 	    NULL, "(annotation?)");
7016     }
7017 
7018     return (ret);
7019 }
7020 
7021 
7022 /**
7023  * xmlSchemaParseAttribute:
7024  * @ctxt:  a schema validation context
7025  * @schema:  the schema being built
7026  * @node:  a subtree containing XML Schema information
7027  *
7028  * parse a XML schema Attribute declaration
7029  * *WARNING* this interface is highly subject to change
7030  *
7031  * Returns the attribute declaration.
7032  */
7033 static xmlSchemaBasicItemPtr
xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlSchemaItemListPtr uses,int parentType)7034 xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
7035 			     xmlSchemaPtr schema,
7036 			     xmlNodePtr node,
7037 			     xmlSchemaItemListPtr uses,
7038 			     int parentType)
7039 {
7040     const xmlChar *attrValue, *name = NULL, *ns = NULL;
7041     xmlSchemaAttributeUsePtr use = NULL;
7042     xmlNodePtr child = NULL;
7043     xmlAttrPtr attr;
7044     const xmlChar *tmpNs = NULL, *tmpName = NULL, *defValue = NULL;
7045     int isRef = 0, occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7046     int	nberrors, hasForm = 0, defValueType = 0;
7047 
7048 #define WXS_ATTR_DEF_VAL_DEFAULT 1
7049 #define WXS_ATTR_DEF_VAL_FIXED 2
7050 
7051     /*
7052      * 3.2.3 Constraints on XML Representations of Attribute Declarations
7053      */
7054 
7055     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7056         return (NULL);
7057     attr = xmlSchemaGetPropNode(node, "ref");
7058     if (attr != NULL) {
7059 	if (xmlSchemaPValAttrNodeQName(pctxt, schema,
7060 	    NULL, attr, &tmpNs, &tmpName) != 0) {
7061 	    return (NULL);
7062 	}
7063 	if (xmlSchemaCheckReference(pctxt, schema, node, attr, tmpNs) != 0)
7064 	    return(NULL);
7065 	isRef = 1;
7066     }
7067     nberrors = pctxt->nberrors;
7068     /*
7069     * Check for illegal attributes.
7070     */
7071     attr = node->properties;
7072     while (attr != NULL) {
7073 	if (attr->ns == NULL) {
7074 	    if (isRef) {
7075 		if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7076 		    xmlSchemaPValAttrNodeID(pctxt, attr);
7077 		    goto attr_next;
7078 		} else if (xmlStrEqual(attr->name, BAD_CAST "ref")) {
7079 		    goto attr_next;
7080 		}
7081 	    } else {
7082 		if (xmlStrEqual(attr->name, BAD_CAST "name")) {
7083 		    goto attr_next;
7084 		} else if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7085 		    xmlSchemaPValAttrNodeID(pctxt, attr);
7086 		    goto attr_next;
7087 		} else if (xmlStrEqual(attr->name, BAD_CAST "type")) {
7088 		    xmlSchemaPValAttrNodeQName(pctxt, schema, NULL,
7089 			attr, &tmpNs, &tmpName);
7090 		    goto attr_next;
7091 		} else if (xmlStrEqual(attr->name, BAD_CAST "form")) {
7092 		    /*
7093 		    * Evaluate the target namespace
7094 		    */
7095 		    hasForm = 1;
7096 		    attrValue = xmlSchemaGetNodeContent(pctxt,
7097 			(xmlNodePtr) attr);
7098 		    if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
7099 			ns = pctxt->targetNamespace;
7100 		    } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified"))
7101 		    {
7102 			xmlSchemaPSimpleTypeErr(pctxt,
7103 			    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7104 			    NULL, (xmlNodePtr) attr,
7105 			    NULL, "(qualified | unqualified)",
7106 			    attrValue, NULL, NULL, NULL);
7107 		    }
7108 		    goto attr_next;
7109 		}
7110 	    }
7111 	    if (xmlStrEqual(attr->name, BAD_CAST "use")) {
7112 
7113 		attrValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7114 		/* TODO: Maybe we need to normalize the value beforehand. */
7115 		if (xmlStrEqual(attrValue, BAD_CAST "optional"))
7116 		    occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7117 		else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
7118 		    occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
7119 		else if (xmlStrEqual(attrValue, BAD_CAST "required"))
7120 		    occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
7121 		else {
7122 		    xmlSchemaPSimpleTypeErr(pctxt,
7123 			XML_SCHEMAP_INVALID_ATTR_USE,
7124 			NULL, (xmlNodePtr) attr,
7125 			NULL, "(optional | prohibited | required)",
7126 			attrValue, NULL, NULL, NULL);
7127 		}
7128 		goto attr_next;
7129 	    } else if (xmlStrEqual(attr->name, BAD_CAST "default")) {
7130 		/*
7131 		* 3.2.3 : 1
7132 		* default and fixed must not both be present.
7133 		*/
7134 		if (defValue) {
7135 		    xmlSchemaPMutualExclAttrErr(pctxt,
7136 			XML_SCHEMAP_SRC_ATTRIBUTE_1,
7137 			NULL, attr, "default", "fixed");
7138 		} else {
7139 		    defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7140 		    defValueType = WXS_ATTR_DEF_VAL_DEFAULT;
7141 		}
7142 		goto attr_next;
7143 	    } else if (xmlStrEqual(attr->name, BAD_CAST "fixed")) {
7144 		/*
7145 		* 3.2.3 : 1
7146 		* default and fixed must not both be present.
7147 		*/
7148 		if (defValue) {
7149 		    xmlSchemaPMutualExclAttrErr(pctxt,
7150 			XML_SCHEMAP_SRC_ATTRIBUTE_1,
7151 			NULL, attr, "default", "fixed");
7152 		} else {
7153 		    defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7154 		    defValueType = WXS_ATTR_DEF_VAL_FIXED;
7155 		}
7156 		goto attr_next;
7157 	    }
7158 	} else if (! xmlStrEqual(attr->ns->href, xmlSchemaNs))
7159 	    goto attr_next;
7160 
7161 	xmlSchemaPIllegalAttrErr(pctxt,
7162 	    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7163 
7164 attr_next:
7165 	attr = attr->next;
7166     }
7167     /*
7168     * 3.2.3 : 2
7169     * If default and use are both present, use must have
7170     * the actual value optional.
7171     */
7172     if ((defValueType == WXS_ATTR_DEF_VAL_DEFAULT) &&
7173 	(occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
7174 	xmlSchemaPSimpleTypeErr(pctxt,
7175 	    XML_SCHEMAP_SRC_ATTRIBUTE_2,
7176 	    NULL, node, NULL,
7177 	    "(optional | prohibited | required)", NULL,
7178 	    "The value of the attribute 'use' must be 'optional' "
7179 	    "if the attribute 'default' is present",
7180 	    NULL, NULL);
7181     }
7182     /*
7183     * We want correct attributes.
7184     */
7185     if (nberrors != pctxt->nberrors)
7186 	return(NULL);
7187     if (! isRef) {
7188 	xmlSchemaAttributePtr attrDecl;
7189 
7190 	/* TODO: move XML_SCHEMAS_QUALIF_ATTR to the parser. */
7191 	if ((! hasForm) && (schema->flags & XML_SCHEMAS_QUALIF_ATTR))
7192 	    ns = pctxt->targetNamespace;
7193 	/*
7194 	* 3.2.6 Schema Component Constraint: xsi: Not Allowed
7195 	* TODO: Move this to the component layer.
7196 	*/
7197 	if (xmlStrEqual(ns, xmlSchemaInstanceNs)) {
7198 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
7199 		XML_SCHEMAP_NO_XSI,
7200 		node, NULL,
7201 		"The target namespace must not match '%s'",
7202 		xmlSchemaInstanceNs, NULL);
7203 	}
7204 	attr = xmlSchemaGetPropNode(node, "name");
7205 	if (attr == NULL) {
7206 	    xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7207 		NULL, node, "name", NULL);
7208 	    return (NULL);
7209 	}
7210 	if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7211 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7212 	    return (NULL);
7213 	}
7214 	/*
7215 	* 3.2.6 Schema Component Constraint: xmlns Not Allowed
7216 	* TODO: Move this to the component layer.
7217 	*/
7218 	if (xmlStrEqual(name, BAD_CAST "xmlns")) {
7219 	    xmlSchemaPSimpleTypeErr(pctxt,
7220 		XML_SCHEMAP_NO_XMLNS,
7221 		NULL, (xmlNodePtr) attr,
7222 		xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7223 		"The value of the attribute must not match 'xmlns'",
7224 		NULL, NULL);
7225 	    return (NULL);
7226 	}
7227 	if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED)
7228 	    goto check_children;
7229 	/*
7230 	* Create the attribute use component.
7231 	*/
7232 	use = xmlSchemaAddAttributeUse(pctxt, node);
7233 	if (use == NULL)
7234 	    return(NULL);
7235 	use->occurs = occurs;
7236 	/*
7237 	* Create the attribute declaration.
7238 	*/
7239 	attrDecl = xmlSchemaAddAttribute(pctxt, schema, name, ns, node, 0);
7240 	if (attrDecl == NULL)
7241 	    return (NULL);
7242 	if (tmpName != NULL) {
7243 	    attrDecl->typeName = tmpName;
7244 	    attrDecl->typeNs = tmpNs;
7245 	}
7246 	use->attrDecl = attrDecl;
7247 	/*
7248 	* Value constraint.
7249 	*/
7250 	if (defValue != NULL) {
7251 	    attrDecl->defValue = defValue;
7252 	    if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7253 		attrDecl->flags |= XML_SCHEMAS_ATTR_FIXED;
7254 	}
7255     } else if (occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7256 	xmlSchemaQNameRefPtr ref;
7257 
7258 	/*
7259 	* Create the attribute use component.
7260 	*/
7261 	use = xmlSchemaAddAttributeUse(pctxt, node);
7262 	if (use == NULL)
7263 	    return(NULL);
7264 	/*
7265 	* We need to resolve the reference at later stage.
7266 	*/
7267 	WXS_ADD_PENDING(pctxt, use);
7268 	use->occurs = occurs;
7269 	/*
7270 	* Create a QName reference to the attribute declaration.
7271 	*/
7272 	ref = xmlSchemaNewQNameRef(pctxt, XML_SCHEMA_TYPE_ATTRIBUTE,
7273 	    tmpName, tmpNs);
7274 	if (ref == NULL)
7275 	    return(NULL);
7276 	/*
7277 	* Assign the reference. This will be substituted for the
7278 	* referenced attribute declaration when the QName is resolved.
7279 	*/
7280 	use->attrDecl = WXS_ATTR_CAST ref;
7281 	/*
7282 	* Value constraint.
7283 	*/
7284 	if (defValue != NULL)
7285 	    use->defValue = defValue;
7286 	if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7287 	    use->flags |= XML_SCHEMA_ATTR_USE_FIXED;
7288     }
7289 
7290 check_children:
7291     /*
7292     * And now for the children...
7293     */
7294     child = node->children;
7295     if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7296 	xmlSchemaAttributeUseProhibPtr prohib;
7297 
7298 	if (IS_SCHEMA(child, "annotation")) {
7299 	    xmlSchemaParseAnnotation(pctxt, child, 0);
7300 	    child = child->next;
7301 	}
7302 	if (child != NULL) {
7303 	    xmlSchemaPContentErr(pctxt,
7304 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7305 		NULL, node, child, NULL,
7306 		"(annotation?)");
7307 	}
7308 	/*
7309 	* Check for pointlessness of attribute prohibitions.
7310 	*/
7311 	if (parentType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
7312 	    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7313 		XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7314 		node, NULL,
7315 		"Skipping attribute use prohibition, since it is "
7316 		"pointless inside an <attributeGroup>",
7317 		NULL, NULL, NULL);
7318 	    return(NULL);
7319 	} else if (parentType == XML_SCHEMA_TYPE_EXTENSION) {
7320 	    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7321 		XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7322 		node, NULL,
7323 		"Skipping attribute use prohibition, since it is "
7324 		"pointless when extending a type",
7325 		NULL, NULL, NULL);
7326 	    return(NULL);
7327 	}
7328 	if (! isRef) {
7329 	    tmpName = name;
7330 	    tmpNs = ns;
7331 	}
7332 	/*
7333 	* Check for duplicate attribute prohibitions.
7334 	*/
7335 	if (uses) {
7336 	    int i;
7337 
7338 	    for (i = 0; i < uses->nbItems; i++) {
7339 		use = uses->items[i];
7340 		if ((use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) &&
7341 		    (tmpName == (WXS_ATTR_PROHIB_CAST use)->name) &&
7342 		    (tmpNs == (WXS_ATTR_PROHIB_CAST use)->targetNamespace))
7343 		{
7344 		    xmlChar *str = NULL;
7345 
7346 		    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7347 			XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7348 			node, NULL,
7349 			"Skipping duplicate attribute use prohibition '%s'",
7350 			xmlSchemaFormatQName(&str, tmpNs, tmpName),
7351 			NULL, NULL);
7352 		    FREE_AND_NULL(str)
7353 		    return(NULL);
7354 		}
7355 	    }
7356 	}
7357 	/*
7358 	* Create the attribute prohibition helper component.
7359 	*/
7360 	prohib = xmlSchemaAddAttributeUseProhib(pctxt);
7361 	if (prohib == NULL)
7362 	    return(NULL);
7363 	prohib->node = node;
7364 	prohib->name = tmpName;
7365 	prohib->targetNamespace = tmpNs;
7366 	if (isRef) {
7367 	    /*
7368 	    * We need at least to resolve to the attribute declaration.
7369 	    */
7370 	    WXS_ADD_PENDING(pctxt, prohib);
7371 	}
7372 	return(WXS_BASIC_CAST prohib);
7373     } else {
7374 	if (IS_SCHEMA(child, "annotation")) {
7375 	    /*
7376 	    * TODO: Should this go into the attr decl?
7377 	    */
7378 	    use->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7379 	    child = child->next;
7380 	}
7381 	if (isRef) {
7382 	    if (child != NULL) {
7383 		if (IS_SCHEMA(child, "simpleType"))
7384 		    /*
7385 		    * 3.2.3 : 3.2
7386 		    * If ref is present, then all of <simpleType>,
7387 		    * form and type must be absent.
7388 		    */
7389 		    xmlSchemaPContentErr(pctxt,
7390 			XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
7391 			NULL, node, child, NULL,
7392 			"(annotation?)");
7393 		else
7394 		    xmlSchemaPContentErr(pctxt,
7395 			XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7396 			NULL, node, child, NULL,
7397 			"(annotation?)");
7398 	    }
7399 	} else {
7400 	    if (IS_SCHEMA(child, "simpleType")) {
7401 		if (WXS_ATTRUSE_DECL(use)->typeName != NULL) {
7402 		    /*
7403 		    * 3.2.3 : 4
7404 		    * type and <simpleType> must not both be present.
7405 		    */
7406 		    xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7407 			NULL, node, child,
7408 			"The attribute 'type' and the <simpleType> child "
7409 			"are mutually exclusive", NULL);
7410 		} else
7411 		    WXS_ATTRUSE_TYPEDEF(use) =
7412 			xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7413 		child = child->next;
7414 	    }
7415 	    if (child != NULL)
7416 		xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7417 		NULL, node, child, NULL,
7418 		"(annotation?, simpleType?)");
7419 	}
7420     }
7421     return (WXS_BASIC_CAST use);
7422 }
7423 
7424 
7425 static xmlSchemaAttributePtr
xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)7426 xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt,
7427 			      xmlSchemaPtr schema,
7428 			      xmlNodePtr node)
7429 {
7430     const xmlChar *attrValue;
7431     xmlSchemaAttributePtr ret;
7432     xmlNodePtr child = NULL;
7433     xmlAttrPtr attr;
7434 
7435     /*
7436      * Note that the w3c spec assumes the schema to be validated with schema
7437      * for schemas beforehand.
7438      *
7439      * 3.2.3 Constraints on XML Representations of Attribute Declarations
7440      */
7441     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7442         return (NULL);
7443     /*
7444     * 3.2.3 : 3.1
7445     * One of ref or name must be present, but not both
7446     */
7447     attr = xmlSchemaGetPropNode(node, "name");
7448     if (attr == NULL) {
7449 	xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7450 	    NULL, node, "name", NULL);
7451 	return (NULL);
7452     }
7453     if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7454 	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
7455 	return (NULL);
7456     }
7457     /*
7458     * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7459     * TODO: Move this to the component layer.
7460     */
7461     if (xmlStrEqual(attrValue, BAD_CAST "xmlns")) {
7462 	xmlSchemaPSimpleTypeErr(pctxt,
7463 	    XML_SCHEMAP_NO_XMLNS,
7464 	    NULL, (xmlNodePtr) attr,
7465 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7466 	    "The value of the attribute must not match 'xmlns'",
7467 	    NULL, NULL);
7468 	return (NULL);
7469     }
7470     /*
7471     * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7472     * TODO: Move this to the component layer.
7473     *       Or better leave it here and add it to the component layer
7474     *       if we have a schema construction API.
7475     */
7476     if (xmlStrEqual(pctxt->targetNamespace, xmlSchemaInstanceNs)) {
7477 	xmlSchemaCustomErr(ACTXT_CAST pctxt,
7478 	    XML_SCHEMAP_NO_XSI, node, NULL,
7479 	    "The target namespace must not match '%s'",
7480 	    xmlSchemaInstanceNs, NULL);
7481     }
7482 
7483     ret = xmlSchemaAddAttribute(pctxt, schema, attrValue,
7484 	pctxt->targetNamespace, node, 1);
7485     if (ret == NULL)
7486 	return (NULL);
7487     ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
7488 
7489     /*
7490     * Check for illegal attributes.
7491     */
7492     attr = node->properties;
7493     while (attr != NULL) {
7494 	if (attr->ns == NULL) {
7495 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7496 		(!xmlStrEqual(attr->name, BAD_CAST "default")) &&
7497 		(!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
7498 		(!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7499 		(!xmlStrEqual(attr->name, BAD_CAST "type")))
7500 	    {
7501 		xmlSchemaPIllegalAttrErr(pctxt,
7502 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7503 	    }
7504 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7505 	    xmlSchemaPIllegalAttrErr(pctxt,
7506 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7507 	}
7508 	attr = attr->next;
7509     }
7510     xmlSchemaPValAttrQName(pctxt, schema, NULL,
7511 	node, "type", &ret->typeNs, &ret->typeName);
7512 
7513     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7514     /*
7515     * Attribute "fixed".
7516     */
7517     ret->defValue = xmlSchemaGetProp(pctxt, node, "fixed");
7518     if (ret->defValue != NULL)
7519 	ret->flags |= XML_SCHEMAS_ATTR_FIXED;
7520     /*
7521     * Attribute "default".
7522     */
7523     attr = xmlSchemaGetPropNode(node, "default");
7524     if (attr != NULL) {
7525 	/*
7526 	* 3.2.3 : 1
7527 	* default and fixed must not both be present.
7528 	*/
7529 	if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
7530 	    xmlSchemaPMutualExclAttrErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
7531 		WXS_BASIC_CAST ret, attr, "default", "fixed");
7532 	} else
7533 	    ret->defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7534     }
7535     /*
7536     * And now for the children...
7537     */
7538     child = node->children;
7539     if (IS_SCHEMA(child, "annotation")) {
7540         ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7541         child = child->next;
7542     }
7543     if (IS_SCHEMA(child, "simpleType")) {
7544 	if (ret->typeName != NULL) {
7545 	    /*
7546 	    * 3.2.3 : 4
7547 	    * type and <simpleType> must not both be present.
7548 	    */
7549 	    xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7550 		NULL, node, child,
7551 		"The attribute 'type' and the <simpleType> child "
7552 		"are mutually exclusive", NULL);
7553 	} else
7554 	    ret->subtypes = xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7555 	child = child->next;
7556     }
7557     if (child != NULL)
7558 	xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7559 	    NULL, node, child, NULL,
7560 	    "(annotation?, simpleType?)");
7561 
7562     return (ret);
7563 }
7564 
7565 /**
7566  * xmlSchemaParseAttributeGroupRef:
7567  * @ctxt:  a schema validation context
7568  * @schema:  the schema being built
7569  * @node:  a subtree containing XML Schema information
7570  *
7571  * Parse an attribute group definition reference.
7572  * Note that a reference to an attribute group does not
7573  * correspond to any component at all.
7574  * *WARNING* this interface is highly subject to change
7575  *
7576  * Returns the attribute group or NULL in case of error.
7577  */
7578 static xmlSchemaQNameRefPtr
xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)7579 xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
7580 				xmlSchemaPtr schema,
7581 				xmlNodePtr node)
7582 {
7583     xmlSchemaQNameRefPtr ret;
7584     xmlNodePtr child = NULL;
7585     xmlAttrPtr attr;
7586     const xmlChar *refNs = NULL, *ref = NULL;
7587 
7588     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7589         return (NULL);
7590 
7591     attr = xmlSchemaGetPropNode(node, "ref");
7592     if (attr == NULL) {
7593 	xmlSchemaPMissingAttrErr(pctxt,
7594 	    XML_SCHEMAP_S4S_ATTR_MISSING,
7595 	    NULL, node, "ref", NULL);
7596 	return (NULL);
7597     }
7598     xmlSchemaPValAttrNodeQName(pctxt, schema,
7599 	NULL, attr, &refNs, &ref);
7600     if (xmlSchemaCheckReference(pctxt, schema, node, attr, refNs) != 0)
7601 	return(NULL);
7602 
7603     /*
7604     * Check for illegal attributes.
7605     */
7606     attr = node->properties;
7607     while (attr != NULL) {
7608 	if (attr->ns == NULL) {
7609 	    if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
7610 		(!xmlStrEqual(attr->name, BAD_CAST "id")))
7611 	    {
7612 		xmlSchemaPIllegalAttrErr(pctxt,
7613 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7614 	    }
7615 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7616 	    xmlSchemaPIllegalAttrErr(pctxt,
7617 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7618 	}
7619 	attr = attr->next;
7620     }
7621     /* Attribute ID */
7622     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7623 
7624     /*
7625     * And now for the children...
7626     */
7627     child = node->children;
7628     if (IS_SCHEMA(child, "annotation")) {
7629 	/*
7630 	* TODO: We do not have a place to store the annotation, do we?
7631 	*/
7632         xmlSchemaParseAnnotation(pctxt, child, 0);
7633         child = child->next;
7634     }
7635     if (child != NULL) {
7636 	xmlSchemaPContentErr(pctxt,
7637 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7638 	    NULL, node, child, NULL,
7639 	    "(annotation?)");
7640     }
7641 
7642     /*
7643     * Handle attribute group redefinitions.
7644     */
7645     if (pctxt->isRedefine && pctxt->redef &&
7646 	(pctxt->redef->item->type ==
7647 	    XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
7648 	(ref == pctxt->redef->refName) &&
7649 	(refNs == pctxt->redef->refTargetNs))
7650     {
7651 	/*
7652 	* SPEC src-redefine:
7653 	* (7.1) "If it has an <attributeGroup> among its contents
7654 	* the `actual value` of whose ref [attribute] is the same
7655 	* as the `actual value` of its own name attribute plus
7656 	* target namespace, then it must have exactly one such group."
7657 	*/
7658 	if (pctxt->redefCounter != 0) {
7659 	    xmlChar *str = NULL;
7660 
7661 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
7662 		XML_SCHEMAP_SRC_REDEFINE, node, NULL,
7663 		"The redefining attribute group definition "
7664 		"'%s' must not contain more than one "
7665 		"reference to the redefined definition",
7666 		xmlSchemaFormatQName(&str, refNs, ref), NULL);
7667 	    FREE_AND_NULL(str);
7668 	    return(NULL);
7669 	}
7670 	pctxt->redefCounter++;
7671 	/*
7672 	* URGENT TODO: How to ensure that the reference will not be
7673 	* handled by the normal component resolution mechanism?
7674 	*/
7675 	ret = xmlSchemaNewQNameRef(pctxt,
7676 	    XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7677 	if (ret == NULL)
7678 	    return(NULL);
7679 	ret->node = node;
7680 	pctxt->redef->reference = WXS_BASIC_CAST ret;
7681     } else {
7682 	/*
7683 	* Create a QName-reference helper component. We will substitute this
7684 	* component for the attribute uses of the referenced attribute group
7685 	* definition.
7686 	*/
7687 	ret = xmlSchemaNewQNameRef(pctxt,
7688 	    XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7689 	if (ret == NULL)
7690 	    return(NULL);
7691 	ret->node = node;
7692 	/* Add to pending items, to be able to resolve the reference. */
7693 	WXS_ADD_PENDING(pctxt, ret);
7694     }
7695     return (ret);
7696 }
7697 
7698 /**
7699  * xmlSchemaParseAttributeGroupDefinition:
7700  * @pctxt:  a schema validation context
7701  * @schema:  the schema being built
7702  * @node:  a subtree containing XML Schema information
7703  *
7704  * parse a XML schema Attribute Group declaration
7705  * *WARNING* this interface is highly subject to change
7706  *
7707  * Returns the attribute group definition or NULL in case of error.
7708  */
7709 static xmlSchemaAttributeGroupPtr
xmlSchemaParseAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)7710 xmlSchemaParseAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
7711 				       xmlSchemaPtr schema,
7712 				       xmlNodePtr node)
7713 {
7714     const xmlChar *name;
7715     xmlSchemaAttributeGroupPtr ret;
7716     xmlNodePtr child = NULL;
7717     xmlAttrPtr attr;
7718     int hasRefs = 0;
7719 
7720     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7721         return (NULL);
7722 
7723     attr = xmlSchemaGetPropNode(node, "name");
7724     if (attr == NULL) {
7725 	xmlSchemaPMissingAttrErr(pctxt,
7726 	    XML_SCHEMAP_S4S_ATTR_MISSING,
7727 	    NULL, node, "name", NULL);
7728 	return (NULL);
7729     }
7730     /*
7731     * The name is crucial, exit if invalid.
7732     */
7733     if (xmlSchemaPValAttrNode(pctxt,
7734 	NULL, attr,
7735 	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7736 	return (NULL);
7737     }
7738     ret = xmlSchemaAddAttributeGroupDefinition(pctxt, schema,
7739 	name, pctxt->targetNamespace, node);
7740     if (ret == NULL)
7741 	return (NULL);
7742     /*
7743     * Check for illegal attributes.
7744     */
7745     attr = node->properties;
7746     while (attr != NULL) {
7747 	if (attr->ns == NULL) {
7748 	    if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7749 		(!xmlStrEqual(attr->name, BAD_CAST "id")))
7750 	    {
7751 		xmlSchemaPIllegalAttrErr(pctxt,
7752 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7753 	    }
7754 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7755 	    xmlSchemaPIllegalAttrErr(pctxt,
7756 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7757 	}
7758 	attr = attr->next;
7759     }
7760     /* Attribute ID */
7761     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7762     /*
7763     * And now for the children...
7764     */
7765     child = node->children;
7766     if (IS_SCHEMA(child, "annotation")) {
7767         ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7768         child = child->next;
7769     }
7770     /*
7771     * Parse contained attribute decls/refs.
7772     */
7773     if (xmlSchemaParseLocalAttributes(pctxt, schema, &child,
7774 	(xmlSchemaItemListPtr *) &(ret->attrUses),
7775 	XML_SCHEMA_TYPE_ATTRIBUTEGROUP, &hasRefs) == -1)
7776 	return(NULL);
7777     if (hasRefs)
7778 	ret->flags |= XML_SCHEMAS_ATTRGROUP_HAS_REFS;
7779     /*
7780     * Parse the attribute wildcard.
7781     */
7782     if (IS_SCHEMA(child, "anyAttribute")) {
7783 	ret->attributeWildcard = xmlSchemaParseAnyAttribute(pctxt,
7784 	    schema, child);
7785 	child = child->next;
7786     }
7787     if (child != NULL) {
7788 	xmlSchemaPContentErr(pctxt,
7789 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7790 	    NULL, node, child, NULL,
7791 	    "(annotation?, ((attribute | attributeGroup)*, anyAttribute?))");
7792     }
7793     return (ret);
7794 }
7795 
7796 /**
7797  * xmlSchemaPValAttrFormDefault:
7798  * @value:  the value
7799  * @flags: the flags to be modified
7800  * @flagQualified: the specific flag for "qualified"
7801  *
7802  * Returns 0 if the value is valid, 1 otherwise.
7803  */
7804 static int
xmlSchemaPValAttrFormDefault(const xmlChar * value,int * flags,int flagQualified)7805 xmlSchemaPValAttrFormDefault(const xmlChar *value,
7806 			     int *flags,
7807 			     int flagQualified)
7808 {
7809     if (xmlStrEqual(value, BAD_CAST "qualified")) {
7810 	if  ((*flags & flagQualified) == 0)
7811 	    *flags |= flagQualified;
7812     } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
7813 	return (1);
7814 
7815     return (0);
7816 }
7817 
7818 /**
7819  * xmlSchemaPValAttrBlockFinal:
7820  * @value:  the value
7821  * @flags: the flags to be modified
7822  * @flagAll: the specific flag for "#all"
7823  * @flagExtension: the specific flag for "extension"
7824  * @flagRestriction: the specific flag for "restriction"
7825  * @flagSubstitution: the specific flag for "substitution"
7826  * @flagList: the specific flag for "list"
7827  * @flagUnion: the specific flag for "union"
7828  *
7829  * Validates the value of the attribute "final" and "block". The value
7830  * is converted into the specified flag values and returned in @flags.
7831  *
7832  * Returns 0 if the value is valid, 1 otherwise.
7833  */
7834 
7835 static int
xmlSchemaPValAttrBlockFinal(const xmlChar * value,int * flags,int flagAll,int flagExtension,int flagRestriction,int flagSubstitution,int flagList,int flagUnion)7836 xmlSchemaPValAttrBlockFinal(const xmlChar *value,
7837 			    int *flags,
7838 			    int flagAll,
7839 			    int flagExtension,
7840 			    int flagRestriction,
7841 			    int flagSubstitution,
7842 			    int flagList,
7843 			    int flagUnion)
7844 {
7845     int ret = 0;
7846 
7847     /*
7848     * TODO: This does not check for duplicate entries.
7849     */
7850     if ((flags == NULL) || (value == NULL))
7851 	return (-1);
7852     if (value[0] == 0)
7853 	return (0);
7854     if (xmlStrEqual(value, BAD_CAST "#all")) {
7855 	if (flagAll != -1)
7856 	    *flags |= flagAll;
7857 	else {
7858 	    if (flagExtension != -1)
7859 		*flags |= flagExtension;
7860 	    if (flagRestriction != -1)
7861 		*flags |= flagRestriction;
7862 	    if (flagSubstitution != -1)
7863 		*flags |= flagSubstitution;
7864 	    if (flagList != -1)
7865 		*flags |= flagList;
7866 	    if (flagUnion != -1)
7867 		*flags |= flagUnion;
7868 	}
7869     } else {
7870 	const xmlChar *end, *cur = value;
7871 	xmlChar *item;
7872 
7873 	do {
7874 	    while (IS_BLANK_CH(*cur))
7875 		cur++;
7876 	    end = cur;
7877 	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7878 		end++;
7879 	    if (end == cur)
7880 		break;
7881 	    item = xmlStrndup(cur, end - cur);
7882 	    if (xmlStrEqual(item, BAD_CAST "extension")) {
7883 		if (flagExtension != -1) {
7884 		    if ((*flags & flagExtension) == 0)
7885 			*flags |= flagExtension;
7886 		} else
7887 		    ret = 1;
7888 	    } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
7889 		if (flagRestriction != -1) {
7890 		    if ((*flags & flagRestriction) == 0)
7891 			*flags |= flagRestriction;
7892 		} else
7893 		    ret = 1;
7894 	    } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
7895 		if (flagSubstitution != -1) {
7896 		    if ((*flags & flagSubstitution) == 0)
7897 			*flags |= flagSubstitution;
7898 		} else
7899 		    ret = 1;
7900 	    } else if (xmlStrEqual(item, BAD_CAST "list")) {
7901 		if (flagList != -1) {
7902 		    if ((*flags & flagList) == 0)
7903 			*flags |= flagList;
7904 		} else
7905 		    ret = 1;
7906 	    } else if (xmlStrEqual(item, BAD_CAST "union")) {
7907 		if (flagUnion != -1) {
7908 		    if ((*flags & flagUnion) == 0)
7909 			*flags |= flagUnion;
7910 		} else
7911 		    ret = 1;
7912 	    } else
7913 		ret = 1;
7914 	    if (item != NULL)
7915 		xmlFree(item);
7916 	    cur = end;
7917 	} while ((ret == 0) && (*cur != 0));
7918     }
7919 
7920     return (ret);
7921 }
7922 
7923 static int
xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,xmlSchemaIDCPtr idc,xmlSchemaIDCSelectPtr selector,xmlAttrPtr attr,int isField)7924 xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
7925 			     xmlSchemaIDCPtr idc,
7926 			     xmlSchemaIDCSelectPtr selector,
7927 			     xmlAttrPtr attr,
7928 			     int isField)
7929 {
7930     xmlNodePtr node;
7931 
7932     /*
7933     * c-selector-xpath:
7934     * Schema Component Constraint: Selector Value OK
7935     *
7936     * TODO: 1 The {selector} must be a valid XPath expression, as defined
7937     * in [XPath].
7938     */
7939     if (selector == NULL) {
7940 	xmlSchemaPErr(ctxt, idc->node,
7941 	    XML_SCHEMAP_INTERNAL,
7942 	    "Internal error: xmlSchemaCheckCSelectorXPath, "
7943 	    "the selector is not specified.\n", NULL, NULL);
7944 	return (-1);
7945     }
7946     if (attr == NULL)
7947 	node = idc->node;
7948     else
7949 	node = (xmlNodePtr) attr;
7950     if (selector->xpath == NULL) {
7951 	xmlSchemaPCustomErr(ctxt,
7952 	    /* TODO: Adjust error code. */
7953 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7954 	    NULL, node,
7955 	    "The XPath expression of the selector is not valid", NULL);
7956 	return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
7957     } else {
7958 	const xmlChar **nsArray = NULL;
7959 	xmlNsPtr *nsList = NULL;
7960 	/*
7961 	* Compile the XPath expression.
7962 	*/
7963 	/*
7964 	* TODO: We need the array of in-scope namespaces for compilation.
7965 	* TODO: Call xmlPatterncompile with different options for selector/
7966 	* field.
7967 	*/
7968 	if (attr == NULL)
7969 	    nsList = NULL;
7970 	else
7971 	    nsList = xmlGetNsList(attr->doc, attr->parent);
7972 	/*
7973 	* Build an array of prefixes and namespaces.
7974 	*/
7975 	if (nsList != NULL) {
7976 	    int i, count = 0;
7977 
7978 	    for (i = 0; nsList[i] != NULL; i++)
7979 		count++;
7980 
7981 	    nsArray = (const xmlChar **) xmlMalloc(
7982 		(count * 2 + 1) * sizeof(const xmlChar *));
7983 	    if (nsArray == NULL) {
7984 		xmlSchemaPErrMemory(ctxt);
7985 		xmlFree(nsList);
7986 		return (-1);
7987 	    }
7988 	    for (i = 0; i < count; i++) {
7989 		nsArray[2 * i] = nsList[i]->href;
7990 		nsArray[2 * i + 1] = nsList[i]->prefix;
7991 	    }
7992 	    nsArray[count * 2] = NULL;
7993 	    xmlFree(nsList);
7994 	}
7995 	/*
7996 	* TODO: Differentiate between "selector" and "field".
7997 	*/
7998 	if (isField)
7999 	    selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
8000 		NULL, XML_PATTERN_XSFIELD, nsArray);
8001 	else
8002 	    selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
8003 		NULL, XML_PATTERN_XSSEL, nsArray);
8004 	if (nsArray != NULL)
8005 	    xmlFree((xmlChar **) nsArray);
8006 
8007 	if (selector->xpathComp == NULL) {
8008 	    xmlSchemaPCustomErr(ctxt,
8009 		/* TODO: Adjust error code? */
8010 		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8011 		NULL, node,
8012 		"The XPath expression '%s' could not be "
8013 		"compiled", selector->xpath);
8014 	    return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
8015 	}
8016     }
8017     return (0);
8018 }
8019 
8020 #define ADD_ANNOTATION(annot)   \
8021     xmlSchemaAnnotPtr cur = item->annot; \
8022     if (item->annot == NULL) {  \
8023 	item->annot = annot;    \
8024 	return (annot);         \
8025     }                           \
8026     cur = item->annot;          \
8027     while (cur->next != NULL) { \
8028 	cur = cur->next;	\
8029     }                           \
8030     cur->next = annot;
8031 
8032 /**
8033  * xmlSchemaAssignAnnotation:
8034  * @item: the schema component
8035  * @annot: the annotation
8036  *
8037  * Adds the annotation to the given schema component.
8038  *
8039  * Returns the given annotation.
8040  */
8041 static xmlSchemaAnnotPtr
xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,xmlSchemaAnnotPtr annot)8042 xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
8043 		       xmlSchemaAnnotPtr annot)
8044 {
8045     if ((annItem == NULL) || (annot == NULL))
8046 	return (NULL);
8047     switch (annItem->type) {
8048 	case XML_SCHEMA_TYPE_ELEMENT: {
8049 		xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
8050 		ADD_ANNOTATION(annot)
8051 	    }
8052 	    break;
8053 	case XML_SCHEMA_TYPE_ATTRIBUTE: {
8054 		xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
8055 		ADD_ANNOTATION(annot)
8056 	    }
8057 	    break;
8058 	case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
8059 	case XML_SCHEMA_TYPE_ANY: {
8060 		xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
8061 		ADD_ANNOTATION(annot)
8062 	    }
8063 	    break;
8064 	case XML_SCHEMA_TYPE_PARTICLE:
8065 	case XML_SCHEMA_TYPE_IDC_KEY:
8066 	case XML_SCHEMA_TYPE_IDC_KEYREF:
8067 	case XML_SCHEMA_TYPE_IDC_UNIQUE: {
8068 		xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
8069 		ADD_ANNOTATION(annot)
8070 	    }
8071 	    break;
8072 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
8073 		xmlSchemaAttributeGroupPtr item =
8074 		    (xmlSchemaAttributeGroupPtr) annItem;
8075 		ADD_ANNOTATION(annot)
8076 	    }
8077 	    break;
8078 	case XML_SCHEMA_TYPE_NOTATION: {
8079 		xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
8080 		ADD_ANNOTATION(annot)
8081 	    }
8082 	    break;
8083 	case XML_SCHEMA_FACET_MININCLUSIVE:
8084 	case XML_SCHEMA_FACET_MINEXCLUSIVE:
8085 	case XML_SCHEMA_FACET_MAXINCLUSIVE:
8086 	case XML_SCHEMA_FACET_MAXEXCLUSIVE:
8087 	case XML_SCHEMA_FACET_TOTALDIGITS:
8088 	case XML_SCHEMA_FACET_FRACTIONDIGITS:
8089 	case XML_SCHEMA_FACET_PATTERN:
8090 	case XML_SCHEMA_FACET_ENUMERATION:
8091 	case XML_SCHEMA_FACET_WHITESPACE:
8092 	case XML_SCHEMA_FACET_LENGTH:
8093 	case XML_SCHEMA_FACET_MAXLENGTH:
8094 	case XML_SCHEMA_FACET_MINLENGTH: {
8095 		xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
8096 		ADD_ANNOTATION(annot)
8097 	    }
8098 	    break;
8099 	case XML_SCHEMA_TYPE_SIMPLE:
8100 	case XML_SCHEMA_TYPE_COMPLEX: {
8101 		xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
8102 		ADD_ANNOTATION(annot)
8103 	    }
8104 	    break;
8105 	case XML_SCHEMA_TYPE_GROUP: {
8106 		xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
8107 		ADD_ANNOTATION(annot)
8108 	    }
8109 	    break;
8110 	case XML_SCHEMA_TYPE_SEQUENCE:
8111 	case XML_SCHEMA_TYPE_CHOICE:
8112 	case XML_SCHEMA_TYPE_ALL: {
8113 		xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
8114 		ADD_ANNOTATION(annot)
8115 	    }
8116 	    break;
8117 	default:
8118 	     xmlSchemaPCustomErr(NULL,
8119 		XML_SCHEMAP_INTERNAL,
8120 		NULL, NULL,
8121 		"Internal error: xmlSchemaAddAnnotation, "
8122 		"The item is not a annotated schema component", NULL);
8123 	     break;
8124     }
8125     return (annot);
8126 }
8127 
8128 /**
8129  * xmlSchemaParseIDCSelectorAndField:
8130  * @ctxt:  a schema validation context
8131  * @schema:  the schema being built
8132  * @node:  a subtree containing XML Schema information
8133  *
8134  * Parses a XML Schema identity-constraint definition's
8135  * <selector> and <field> elements.
8136  *
8137  * Returns the parsed identity-constraint definition.
8138  */
8139 static xmlSchemaIDCSelectPtr
xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,xmlSchemaIDCPtr idc,xmlNodePtr node,int isField)8140 xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
8141 			  xmlSchemaIDCPtr idc,
8142 			  xmlNodePtr node,
8143 			  int isField)
8144 {
8145     xmlSchemaIDCSelectPtr item;
8146     xmlNodePtr child = NULL;
8147     xmlAttrPtr attr;
8148 
8149     /*
8150     * Check for illegal attributes.
8151     */
8152     attr = node->properties;
8153     while (attr != NULL) {
8154 	if (attr->ns == NULL) {
8155 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8156 		(!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
8157 		xmlSchemaPIllegalAttrErr(ctxt,
8158 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8159 	    }
8160 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8161 	    xmlSchemaPIllegalAttrErr(ctxt,
8162 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8163 	}
8164 	attr = attr->next;
8165     }
8166     /*
8167     * Create the item.
8168     */
8169     item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
8170     if (item == NULL) {
8171         xmlSchemaPErrMemory(ctxt);
8172         return (NULL);
8173     }
8174     memset(item, 0, sizeof(xmlSchemaIDCSelect));
8175     /*
8176     * Attribute "xpath" (mandatory).
8177     */
8178     attr = xmlSchemaGetPropNode(node, "xpath");
8179     if (attr == NULL) {
8180 	xmlSchemaPMissingAttrErr(ctxt,
8181 	    XML_SCHEMAP_S4S_ATTR_MISSING,
8182 	    NULL, node,
8183 	    "name", NULL);
8184     } else {
8185 	item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8186 	/*
8187 	* URGENT TODO: "field"s have an other syntax than "selector"s.
8188 	*/
8189 
8190 	if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
8191 	    isField) == -1) {
8192 	    xmlSchemaPErr(ctxt,
8193 		(xmlNodePtr) attr,
8194 		XML_SCHEMAP_INTERNAL,
8195 		"Internal error: xmlSchemaParseIDCSelectorAndField, "
8196 		"validating the XPath expression of a IDC selector.\n",
8197 		NULL, NULL);
8198 	}
8199 
8200     }
8201     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8202     /*
8203     * And now for the children...
8204     */
8205     child = node->children;
8206     if (IS_SCHEMA(child, "annotation")) {
8207 	/*
8208 	* Add the annotation to the parent IDC.
8209 	*/
8210 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
8211 	    xmlSchemaParseAnnotation(ctxt, child, 1));
8212 	child = child->next;
8213     }
8214     if (child != NULL) {
8215 	xmlSchemaPContentErr(ctxt,
8216 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8217 	    NULL, node, child,
8218 	    NULL, "(annotation?)");
8219     }
8220 
8221     return (item);
8222 }
8223 
8224 /**
8225  * xmlSchemaParseIDC:
8226  * @ctxt:  a schema validation context
8227  * @schema:  the schema being built
8228  * @node:  a subtree containing XML Schema information
8229  *
8230  * Parses a XML Schema identity-constraint definition.
8231  *
8232  * Returns the parsed identity-constraint definition.
8233  */
8234 static xmlSchemaIDCPtr
xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlSchemaTypeType idcCategory,const xmlChar * targetNamespace)8235 xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
8236 		  xmlSchemaPtr schema,
8237 		  xmlNodePtr node,
8238 		  xmlSchemaTypeType idcCategory,
8239 		  const xmlChar *targetNamespace)
8240 {
8241     xmlSchemaIDCPtr item = NULL;
8242     xmlNodePtr child = NULL;
8243     xmlAttrPtr attr;
8244     const xmlChar *name = NULL;
8245     xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
8246 
8247     /*
8248     * Check for illegal attributes.
8249     */
8250     attr = node->properties;
8251     while (attr != NULL) {
8252 	if (attr->ns == NULL) {
8253 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8254 		(!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8255 		((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
8256 		 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
8257 		xmlSchemaPIllegalAttrErr(ctxt,
8258 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8259 	    }
8260 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8261 	    xmlSchemaPIllegalAttrErr(ctxt,
8262 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8263 	}
8264 	attr = attr->next;
8265     }
8266     /*
8267     * Attribute "name" (mandatory).
8268     */
8269     attr = xmlSchemaGetPropNode(node, "name");
8270     if (attr == NULL) {
8271 	xmlSchemaPMissingAttrErr(ctxt,
8272 	    XML_SCHEMAP_S4S_ATTR_MISSING,
8273 	    NULL, node,
8274 	    "name", NULL);
8275 	return (NULL);
8276     } else if (xmlSchemaPValAttrNode(ctxt,
8277 	NULL, attr,
8278 	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8279 	return (NULL);
8280     }
8281     /* Create the component. */
8282     item = xmlSchemaAddIDC(ctxt, schema, name, targetNamespace,
8283 	idcCategory, node);
8284     if (item == NULL)
8285 	return(NULL);
8286 
8287     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8288     if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
8289 	/*
8290 	* Attribute "refer" (mandatory).
8291 	*/
8292 	attr = xmlSchemaGetPropNode(node, "refer");
8293 	if (attr == NULL) {
8294 	    xmlSchemaPMissingAttrErr(ctxt,
8295 		XML_SCHEMAP_S4S_ATTR_MISSING,
8296 		NULL, node,
8297 		"refer", NULL);
8298 	} else {
8299 	    /*
8300 	    * Create a reference item.
8301 	    */
8302 	    item->ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_IDC_KEY,
8303 		NULL, NULL);
8304 	    if (item->ref == NULL)
8305 		return (NULL);
8306 	    xmlSchemaPValAttrNodeQName(ctxt, schema,
8307 		NULL, attr,
8308 		&(item->ref->targetNamespace),
8309 		&(item->ref->name));
8310 	    xmlSchemaCheckReference(ctxt, schema, node, attr,
8311 		item->ref->targetNamespace);
8312 	}
8313     }
8314     /*
8315     * And now for the children...
8316     */
8317     child = node->children;
8318     if (IS_SCHEMA(child, "annotation")) {
8319 	item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
8320 	child = child->next;
8321     }
8322     if (child == NULL) {
8323 	xmlSchemaPContentErr(ctxt,
8324 		XML_SCHEMAP_S4S_ELEM_MISSING,
8325 		NULL, node, child,
8326 		"A child element is missing",
8327 		"(annotation?, (selector, field+))");
8328     }
8329     /*
8330     * Child element <selector>.
8331     */
8332     if (IS_SCHEMA(child, "selector")) {
8333 	item->selector = xmlSchemaParseIDCSelectorAndField(ctxt,
8334 	    item, child, 0);
8335 	child = child->next;
8336 	/*
8337 	* Child elements <field>.
8338 	*/
8339 	if (IS_SCHEMA(child, "field")) {
8340 	    do {
8341 		field = xmlSchemaParseIDCSelectorAndField(ctxt,
8342 		    item, child, 1);
8343 		if (field != NULL) {
8344 		    field->index = item->nbFields;
8345 		    item->nbFields++;
8346 		    if (lastField != NULL)
8347 			lastField->next = field;
8348 		    else
8349 			item->fields = field;
8350 		    lastField = field;
8351 		}
8352 		child = child->next;
8353 	    } while (IS_SCHEMA(child, "field"));
8354 	} else {
8355 	    xmlSchemaPContentErr(ctxt,
8356 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8357 		NULL, node, child,
8358 		NULL, "(annotation?, (selector, field+))");
8359 	}
8360     }
8361     if (child != NULL) {
8362 	xmlSchemaPContentErr(ctxt,
8363 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8364 	    NULL, node, child,
8365 	    NULL, "(annotation?, (selector, field+))");
8366     }
8367 
8368     return (item);
8369 }
8370 
8371 /**
8372  * xmlSchemaParseElement:
8373  * @ctxt:  a schema validation context
8374  * @schema:  the schema being built
8375  * @node:  a subtree containing XML Schema information
8376  * @topLevel: indicates if this is global declaration
8377  *
8378  * Parses a XML schema element declaration.
8379  * *WARNING* this interface is highly subject to change
8380  *
8381  * Returns the element declaration or a particle; NULL in case
8382  * of an error or if the particle has minOccurs==maxOccurs==0.
8383  */
8384 static xmlSchemaBasicItemPtr
xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int * isElemRef,int topLevel)8385 xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8386                       xmlNodePtr node, int *isElemRef, int topLevel)
8387 {
8388     xmlSchemaElementPtr decl = NULL;
8389     xmlSchemaParticlePtr particle = NULL;
8390     xmlSchemaAnnotPtr annot = NULL;
8391     xmlNodePtr child = NULL;
8392     xmlAttrPtr attr, nameAttr;
8393     int min, max, isRef = 0;
8394     xmlChar *des = NULL;
8395 
8396     /* 3.3.3 Constraints on XML Representations of Element Declarations */
8397     /* TODO: Complete implementation of 3.3.6 */
8398 
8399     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8400         return (NULL);
8401 
8402     if (isElemRef != NULL)
8403 	*isElemRef = 0;
8404     /*
8405     * If we get a "ref" attribute on a local <element> we will assume it's
8406     * a reference - even if there's a "name" attribute; this seems to be more
8407     * robust.
8408     */
8409     nameAttr = xmlSchemaGetPropNode(node, "name");
8410     attr = xmlSchemaGetPropNode(node, "ref");
8411     if ((topLevel) || (attr == NULL)) {
8412 	if (nameAttr == NULL) {
8413 	    xmlSchemaPMissingAttrErr(ctxt,
8414 		XML_SCHEMAP_S4S_ATTR_MISSING,
8415 		NULL, node, "name", NULL);
8416 	    return (NULL);
8417 	}
8418     } else
8419 	isRef = 1;
8420 
8421     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8422     child = node->children;
8423     if (IS_SCHEMA(child, "annotation")) {
8424 	annot = xmlSchemaParseAnnotation(ctxt, child, 1);
8425 	child = child->next;
8426     }
8427     /*
8428     * Skip particle part if a global declaration.
8429     */
8430     if (topLevel)
8431 	goto declaration_part;
8432     /*
8433     * The particle part ==================================================
8434     */
8435     min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
8436     max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
8437     xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
8438     particle = xmlSchemaAddParticle(ctxt, node, min, max);
8439     if (particle == NULL)
8440 	goto return_null;
8441 
8442     /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
8443 
8444     if (isRef) {
8445 	const xmlChar *refNs = NULL, *ref = NULL;
8446 	xmlSchemaQNameRefPtr refer = NULL;
8447 	/*
8448 	* The reference part =============================================
8449 	*/
8450 	if (isElemRef != NULL)
8451 	    *isElemRef = 1;
8452 
8453 	xmlSchemaPValAttrNodeQName(ctxt, schema,
8454 	    NULL, attr, &refNs, &ref);
8455 	xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
8456 	/*
8457 	* SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
8458 	*/
8459 	if (nameAttr != NULL) {
8460 	    xmlSchemaPMutualExclAttrErr(ctxt,
8461 		XML_SCHEMAP_SRC_ELEMENT_2_1, NULL, nameAttr, "ref", "name");
8462 	}
8463 	/*
8464 	* Check for illegal attributes.
8465 	*/
8466 	attr = node->properties;
8467 	while (attr != NULL) {
8468 	    if (attr->ns == NULL) {
8469 		if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
8470 		    xmlStrEqual(attr->name, BAD_CAST "name") ||
8471 		    xmlStrEqual(attr->name, BAD_CAST "id") ||
8472 		    xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
8473 		    xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
8474 		{
8475 		    attr = attr->next;
8476 		    continue;
8477 		} else {
8478 		    /* SPEC (3.3.3 : 2.2) */
8479 		    xmlSchemaPCustomAttrErr(ctxt,
8480 			XML_SCHEMAP_SRC_ELEMENT_2_2,
8481 			NULL, NULL, attr,
8482 			"Only the attributes 'minOccurs', 'maxOccurs' and "
8483 			"'id' are allowed in addition to 'ref'");
8484 		    break;
8485 		}
8486 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8487 		xmlSchemaPIllegalAttrErr(ctxt,
8488 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8489 	    }
8490 	    attr = attr->next;
8491 	}
8492 	/*
8493 	* No children except <annotation> expected.
8494 	*/
8495 	if (child != NULL) {
8496 	    xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8497 		NULL, node, child, NULL, "(annotation?)");
8498 	}
8499 	if ((min == 0) && (max == 0))
8500 	    goto return_null;
8501 	/*
8502 	* Create the reference item and attach it to the particle.
8503 	*/
8504 	refer = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_ELEMENT,
8505 	    ref, refNs);
8506 	if (refer == NULL)
8507 	    goto return_null;
8508 	particle->children = (xmlSchemaTreeItemPtr) refer;
8509 	particle->annot = annot;
8510 	/*
8511 	* Add the particle to pending components, since the reference
8512 	* need to be resolved.
8513 	*/
8514 	WXS_ADD_PENDING(ctxt, particle);
8515 	return ((xmlSchemaBasicItemPtr) particle);
8516     }
8517     /*
8518     * The declaration part ===============================================
8519     */
8520 declaration_part:
8521     {
8522 	const xmlChar *ns = NULL, *fixed, *name, *attrValue;
8523 	xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
8524 
8525 	if (xmlSchemaPValAttrNode(ctxt, NULL, nameAttr,
8526 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
8527 	    goto return_null;
8528 	/*
8529 	* Evaluate the target namespace.
8530 	*/
8531 	if (topLevel) {
8532 	    ns = ctxt->targetNamespace;
8533 	} else {
8534 	    attr = xmlSchemaGetPropNode(node, "form");
8535 	    if (attr != NULL) {
8536 		attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8537 		if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
8538 		    ns = ctxt->targetNamespace;
8539 		} else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
8540 		    xmlSchemaPSimpleTypeErr(ctxt,
8541 			XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8542 			NULL, (xmlNodePtr) attr,
8543 			NULL, "(qualified | unqualified)",
8544 			attrValue, NULL, NULL, NULL);
8545 		}
8546 	    } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
8547 		ns = ctxt->targetNamespace;
8548 	}
8549 	decl = xmlSchemaAddElement(ctxt, name, ns, node, topLevel);
8550 	if (decl == NULL) {
8551 	    goto return_null;
8552 	}
8553 	/*
8554 	* Check for illegal attributes.
8555 	*/
8556 	attr = node->properties;
8557 	while (attr != NULL) {
8558 	    if (attr->ns == NULL) {
8559 		if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8560 		    (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
8561 		    (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8562 		    (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
8563 		    (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
8564 		    (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
8565 		    (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
8566 		{
8567 		    if (topLevel == 0) {
8568 			if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8569 			    (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
8570 			    (!xmlStrEqual(attr->name, BAD_CAST "form")))
8571 			{
8572 			    xmlSchemaPIllegalAttrErr(ctxt,
8573 				XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8574 			}
8575 		    } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
8576 			(!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
8577 			(!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
8578 
8579 			xmlSchemaPIllegalAttrErr(ctxt,
8580 			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8581 		    }
8582 		}
8583 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8584 
8585 		xmlSchemaPIllegalAttrErr(ctxt,
8586 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8587 	    }
8588 	    attr = attr->next;
8589 	}
8590 	/*
8591 	* Extract/validate attributes.
8592 	*/
8593 	if (topLevel) {
8594 	    /*
8595 	    * Process top attributes of global element declarations here.
8596 	    */
8597 	    decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
8598 	    decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
8599 	    xmlSchemaPValAttrQName(ctxt, schema,
8600 		NULL, node, "substitutionGroup",
8601 		&(decl->substGroupNs), &(decl->substGroup));
8602 	    if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
8603 		decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
8604 	    /*
8605 	    * Attribute "final".
8606 	    */
8607 	    attr = xmlSchemaGetPropNode(node, "final");
8608 	    if (attr == NULL) {
8609 		if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8610 		    decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
8611 		if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8612 		    decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
8613 	    } else {
8614 		attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8615 		if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
8616 		    -1,
8617 		    XML_SCHEMAS_ELEM_FINAL_EXTENSION,
8618 		    XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
8619 		    xmlSchemaPSimpleTypeErr(ctxt,
8620 			XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8621 			NULL, (xmlNodePtr) attr,
8622 			NULL, "(#all | List of (extension | restriction))",
8623 			attrValue, NULL, NULL, NULL);
8624 		}
8625 	    }
8626 	}
8627 	/*
8628 	* Attribute "block".
8629 	*/
8630 	attr = xmlSchemaGetPropNode(node, "block");
8631 	if (attr == NULL) {
8632 	    /*
8633 	    * Apply default "block" values.
8634 	    */
8635 	    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8636 		decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
8637 	    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8638 		decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
8639 	    if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8640 		decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
8641 	} else {
8642 	    attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8643 	    if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
8644 		-1,
8645 		XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
8646 		XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
8647 		XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
8648 		xmlSchemaPSimpleTypeErr(ctxt,
8649 		    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8650 		    NULL, (xmlNodePtr) attr,
8651 		    NULL, "(#all | List of (extension | "
8652 		    "restriction | substitution))", attrValue,
8653 		    NULL, NULL, NULL);
8654 	    }
8655 	}
8656 	if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
8657 	    decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
8658 
8659 	attr = xmlSchemaGetPropNode(node, "type");
8660 	if (attr != NULL) {
8661 	    xmlSchemaPValAttrNodeQName(ctxt, schema,
8662 		NULL, attr,
8663 		&(decl->namedTypeNs), &(decl->namedType));
8664 	    xmlSchemaCheckReference(ctxt, schema, node,
8665 		attr, decl->namedTypeNs);
8666 	}
8667 	decl->value = xmlSchemaGetProp(ctxt, node, "default");
8668 	attr = xmlSchemaGetPropNode(node, "fixed");
8669 	if (attr != NULL) {
8670 	    fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8671 	    if (decl->value != NULL) {
8672 		/*
8673 		* 3.3.3 : 1
8674 		* default and fixed must not both be present.
8675 		*/
8676 		xmlSchemaPMutualExclAttrErr(ctxt,
8677 		    XML_SCHEMAP_SRC_ELEMENT_1,
8678 		    NULL, attr, "default", "fixed");
8679 	    } else {
8680 		decl->flags |= XML_SCHEMAS_ELEM_FIXED;
8681 		decl->value = fixed;
8682 	    }
8683 	}
8684 	/*
8685 	* And now for the children...
8686 	*/
8687 	if (IS_SCHEMA(child, "complexType")) {
8688 	    /*
8689 	    * 3.3.3 : 3
8690 	    * "type" and either <simpleType> or <complexType> are mutually
8691 	    * exclusive
8692 	    */
8693 	    if (decl->namedType != NULL) {
8694 		xmlSchemaPContentErr(ctxt,
8695 		    XML_SCHEMAP_SRC_ELEMENT_3,
8696 		    NULL, node, child,
8697 		    "The attribute 'type' and the <complexType> child are "
8698 		    "mutually exclusive", NULL);
8699 	    } else
8700 		WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
8701 	    child = child->next;
8702 	} else if (IS_SCHEMA(child, "simpleType")) {
8703 	    /*
8704 	    * 3.3.3 : 3
8705 	    * "type" and either <simpleType> or <complexType> are
8706 	    * mutually exclusive
8707 	    */
8708 	    if (decl->namedType != NULL) {
8709 		xmlSchemaPContentErr(ctxt,
8710 		    XML_SCHEMAP_SRC_ELEMENT_3,
8711 		    NULL, node, child,
8712 		    "The attribute 'type' and the <simpleType> child are "
8713 		    "mutually exclusive", NULL);
8714 	    } else
8715 		WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8716 	    child = child->next;
8717 	}
8718 	while ((IS_SCHEMA(child, "unique")) ||
8719 	    (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
8720 	    if (IS_SCHEMA(child, "unique")) {
8721 		curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8722 		    XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
8723 	    } else if (IS_SCHEMA(child, "key")) {
8724 		curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8725 		    XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
8726 	    } else if (IS_SCHEMA(child, "keyref")) {
8727 		curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8728 		    XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
8729 	    }
8730 	    if (lastIDC != NULL)
8731 		lastIDC->next = curIDC;
8732 	    else
8733 		decl->idcs = (void *) curIDC;
8734 	    lastIDC = curIDC;
8735 	    child = child->next;
8736 	}
8737 	if (child != NULL) {
8738 	    xmlSchemaPContentErr(ctxt,
8739 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8740 		NULL, node, child,
8741 		NULL, "(annotation?, ((simpleType | complexType)?, "
8742 		"(unique | key | keyref)*))");
8743 	}
8744 	decl->annot = annot;
8745     }
8746     /*
8747     * NOTE: Element Declaration Representation OK 4. will be checked at a
8748     * different layer.
8749     */
8750     FREE_AND_NULL(des)
8751     if (topLevel)
8752 	return ((xmlSchemaBasicItemPtr) decl);
8753     else {
8754 	particle->children = (xmlSchemaTreeItemPtr) decl;
8755 	return ((xmlSchemaBasicItemPtr) particle);
8756     }
8757 
8758 return_null:
8759     FREE_AND_NULL(des);
8760     if (annot != NULL) {
8761 	if (particle != NULL)
8762 	    particle->annot = NULL;
8763 	if (decl != NULL)
8764 	    decl->annot = NULL;
8765 	xmlSchemaFreeAnnot(annot);
8766     }
8767     return (NULL);
8768 }
8769 
8770 /**
8771  * xmlSchemaParseUnion:
8772  * @ctxt:  a schema validation context
8773  * @schema:  the schema being built
8774  * @node:  a subtree containing XML Schema information
8775  *
8776  * parse a XML schema Union definition
8777  * *WARNING* this interface is highly subject to change
8778  *
8779  * Returns -1 in case of internal error, 0 in case of success and a positive
8780  * error code otherwise.
8781  */
8782 static int
xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)8783 xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8784                     xmlNodePtr node)
8785 {
8786     xmlSchemaTypePtr type;
8787     xmlNodePtr child = NULL;
8788     xmlAttrPtr attr;
8789     const xmlChar *cur = NULL;
8790 
8791     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8792         return (-1);
8793     /* Not a component, don't create it. */
8794     type = ctxt->ctxtType;
8795     /*
8796     * Mark the simple type as being of variety "union".
8797     */
8798     type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
8799     /*
8800     * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
8801     * then the `simple ur-type definition`."
8802     */
8803     type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
8804     /*
8805     * Check for illegal attributes.
8806     */
8807     attr = node->properties;
8808     while (attr != NULL) {
8809 	if (attr->ns == NULL) {
8810 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8811 		(!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
8812 		xmlSchemaPIllegalAttrErr(ctxt,
8813 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8814 	    }
8815 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8816 	    xmlSchemaPIllegalAttrErr(ctxt,
8817 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8818 	}
8819 	attr = attr->next;
8820     }
8821     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8822     /*
8823     * Attribute "memberTypes". This is a list of QNames.
8824     * TODO: Check the value to contain anything.
8825     */
8826     attr = xmlSchemaGetPropNode(node, "memberTypes");
8827     if (attr != NULL) {
8828 	const xmlChar *end;
8829 	xmlChar *tmp;
8830 	const xmlChar *localName, *nsName;
8831 	xmlSchemaTypeLinkPtr link, lastLink = NULL;
8832 	xmlSchemaQNameRefPtr ref;
8833 
8834 	cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8835         if (cur == NULL)
8836             return (-1);
8837 	type->base = cur;
8838 	do {
8839 	    while (IS_BLANK_CH(*cur))
8840 		cur++;
8841 	    end = cur;
8842 	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
8843 		end++;
8844 	    if (end == cur)
8845 		break;
8846 	    tmp = xmlStrndup(cur, end - cur);
8847             if (tmp == NULL) {
8848                 xmlSchemaPErrMemory(ctxt);
8849                 return (-1);
8850             }
8851 	    if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
8852 		NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
8853 		/*
8854 		* Create the member type link.
8855 		*/
8856 		link = (xmlSchemaTypeLinkPtr)
8857 		    xmlMalloc(sizeof(xmlSchemaTypeLink));
8858 		if (link == NULL) {
8859 		    xmlSchemaPErrMemory(ctxt);
8860 	            FREE_AND_NULL(tmp)
8861 		    return (-1);
8862 		}
8863 		link->type = NULL;
8864 		link->next = NULL;
8865 		/*
8866 		* Create a reference item.
8867 		*/
8868 		ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_SIMPLE,
8869 		    localName, nsName);
8870 		if (ref == NULL) {
8871                     xmlSchemaPErrMemory(ctxt);
8872                     xmlFree(link);
8873 		    FREE_AND_NULL(tmp)
8874 		    return (-1);
8875 		}
8876 		/*
8877 		* Assign the reference to the link, it will be resolved
8878 		* later during fixup of the union simple type.
8879 		*/
8880 		link->type = (xmlSchemaTypePtr) ref;
8881 
8882 		if (lastLink == NULL)
8883 		    type->memberTypes = link;
8884 		else
8885 		    lastLink->next = link;
8886 		lastLink = link;
8887 	    }
8888 	    FREE_AND_NULL(tmp)
8889 	    cur = end;
8890 	} while (*cur != 0);
8891 
8892     }
8893     /*
8894     * And now for the children...
8895     */
8896     child = node->children;
8897     if (IS_SCHEMA(child, "annotation")) {
8898 	/*
8899 	* Add the annotation to the simple type ancestor.
8900 	*/
8901 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
8902 	    xmlSchemaParseAnnotation(ctxt, child, 1));
8903         child = child->next;
8904     }
8905     if (IS_SCHEMA(child, "simpleType")) {
8906 	xmlSchemaTypePtr subtype, last = NULL;
8907 
8908 	/*
8909 	* Anchor the member types in the "subtypes" field of the
8910 	* simple type.
8911 	*/
8912 	while (IS_SCHEMA(child, "simpleType")) {
8913 	    subtype = (xmlSchemaTypePtr)
8914 		xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8915 	    if (subtype != NULL) {
8916 		if (last == NULL) {
8917 		    type->subtypes = subtype;
8918 		    last = subtype;
8919 		} else {
8920 		    last->next = subtype;
8921 		    last = subtype;
8922 		}
8923 		last->next = NULL;
8924 	    }
8925 	    child = child->next;
8926 	}
8927     }
8928     if (child != NULL) {
8929 	xmlSchemaPContentErr(ctxt,
8930 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8931 	    NULL, node, child, NULL, "(annotation?, simpleType*)");
8932     }
8933     if ((attr == NULL) && (type->subtypes == NULL)) {
8934 	 /*
8935 	* src-union-memberTypes-or-simpleTypes
8936 	* Either the memberTypes [attribute] of the <union> element must
8937 	* be non-empty or there must be at least one simpleType [child].
8938 	*/
8939 	xmlSchemaPCustomErr(ctxt,
8940 	    XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
8941 	    NULL, node,
8942 	    "Either the attribute 'memberTypes' or "
8943 	    "at least one <simpleType> child must be present", NULL);
8944     }
8945     return (0);
8946 }
8947 
8948 /**
8949  * xmlSchemaParseList:
8950  * @ctxt:  a schema validation context
8951  * @schema:  the schema being built
8952  * @node:  a subtree containing XML Schema information
8953  *
8954  * parse a XML schema List definition
8955  * *WARNING* this interface is highly subject to change
8956  *
8957  * Returns -1 in case of error, 0 if the declaration is improper and
8958  *         1 in case of success.
8959  */
8960 static xmlSchemaTypePtr
xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)8961 xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8962                    xmlNodePtr node)
8963 {
8964     xmlSchemaTypePtr type;
8965     xmlNodePtr child = NULL;
8966     xmlAttrPtr attr;
8967 
8968     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8969         return (NULL);
8970     /* Not a component, don't create it. */
8971     type = ctxt->ctxtType;
8972     /*
8973     * Mark the type as being of variety "list".
8974     */
8975     type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
8976     /*
8977     * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
8978     * then the `simple ur-type definition`."
8979     */
8980     type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
8981     /*
8982     * Check for illegal attributes.
8983     */
8984     attr = node->properties;
8985     while (attr != NULL) {
8986 	if (attr->ns == NULL) {
8987 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8988 		(!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
8989 		xmlSchemaPIllegalAttrErr(ctxt,
8990 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8991 	    }
8992 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8993 	    xmlSchemaPIllegalAttrErr(ctxt,
8994 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8995 	}
8996 	attr = attr->next;
8997     }
8998 
8999     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9000 
9001     /*
9002     * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
9003     * fields for holding the reference to the itemType.
9004     *
9005     * REVAMP TODO: Use the "base" and "baseNs" fields, since we will remove
9006     * the "ref" fields.
9007     */
9008     xmlSchemaPValAttrQName(ctxt, schema, NULL,
9009 	node, "itemType", &(type->baseNs), &(type->base));
9010     /*
9011     * And now for the children...
9012     */
9013     child = node->children;
9014     if (IS_SCHEMA(child, "annotation")) {
9015 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9016 	    xmlSchemaParseAnnotation(ctxt, child, 1));
9017         child = child->next;
9018     }
9019     if (IS_SCHEMA(child, "simpleType")) {
9020 	/*
9021 	* src-list-itemType-or-simpleType
9022 	* Either the itemType [attribute] or the <simpleType> [child] of
9023 	* the <list> element must be present, but not both.
9024 	*/
9025 	if (type->base != NULL) {
9026 	    xmlSchemaPCustomErr(ctxt,
9027 		XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9028 		NULL, node,
9029 		"The attribute 'itemType' and the <simpleType> child "
9030 		"are mutually exclusive", NULL);
9031 	} else {
9032 	    type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
9033 	}
9034         child = child->next;
9035     } else if (type->base == NULL) {
9036 	xmlSchemaPCustomErr(ctxt,
9037 	    XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9038 	    NULL, node,
9039 	    "Either the attribute 'itemType' or the <simpleType> child "
9040 	    "must be present", NULL);
9041     }
9042     if (child != NULL) {
9043 	xmlSchemaPContentErr(ctxt,
9044 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9045 	    NULL, node, child, NULL, "(annotation?, simpleType?)");
9046     }
9047     if ((type->base == NULL) &&
9048 	(type->subtypes == NULL) &&
9049 	(xmlSchemaGetPropNode(node, "itemType") == NULL)) {
9050 	xmlSchemaPCustomErr(ctxt,
9051 	    XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9052 	    NULL, node,
9053 	    "Either the attribute 'itemType' or the <simpleType> child "
9054 	    "must be present", NULL);
9055     }
9056     return (NULL);
9057 }
9058 
9059 /**
9060  * xmlSchemaParseSimpleType:
9061  * @ctxt:  a schema validation context
9062  * @schema:  the schema being built
9063  * @node:  a subtree containing XML Schema information
9064  *
9065  * parse a XML schema Simple Type definition
9066  * *WARNING* this interface is highly subject to change
9067  *
9068  * Returns -1 in case of error, 0 if the declaration is improper and
9069  * 1 in case of success.
9070  */
9071 static xmlSchemaTypePtr
xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int topLevel)9072 xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9073                          xmlNodePtr node, int topLevel)
9074 {
9075     xmlSchemaTypePtr type, oldCtxtType;
9076     xmlNodePtr child = NULL;
9077     const xmlChar *attrValue = NULL;
9078     xmlAttrPtr attr;
9079     int hasRestriction = 0;
9080 
9081     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9082         return (NULL);
9083 
9084     if (topLevel) {
9085 	attr = xmlSchemaGetPropNode(node, "name");
9086 	if (attr == NULL) {
9087 	    xmlSchemaPMissingAttrErr(ctxt,
9088 		XML_SCHEMAP_S4S_ATTR_MISSING,
9089 		NULL, node,
9090 		"name", NULL);
9091 	    return (NULL);
9092 	} else {
9093 	    if (xmlSchemaPValAttrNode(ctxt,
9094 		NULL, attr,
9095 		xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
9096 		return (NULL);
9097 	    /*
9098 	    * Skip built-in types.
9099 	    */
9100 	    if (ctxt->isS4S) {
9101 		xmlSchemaTypePtr biType;
9102 
9103 		if (ctxt->isRedefine) {
9104 		    /*
9105 		    * REDEFINE: Disallow redefinition of built-in-types.
9106 		    * TODO: It seems that the spec does not say anything
9107 		    * about this case.
9108 		    */
9109 		    xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
9110 			NULL, node,
9111 			"Redefinition of built-in simple types is not "
9112 			"supported", NULL);
9113 		    return(NULL);
9114 		}
9115 		biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
9116 		if (biType != NULL)
9117 		    return (biType);
9118 	    }
9119 	}
9120     }
9121     /*
9122     * TargetNamespace:
9123     * SPEC "The `actual value` of the targetNamespace [attribute]
9124     * of the <schema> ancestor element information item if present,
9125     * otherwise `absent`.
9126     */
9127     if (topLevel == 0) {
9128 #ifdef ENABLE_NAMED_LOCALS
9129         char buf[40];
9130 #endif
9131 	/*
9132 	* Parse as local simple type definition.
9133 	*/
9134 #ifdef ENABLE_NAMED_LOCALS
9135         snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
9136 	type = xmlSchemaAddType(ctxt, schema,
9137 	    XML_SCHEMA_TYPE_SIMPLE,
9138 	    xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
9139 	    ctxt->targetNamespace, node, 0);
9140 #else
9141 	type = xmlSchemaAddType(ctxt, schema,
9142 	    XML_SCHEMA_TYPE_SIMPLE,
9143 	    NULL, ctxt->targetNamespace, node, 0);
9144 #endif
9145 	if (type == NULL)
9146 	    return (NULL);
9147 	type->type = XML_SCHEMA_TYPE_SIMPLE;
9148 	type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
9149 	/*
9150 	* Check for illegal attributes.
9151 	*/
9152 	attr = node->properties;
9153 	while (attr != NULL) {
9154 	    if (attr->ns == NULL) {
9155 		if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
9156 		    xmlSchemaPIllegalAttrErr(ctxt,
9157 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9158 		}
9159 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9160 		    xmlSchemaPIllegalAttrErr(ctxt,
9161 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9162 	    }
9163 	    attr = attr->next;
9164 	}
9165     } else {
9166 	/*
9167 	* Parse as global simple type definition.
9168 	*
9169 	* Note that attrValue is the value of the attribute "name" here.
9170 	*/
9171 	type = xmlSchemaAddType(ctxt, schema, XML_SCHEMA_TYPE_SIMPLE,
9172 	    attrValue, ctxt->targetNamespace, node, 1);
9173 	if (type == NULL)
9174 	    return (NULL);
9175 	type->type = XML_SCHEMA_TYPE_SIMPLE;
9176 	type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
9177 	type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
9178 	/*
9179 	* Check for illegal attributes.
9180 	*/
9181 	attr = node->properties;
9182 	while (attr != NULL) {
9183 	    if (attr->ns == NULL) {
9184 		if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9185 		    (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
9186 		    (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
9187 		    xmlSchemaPIllegalAttrErr(ctxt,
9188 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9189 		}
9190 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9191 		xmlSchemaPIllegalAttrErr(ctxt,
9192 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9193 	    }
9194 	    attr = attr->next;
9195 	}
9196 	/*
9197 	* Attribute "final".
9198 	*/
9199 	attr = xmlSchemaGetPropNode(node, "final");
9200 	if (attr == NULL) {
9201 	    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9202 		type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
9203 	    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9204 		type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
9205 	    if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9206 		type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
9207 	} else {
9208 	    attrValue = xmlSchemaGetProp(ctxt, node, "final");
9209 	    if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
9210 		-1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
9211 		XML_SCHEMAS_TYPE_FINAL_LIST,
9212 		XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
9213 
9214 		xmlSchemaPSimpleTypeErr(ctxt,
9215 		    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9216 		    WXS_BASIC_CAST type, (xmlNodePtr) attr,
9217 		    NULL, "(#all | List of (list | union | restriction)",
9218 		    attrValue, NULL, NULL, NULL);
9219 	    }
9220 	}
9221     }
9222     type->targetNamespace = ctxt->targetNamespace;
9223     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9224     /*
9225     * And now for the children...
9226     */
9227     oldCtxtType = ctxt->ctxtType;
9228 
9229     ctxt->ctxtType = type;
9230 
9231     child = node->children;
9232     if (IS_SCHEMA(child, "annotation")) {
9233         type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9234         child = child->next;
9235     }
9236     if (child == NULL) {
9237 	xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
9238 	    NULL, node, child, NULL,
9239 	    "(annotation?, (restriction | list | union))");
9240     } else if (IS_SCHEMA(child, "restriction")) {
9241         xmlSchemaParseRestriction(ctxt, schema, child,
9242 	    XML_SCHEMA_TYPE_SIMPLE);
9243 	hasRestriction = 1;
9244         child = child->next;
9245     } else if (IS_SCHEMA(child, "list")) {
9246         xmlSchemaParseList(ctxt, schema, child);
9247         child = child->next;
9248     } else if (IS_SCHEMA(child, "union")) {
9249         xmlSchemaParseUnion(ctxt, schema, child);
9250         child = child->next;
9251     }
9252     if (child != NULL) {
9253 	xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9254 	    NULL, node, child, NULL,
9255 	    "(annotation?, (restriction | list | union))");
9256     }
9257     /*
9258     * REDEFINE: SPEC src-redefine (5)
9259     * "Within the [children], each <simpleType> must have a
9260     * <restriction> among its [children] ... the `actual value` of whose
9261     * base [attribute] must be the same as the `actual value` of its own
9262     * name attribute plus target namespace;"
9263     */
9264     if (topLevel && ctxt->isRedefine && (! hasRestriction)) {
9265 	xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
9266 	    NULL, node, "This is a redefinition, thus the "
9267 	    "<simpleType> must have a <restriction> child", NULL);
9268     }
9269 
9270     ctxt->ctxtType = oldCtxtType;
9271     return (type);
9272 }
9273 
9274 /**
9275  * xmlSchemaParseModelGroupDefRef:
9276  * @ctxt:  the parser context
9277  * @schema: the schema being built
9278  * @node:  the node
9279  *
9280  * Parses a reference to a model group definition.
9281  *
9282  * We will return a particle component with a qname-component or
9283  * NULL in case of an error.
9284  */
9285 static xmlSchemaTreeItemPtr
xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)9286 xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
9287 			       xmlSchemaPtr schema,
9288 			       xmlNodePtr node)
9289 {
9290     xmlSchemaParticlePtr item;
9291     xmlNodePtr child = NULL;
9292     xmlAttrPtr attr;
9293     const xmlChar *ref = NULL, *refNs = NULL;
9294     int min, max;
9295 
9296     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9297         return (NULL);
9298 
9299     attr = xmlSchemaGetPropNode(node, "ref");
9300     if (attr == NULL) {
9301 	xmlSchemaPMissingAttrErr(ctxt,
9302 	    XML_SCHEMAP_S4S_ATTR_MISSING,
9303 	    NULL, node, "ref", NULL);
9304 	return (NULL);
9305     } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL,
9306 	attr, &refNs, &ref) != 0) {
9307 	return (NULL);
9308     }
9309     xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
9310     min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
9311     max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
9312 	"(xs:nonNegativeInteger | unbounded)");
9313     /*
9314     * Check for illegal attributes.
9315     */
9316     attr = node->properties;
9317     while (attr != NULL) {
9318 	if (attr->ns == NULL) {
9319 	    if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
9320 		(!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9321 		(!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
9322 		(!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
9323 		xmlSchemaPIllegalAttrErr(ctxt,
9324 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9325 	    }
9326 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9327 	    xmlSchemaPIllegalAttrErr(ctxt,
9328 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9329 	}
9330 	attr = attr->next;
9331     }
9332     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9333     item = xmlSchemaAddParticle(ctxt, node, min, max);
9334     if (item == NULL)
9335 	return (NULL);
9336     /*
9337     * Create a qname-reference and set as the term; it will be substituted
9338     * for the model group after the reference has been resolved.
9339     */
9340     item->children = (xmlSchemaTreeItemPtr)
9341 	xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_GROUP, ref, refNs);
9342     xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
9343     /*
9344     * And now for the children...
9345     */
9346     child = node->children;
9347     /* TODO: Is annotation even allowed for a model group reference? */
9348     if (IS_SCHEMA(child, "annotation")) {
9349 	/*
9350 	* TODO: What to do exactly with the annotation?
9351 	*/
9352 	item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9353 	child = child->next;
9354     }
9355     if (child != NULL) {
9356 	xmlSchemaPContentErr(ctxt,
9357 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9358 	    NULL, node, child, NULL,
9359 	    "(annotation?)");
9360     }
9361     /*
9362     * Corresponds to no component at all if minOccurs==maxOccurs==0.
9363     */
9364     if ((min == 0) && (max == 0))
9365 	return (NULL);
9366 
9367     return ((xmlSchemaTreeItemPtr) item);
9368 }
9369 
9370 /**
9371  * xmlSchemaParseModelGroupDefinition:
9372  * @ctxt:  a schema validation context
9373  * @schema:  the schema being built
9374  * @node:  a subtree containing XML Schema information
9375  *
9376  * Parses a XML schema model group definition.
9377  *
9378  * Note that the constraint src-redefine (6.2) can't be applied until
9379  * references have been resolved. So we will do this at the
9380  * component fixup level.
9381  *
9382  * *WARNING* this interface is highly subject to change
9383  *
9384  * Returns -1 in case of error, 0 if the declaration is improper and
9385  *         1 in case of success.
9386  */
9387 static xmlSchemaModelGroupDefPtr
xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)9388 xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
9389 				   xmlSchemaPtr schema,
9390 				   xmlNodePtr node)
9391 {
9392     xmlSchemaModelGroupDefPtr item;
9393     xmlNodePtr child = NULL;
9394     xmlAttrPtr attr;
9395     const xmlChar *name;
9396 
9397     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9398         return (NULL);
9399 
9400     attr = xmlSchemaGetPropNode(node, "name");
9401     if (attr == NULL) {
9402 	xmlSchemaPMissingAttrErr(ctxt,
9403 	    XML_SCHEMAP_S4S_ATTR_MISSING,
9404 	    NULL, node,
9405 	    "name", NULL);
9406 	return (NULL);
9407     } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
9408 	xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
9409 	return (NULL);
9410     }
9411     item = xmlSchemaAddModelGroupDefinition(ctxt, schema, name,
9412 	ctxt->targetNamespace, node);
9413     if (item == NULL)
9414 	return (NULL);
9415     /*
9416     * Check for illegal attributes.
9417     */
9418     attr = node->properties;
9419     while (attr != NULL) {
9420 	if (attr->ns == NULL) {
9421 	    if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
9422 		(!xmlStrEqual(attr->name, BAD_CAST "id"))) {
9423 		xmlSchemaPIllegalAttrErr(ctxt,
9424 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9425 	    }
9426 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9427 	    xmlSchemaPIllegalAttrErr(ctxt,
9428 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9429 	}
9430 	attr = attr->next;
9431     }
9432     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9433     /*
9434     * And now for the children...
9435     */
9436     child = node->children;
9437     if (IS_SCHEMA(child, "annotation")) {
9438 	item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9439 	child = child->next;
9440     }
9441     if (IS_SCHEMA(child, "all")) {
9442 	item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9443 	    XML_SCHEMA_TYPE_ALL, 0);
9444 	child = child->next;
9445     } else if (IS_SCHEMA(child, "choice")) {
9446 	item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9447 	    XML_SCHEMA_TYPE_CHOICE, 0);
9448 	child = child->next;
9449     } else if (IS_SCHEMA(child, "sequence")) {
9450 	item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9451 	    XML_SCHEMA_TYPE_SEQUENCE, 0);
9452 	child = child->next;
9453     }
9454 
9455 
9456 
9457     if (child != NULL) {
9458 	xmlSchemaPContentErr(ctxt,
9459 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9460 	    NULL, node, child, NULL,
9461 	    "(annotation?, (all | choice | sequence)?)");
9462     }
9463     return (item);
9464 }
9465 
9466 /**
9467  * xmlSchemaCleanupDoc:
9468  * @ctxt:  a schema validation context
9469  * @node:  the root of the document.
9470  *
9471  * removes unwanted nodes in a schemas document tree
9472  */
9473 static void
xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt,xmlNodePtr root)9474 xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
9475 {
9476     xmlNodePtr delete, cur;
9477 
9478     if ((ctxt == NULL) || (root == NULL)) return;
9479 
9480     /*
9481      * Remove all the blank text nodes
9482      */
9483     delete = NULL;
9484     cur = root;
9485     while (cur != NULL) {
9486         if (delete != NULL) {
9487             xmlUnlinkNode(delete);
9488             xmlFreeNode(delete);
9489             delete = NULL;
9490         }
9491         if (cur->type == XML_TEXT_NODE) {
9492             if (IS_BLANK_NODE(cur)) {
9493                 if (xmlNodeGetSpacePreserve(cur) != 1) {
9494                     delete = cur;
9495                 }
9496             }
9497         } else if ((cur->type != XML_ELEMENT_NODE) &&
9498                    (cur->type != XML_CDATA_SECTION_NODE)) {
9499             delete = cur;
9500             goto skip_children;
9501         }
9502 
9503         /*
9504          * Skip to next node
9505          */
9506         if (cur->children != NULL) {
9507             if ((cur->children->type != XML_ENTITY_DECL) &&
9508                 (cur->children->type != XML_ENTITY_REF_NODE) &&
9509                 (cur->children->type != XML_ENTITY_NODE)) {
9510                 cur = cur->children;
9511                 continue;
9512             }
9513         }
9514       skip_children:
9515         if (cur->next != NULL) {
9516             cur = cur->next;
9517             continue;
9518         }
9519 
9520         do {
9521             cur = cur->parent;
9522             if (cur == NULL)
9523                 break;
9524             if (cur == root) {
9525                 cur = NULL;
9526                 break;
9527             }
9528             if (cur->next != NULL) {
9529                 cur = cur->next;
9530                 break;
9531             }
9532         } while (cur != NULL);
9533     }
9534     if (delete != NULL) {
9535         xmlUnlinkNode(delete);
9536         xmlFreeNode(delete);
9537         delete = NULL;
9538     }
9539 }
9540 
9541 
9542 static void
xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)9543 xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
9544 {
9545     if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
9546 	schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
9547 
9548     if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
9549 	schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
9550 
9551     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
9552 	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
9553     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9554 	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
9555     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9556 	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
9557     if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9558 	schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
9559 
9560     if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
9561 	schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
9562     if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
9563 	schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
9564     if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
9565 	schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
9566 }
9567 
9568 static int
xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node)9569 xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt,
9570 			     xmlSchemaPtr schema,
9571 			     xmlNodePtr node)
9572 {
9573     xmlAttrPtr attr;
9574     const xmlChar *val;
9575     int res = 0, oldErrs = ctxt->nberrors;
9576 
9577     /*
9578     * Those flags should be moved to the parser context flags,
9579     * since they are not visible at the component level. I.e.
9580     * they are used if processing schema *documents* only.
9581     */
9582     res = xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9583     HFAILURE;
9584 
9585     /*
9586     * Since the version is of type xs:token, we won't bother to
9587     * check it.
9588     */
9589     /* REMOVED:
9590     attr = xmlSchemaGetPropNode(node, "version");
9591     if (attr != NULL) {
9592 	res = xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9593 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &val);
9594 	HFAILURE;
9595     }
9596     */
9597     attr = xmlSchemaGetPropNode(node, "targetNamespace");
9598     if (attr != NULL) {
9599 	res = xmlSchemaPValAttrNode(ctxt, NULL, attr,
9600 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
9601 	HFAILURE;
9602 	if (res != 0) {
9603 	    ctxt->stop = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
9604 	    goto exit;
9605 	}
9606     }
9607     attr = xmlSchemaGetPropNode(node, "elementFormDefault");
9608     if (attr != NULL) {
9609 	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9610 	res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9611 	    XML_SCHEMAS_QUALIF_ELEM);
9612 	HFAILURE;
9613 	if (res != 0) {
9614 	    xmlSchemaPSimpleTypeErr(ctxt,
9615 		XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
9616 		NULL, (xmlNodePtr) attr, NULL,
9617 		"(qualified | unqualified)", val, NULL, NULL, NULL);
9618 	}
9619     }
9620     attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
9621     if (attr != NULL) {
9622 	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9623 	res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9624 	    XML_SCHEMAS_QUALIF_ATTR);
9625 	HFAILURE;
9626 	if (res != 0) {
9627 	    xmlSchemaPSimpleTypeErr(ctxt,
9628 		XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
9629 		NULL, (xmlNodePtr) attr, NULL,
9630 		"(qualified | unqualified)", val, NULL, NULL, NULL);
9631 	}
9632     }
9633     attr = xmlSchemaGetPropNode(node, "finalDefault");
9634     if (attr != NULL) {
9635 	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9636 	res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
9637 	    XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
9638 	    XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
9639 	    -1,
9640 	    XML_SCHEMAS_FINAL_DEFAULT_LIST,
9641 	    XML_SCHEMAS_FINAL_DEFAULT_UNION);
9642 	HFAILURE;
9643 	if (res != 0) {
9644 	    xmlSchemaPSimpleTypeErr(ctxt,
9645 		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9646 		NULL, (xmlNodePtr) attr, NULL,
9647 		"(#all | List of (extension | restriction | list | union))",
9648 		val, NULL, NULL, NULL);
9649 	}
9650     }
9651     attr = xmlSchemaGetPropNode(node, "blockDefault");
9652     if (attr != NULL) {
9653 	val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9654 	res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
9655 	    XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
9656 	    XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
9657 	    XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1);
9658 	HFAILURE;
9659 	if (res != 0) {
9660 	    xmlSchemaPSimpleTypeErr(ctxt,
9661 		XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9662 		NULL, (xmlNodePtr) attr, NULL,
9663 		"(#all | List of (extension | restriction | substitution))",
9664 		val, NULL, NULL, NULL);
9665 	}
9666     }
9667 
9668 exit:
9669     if (oldErrs != ctxt->nberrors)
9670 	res = ctxt->err;
9671     return(res);
9672 exit_failure:
9673     return(-1);
9674 }
9675 
9676 /**
9677  * xmlSchemaParseSchemaTopLevel:
9678  * @ctxt:  a schema validation context
9679  * @schema:  the schemas
9680  * @nodes:  the list of top level nodes
9681  *
9682  * Returns the internal XML Schema structure built from the resource or
9683  *         NULL in case of error
9684  */
9685 static int
xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr nodes)9686 xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
9687                              xmlSchemaPtr schema, xmlNodePtr nodes)
9688 {
9689     xmlNodePtr child;
9690     xmlSchemaAnnotPtr annot;
9691     int res = 0, oldErrs, tmpOldErrs;
9692 
9693     if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
9694         return(-1);
9695 
9696     oldErrs = ctxt->nberrors;
9697     child = nodes;
9698     while ((IS_SCHEMA(child, "include")) ||
9699 	   (IS_SCHEMA(child, "import")) ||
9700 	   (IS_SCHEMA(child, "redefine")) ||
9701 	   (IS_SCHEMA(child, "annotation"))) {
9702 	if (IS_SCHEMA(child, "annotation")) {
9703 	    annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9704 	    if (schema->annot == NULL)
9705 		schema->annot = annot;
9706 	    else
9707 		xmlSchemaFreeAnnot(annot);
9708 	} else if (IS_SCHEMA(child, "import")) {
9709 	    tmpOldErrs = ctxt->nberrors;
9710 	    res = xmlSchemaParseImport(ctxt, schema, child);
9711 	    HFAILURE;
9712 	    HSTOP(ctxt);
9713 	    if (tmpOldErrs != ctxt->nberrors)
9714 		goto exit;
9715 	} else if (IS_SCHEMA(child, "include")) {
9716 	    tmpOldErrs = ctxt->nberrors;
9717 	    res = xmlSchemaParseInclude(ctxt, schema, child);
9718 	    HFAILURE;
9719 	    HSTOP(ctxt);
9720 	    if (tmpOldErrs != ctxt->nberrors)
9721 		goto exit;
9722 	} else if (IS_SCHEMA(child, "redefine")) {
9723 	    tmpOldErrs = ctxt->nberrors;
9724 	    res = xmlSchemaParseRedefine(ctxt, schema, child);
9725 	    HFAILURE;
9726 	    HSTOP(ctxt);
9727 	    if (tmpOldErrs != ctxt->nberrors)
9728 		goto exit;
9729 	}
9730 	child = child->next;
9731     }
9732     /*
9733     * URGENT TODO: Change the functions to return int results.
9734     * We need especially to catch internal errors.
9735     */
9736     while (child != NULL) {
9737 	if (IS_SCHEMA(child, "complexType")) {
9738 	    xmlSchemaParseComplexType(ctxt, schema, child, 1);
9739 	    child = child->next;
9740 	} else if (IS_SCHEMA(child, "simpleType")) {
9741 	    xmlSchemaParseSimpleType(ctxt, schema, child, 1);
9742 	    child = child->next;
9743 	} else if (IS_SCHEMA(child, "element")) {
9744 	    xmlSchemaParseElement(ctxt, schema, child, NULL, 1);
9745 	    child = child->next;
9746 	} else if (IS_SCHEMA(child, "attribute")) {
9747 	    xmlSchemaParseGlobalAttribute(ctxt, schema, child);
9748 	    child = child->next;
9749 	} else if (IS_SCHEMA(child, "attributeGroup")) {
9750 	    xmlSchemaParseAttributeGroupDefinition(ctxt, schema, child);
9751 	    child = child->next;
9752 	} else if (IS_SCHEMA(child, "group")) {
9753 	    xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
9754 	    child = child->next;
9755 	} else if (IS_SCHEMA(child, "notation")) {
9756 	    xmlSchemaParseNotation(ctxt, schema, child);
9757 	    child = child->next;
9758 	} else {
9759 	    xmlSchemaPContentErr(ctxt,
9760 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9761 		NULL, child->parent, child,
9762 		NULL, "((include | import | redefine | annotation)*, "
9763 		"(((simpleType | complexType | group | attributeGroup) "
9764 		"| element | attribute | notation), annotation*)*)");
9765 	    child = child->next;
9766 	}
9767 	while (IS_SCHEMA(child, "annotation")) {
9768 	    /*
9769 	    * TODO: We should add all annotations.
9770 	    */
9771 	    annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9772 	    if (schema->annot == NULL)
9773 		schema->annot = annot;
9774 	    else
9775 		xmlSchemaFreeAnnot(annot);
9776 	    child = child->next;
9777 	}
9778     }
9779 exit:
9780     ctxt->ctxtType = NULL;
9781     if (oldErrs != ctxt->nberrors)
9782 	res = ctxt->err;
9783     return(res);
9784 exit_failure:
9785     return(-1);
9786 }
9787 
9788 static xmlSchemaSchemaRelationPtr
xmlSchemaSchemaRelationCreate(void)9789 xmlSchemaSchemaRelationCreate(void)
9790 {
9791     xmlSchemaSchemaRelationPtr ret;
9792 
9793     ret = (xmlSchemaSchemaRelationPtr)
9794 	xmlMalloc(sizeof(xmlSchemaSchemaRelation));
9795     if (ret == NULL) {
9796 	xmlSchemaPErrMemory(NULL);
9797 	return(NULL);
9798     }
9799     memset(ret, 0, sizeof(xmlSchemaSchemaRelation));
9800     return(ret);
9801 }
9802 
9803 #if 0
9804 static void
9805 xmlSchemaSchemaRelationFree(xmlSchemaSchemaRelationPtr rel)
9806 {
9807     xmlFree(rel);
9808 }
9809 #endif
9810 
9811 static void
xmlSchemaRedefListFree(xmlSchemaRedefPtr redef)9812 xmlSchemaRedefListFree(xmlSchemaRedefPtr redef)
9813 {
9814     xmlSchemaRedefPtr prev;
9815 
9816     while (redef != NULL) {
9817 	prev = redef;
9818 	redef = redef->next;
9819 	xmlFree(prev);
9820     }
9821 }
9822 
9823 static void
xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con)9824 xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con)
9825 {
9826     /*
9827     * After the construction context has been freed, there will be
9828     * no schema graph available any more. Only the schema buckets
9829     * will stay alive, which are put into the "schemasImports" and
9830     * "includes" slots of the xmlSchema.
9831     */
9832     if (con->buckets != NULL)
9833 	xmlSchemaItemListFree(con->buckets);
9834     if (con->pending != NULL)
9835 	xmlSchemaItemListFree(con->pending);
9836     if (con->substGroups != NULL)
9837 	xmlHashFree(con->substGroups, xmlSchemaSubstGroupFreeEntry);
9838     if (con->redefs != NULL)
9839 	xmlSchemaRedefListFree(con->redefs);
9840     if (con->dict != NULL)
9841 	xmlDictFree(con->dict);
9842     xmlFree(con);
9843 }
9844 
9845 static xmlSchemaConstructionCtxtPtr
xmlSchemaConstructionCtxtCreate(xmlDictPtr dict)9846 xmlSchemaConstructionCtxtCreate(xmlDictPtr dict)
9847 {
9848     xmlSchemaConstructionCtxtPtr ret;
9849 
9850     ret = (xmlSchemaConstructionCtxtPtr)
9851 	xmlMalloc(sizeof(xmlSchemaConstructionCtxt));
9852     if (ret == NULL) {
9853         xmlSchemaPErrMemory(NULL);
9854         return (NULL);
9855     }
9856     memset(ret, 0, sizeof(xmlSchemaConstructionCtxt));
9857 
9858     ret->buckets = xmlSchemaItemListCreate();
9859     if (ret->buckets == NULL) {
9860 	xmlSchemaPErrMemory(NULL);
9861 	xmlFree(ret);
9862         return (NULL);
9863     }
9864     ret->pending = xmlSchemaItemListCreate();
9865     if (ret->pending == NULL) {
9866 	xmlSchemaPErrMemory(NULL);
9867 	xmlSchemaConstructionCtxtFree(ret);
9868         return (NULL);
9869     }
9870     ret->dict = dict;
9871     xmlDictReference(dict);
9872     return(ret);
9873 }
9874 
9875 static xmlSchemaParserCtxtPtr
xmlSchemaParserCtxtCreate(void)9876 xmlSchemaParserCtxtCreate(void)
9877 {
9878     xmlSchemaParserCtxtPtr ret;
9879 
9880     ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9881     if (ret == NULL) {
9882         xmlSchemaPErrMemory(NULL);
9883         return (NULL);
9884     }
9885     memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9886     ret->type = XML_SCHEMA_CTXT_PARSER;
9887     ret->attrProhibs = xmlSchemaItemListCreate();
9888     if (ret->attrProhibs == NULL) {
9889 	xmlFree(ret);
9890 	return(NULL);
9891     }
9892     return(ret);
9893 }
9894 
9895 /**
9896  * xmlSchemaNewParserCtxtUseDict:
9897  * @URL:  the location of the schema
9898  * @dict: the dictionary to be used
9899  *
9900  * Create an XML Schemas parse context for that file/resource expected
9901  * to contain an XML Schemas file.
9902  *
9903  * Returns the parser context or NULL in case of error
9904  */
9905 static xmlSchemaParserCtxtPtr
xmlSchemaNewParserCtxtUseDict(const char * URL,xmlDictPtr dict)9906 xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
9907 {
9908     xmlSchemaParserCtxtPtr ret;
9909 
9910     ret = xmlSchemaParserCtxtCreate();
9911     if (ret == NULL)
9912         return (NULL);
9913     ret->dict = dict;
9914     xmlDictReference(dict);
9915     if (URL != NULL)
9916 	ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
9917     return (ret);
9918 }
9919 
9920 static int
xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)9921 xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
9922 {
9923     if (vctxt->pctxt == NULL) {
9924         if (vctxt->schema != NULL)
9925 	    vctxt->pctxt =
9926 		xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
9927 	else
9928 	    vctxt->pctxt = xmlSchemaNewParserCtxt("*");
9929 	if (vctxt->pctxt == NULL) {
9930 	    VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
9931 		"failed to create a temp. parser context");
9932 	    return (-1);
9933 	}
9934 	/* TODO: Pass user data. */
9935 	xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error,
9936 	    vctxt->warning, vctxt->errCtxt);
9937 	xmlSchemaSetParserStructuredErrors(vctxt->pctxt, vctxt->serror,
9938 	    vctxt->errCtxt);
9939     }
9940     return (0);
9941 }
9942 
9943 /**
9944  * xmlSchemaGetSchemaBucket:
9945  * @pctxt: the schema parser context
9946  * @schemaLocation: the URI of the schema document
9947  *
9948  * Returns a schema bucket if it was already parsed.
9949  *
9950  * Returns a schema bucket if it was already parsed from
9951  *         @schemaLocation, NULL otherwise.
9952  */
9953 static xmlSchemaBucketPtr
xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt,const xmlChar * schemaLocation)9954 xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
9955 			    const xmlChar *schemaLocation)
9956 {
9957     xmlSchemaBucketPtr cur;
9958     xmlSchemaItemListPtr list;
9959 
9960     list = pctxt->constructor->buckets;
9961     if (list->nbItems == 0)
9962 	return(NULL);
9963     else {
9964 	int i;
9965 	for (i = 0; i < list->nbItems; i++) {
9966 	    cur = (xmlSchemaBucketPtr) list->items[i];
9967 	    /* Pointer comparison! */
9968 	    if (cur->schemaLocation == schemaLocation)
9969 		return(cur);
9970 	}
9971     }
9972     return(NULL);
9973 }
9974 
9975 static xmlSchemaBucketPtr
xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt,const xmlChar * schemaLocation,const xmlChar * targetNamespace)9976 xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
9977 				     const xmlChar *schemaLocation,
9978 				     const xmlChar *targetNamespace)
9979 {
9980     xmlSchemaBucketPtr cur;
9981     xmlSchemaItemListPtr list;
9982 
9983     list = pctxt->constructor->buckets;
9984     if (list->nbItems == 0)
9985 	return(NULL);
9986     else {
9987 	int i;
9988 	for (i = 0; i < list->nbItems; i++) {
9989 	    cur = (xmlSchemaBucketPtr) list->items[i];
9990 	    /* Pointer comparison! */
9991 	    if ((cur->origTargetNamespace == NULL) &&
9992 		(cur->schemaLocation == schemaLocation) &&
9993 		(cur->targetNamespace == targetNamespace))
9994 		return(cur);
9995 	}
9996     }
9997     return(NULL);
9998 }
9999 
10000 
10001 #define IS_BAD_SCHEMA_DOC(b) \
10002     (((b)->doc == NULL) && ((b)->schemaLocation != NULL))
10003 
10004 static xmlSchemaBucketPtr
xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt,const xmlChar * targetNamespace,int imported)10005 xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt,
10006 				 const xmlChar *targetNamespace,
10007 				 int imported)
10008 {
10009     xmlSchemaBucketPtr cur;
10010     xmlSchemaItemListPtr list;
10011 
10012     list = pctxt->constructor->buckets;
10013     if (list->nbItems == 0)
10014 	return(NULL);
10015     else {
10016 	int i;
10017 	for (i = 0; i < list->nbItems; i++) {
10018 	    cur = (xmlSchemaBucketPtr) list->items[i];
10019 	    if ((! IS_BAD_SCHEMA_DOC(cur)) &&
10020 		(cur->origTargetNamespace == targetNamespace) &&
10021 		((imported && cur->imported) ||
10022 		 ((!imported) && (!cur->imported))))
10023 		return(cur);
10024 	}
10025     }
10026     return(NULL);
10027 }
10028 
10029 static int
xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlSchemaBucketPtr bucket)10030 xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt,
10031 		     xmlSchemaPtr schema,
10032 		     xmlSchemaBucketPtr bucket)
10033 {
10034     int oldFlags;
10035     xmlDocPtr oldDoc;
10036     xmlNodePtr node;
10037     int ret, oldErrs;
10038     xmlSchemaBucketPtr oldbucket = pctxt->constructor->bucket;
10039 
10040     /*
10041     * Save old values; reset the *main* schema.
10042     * URGENT TODO: This is not good; move the per-document information
10043     * to the parser. Get rid of passing the main schema to the
10044     * parsing functions.
10045     */
10046     oldFlags = schema->flags;
10047     oldDoc = schema->doc;
10048     if (schema->flags != 0)
10049 	xmlSchemaClearSchemaDefaults(schema);
10050     schema->doc = bucket->doc;
10051     pctxt->schema = schema;
10052     /*
10053     * Keep the current target namespace on the parser *not* on the
10054     * main schema.
10055     */
10056     pctxt->targetNamespace = bucket->targetNamespace;
10057     WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
10058 
10059     if ((bucket->targetNamespace != NULL) &&
10060 	xmlStrEqual(bucket->targetNamespace, xmlSchemaNs)) {
10061 	/*
10062 	* We are parsing the schema for schemas!
10063 	*/
10064 	pctxt->isS4S = 1;
10065     }
10066     /* Mark it as parsed, even if parsing fails. */
10067     bucket->parsed++;
10068     /* Compile the schema doc. */
10069     node = xmlDocGetRootElement(bucket->doc);
10070     ret = xmlSchemaParseSchemaElement(pctxt, schema, node);
10071     if (ret != 0)
10072 	goto exit;
10073     /* An empty schema; just get out. */
10074     if (node->children == NULL)
10075 	goto exit;
10076     oldErrs = pctxt->nberrors;
10077     ret = xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
10078     if (ret != 0)
10079 	goto exit;
10080     /*
10081     * TODO: Not nice, but I'm not 100% sure we will get always an error
10082     * as a result of the above functions; so better rely on pctxt->err
10083     * as well.
10084     */
10085     if ((ret == 0) && (oldErrs != pctxt->nberrors)) {
10086 	ret = pctxt->err;
10087 	goto exit;
10088     }
10089 
10090 exit:
10091     WXS_CONSTRUCTOR(pctxt)->bucket = oldbucket;
10092     /* Restore schema values. */
10093     schema->doc = oldDoc;
10094     schema->flags = oldFlags;
10095     return(ret);
10096 }
10097 
10098 static int
xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlSchemaBucketPtr bucket)10099 xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt,
10100 		     xmlSchemaPtr schema,
10101 		     xmlSchemaBucketPtr bucket)
10102 {
10103     xmlSchemaParserCtxtPtr newpctxt;
10104     int res = 0;
10105 
10106     if (bucket == NULL)
10107 	return(0);
10108     if (bucket->parsed) {
10109 	PERROR_INT("xmlSchemaParseNewDoc",
10110 	    "reparsing a schema doc");
10111 	return(-1);
10112     }
10113     if (bucket->doc == NULL) {
10114 	PERROR_INT("xmlSchemaParseNewDoc",
10115 	    "parsing a schema doc, but there's no doc");
10116 	return(-1);
10117     }
10118     if (pctxt->constructor == NULL) {
10119 	PERROR_INT("xmlSchemaParseNewDoc",
10120 	    "no constructor");
10121 	return(-1);
10122     }
10123     /* Create and init the temporary parser context. */
10124     newpctxt = xmlSchemaNewParserCtxtUseDict(
10125 	(const char *) bucket->schemaLocation, pctxt->dict);
10126     if (newpctxt == NULL)
10127 	return(-1);
10128     newpctxt->constructor = pctxt->constructor;
10129     /*
10130     * TODO: Can we avoid that the parser knows about the main schema?
10131     * It would be better if he knows about the current schema bucket
10132     * only.
10133     */
10134     newpctxt->schema = schema;
10135     xmlSchemaSetParserErrors(newpctxt, pctxt->error, pctxt->warning,
10136 	pctxt->errCtxt);
10137     xmlSchemaSetParserStructuredErrors(newpctxt, pctxt->serror,
10138 	pctxt->errCtxt);
10139     newpctxt->counter = pctxt->counter;
10140 
10141 
10142     res = xmlSchemaParseNewDocWithContext(newpctxt, schema, bucket);
10143 
10144     /* Channel back errors and cleanup the temporary parser context. */
10145     if (res != 0)
10146 	pctxt->err = res;
10147     pctxt->nberrors += newpctxt->nberrors;
10148     pctxt->counter = newpctxt->counter;
10149     newpctxt->constructor = NULL;
10150     /* Free the parser context. */
10151     xmlSchemaFreeParserCtxt(newpctxt);
10152     return(res);
10153 }
10154 
10155 static void
xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket,xmlSchemaSchemaRelationPtr rel)10156 xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket,
10157 				xmlSchemaSchemaRelationPtr rel)
10158 {
10159     xmlSchemaSchemaRelationPtr cur = bucket->relations;
10160 
10161     if (cur == NULL) {
10162 	bucket->relations = rel;
10163 	return;
10164     }
10165     while (cur->next != NULL)
10166 	cur = cur->next;
10167     cur->next = rel;
10168 }
10169 
10170 
10171 static const xmlChar *
xmlSchemaBuildAbsoluteURI(xmlDictPtr dict,const xmlChar * location,xmlNodePtr ctxtNode)10172 xmlSchemaBuildAbsoluteURI(xmlDictPtr dict, const xmlChar* location,
10173 			  xmlNodePtr ctxtNode)
10174 {
10175     /*
10176     * Build an absolute location URI.
10177     */
10178     if (location != NULL) {
10179 	if (ctxtNode == NULL)
10180 	    return(location);
10181 	else {
10182 	    xmlChar *base, *URI;
10183 	    const xmlChar *ret = NULL;
10184 
10185 	    base = xmlNodeGetBase(ctxtNode->doc, ctxtNode);
10186 	    if (base == NULL) {
10187 		URI = xmlBuildURI(location, ctxtNode->doc->URL);
10188 	    } else {
10189 		URI = xmlBuildURI(location, base);
10190 		xmlFree(base);
10191 	    }
10192 	    if (URI != NULL) {
10193 		ret = xmlDictLookup(dict, URI, -1);
10194 		xmlFree(URI);
10195 		return(ret);
10196 	    }
10197 	}
10198     }
10199     return(NULL);
10200 }
10201 
10202 
10203 
10204 /**
10205  * xmlSchemaAddSchemaDoc:
10206  * @pctxt:  a schema validation context
10207  * @schema:  the schema being built
10208  * @node:  a subtree containing XML Schema information
10209  *
10210  * Parse an included (and to-be-redefined) XML schema document.
10211  *
10212  * Returns 0 on success, a positive error code on errors and
10213  *         -1 in case of an internal or API error.
10214  */
10215 
10216 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)10217 xmlSchemaAddSchemaDoc(xmlSchemaParserCtxtPtr pctxt,
10218 		int type, /* import or include or redefine */
10219 		const xmlChar *schemaLocation,
10220 		xmlDocPtr schemaDoc,
10221 		const char *schemaBuffer,
10222 		int schemaBufferLen,
10223 		xmlNodePtr invokingNode,
10224 		const xmlChar *sourceTargetNamespace,
10225 		const xmlChar *importNamespace,
10226 		xmlSchemaBucketPtr *bucket)
10227 {
10228     const xmlChar *targetNamespace = NULL;
10229     xmlSchemaSchemaRelationPtr relation = NULL;
10230     xmlDocPtr doc = NULL;
10231     int res = 0, err = 0, located = 0, preserveDoc = 0;
10232     xmlSchemaBucketPtr bkt = NULL;
10233 
10234     if (bucket != NULL)
10235 	*bucket = NULL;
10236 
10237     switch (type) {
10238 	case XML_SCHEMA_SCHEMA_IMPORT:
10239 	case XML_SCHEMA_SCHEMA_MAIN:
10240 	    err = XML_SCHEMAP_SRC_IMPORT;
10241 	    break;
10242 	case XML_SCHEMA_SCHEMA_INCLUDE:
10243 	    err = XML_SCHEMAP_SRC_INCLUDE;
10244 	    break;
10245 	case XML_SCHEMA_SCHEMA_REDEFINE:
10246 	    err = XML_SCHEMAP_SRC_REDEFINE;
10247 	    break;
10248     }
10249 
10250 
10251     /* Special handling for the main schema:
10252     * skip the location and relation logic and just parse the doc.
10253     * We need just a bucket to be returned in this case.
10254     */
10255     if ((type == XML_SCHEMA_SCHEMA_MAIN) || (! WXS_HAS_BUCKETS(pctxt)))
10256 	goto doc_load;
10257 
10258     /* Note that we expect the location to be an absolute URI. */
10259     if (schemaLocation != NULL) {
10260 	bkt = xmlSchemaGetSchemaBucket(pctxt, schemaLocation);
10261 	if ((bkt != NULL) &&
10262 	    (pctxt->constructor->bucket == bkt)) {
10263 	    /* Report self-imports/inclusions/redefinitions. */
10264 
10265 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10266 		invokingNode, NULL,
10267 		"The schema must not import/include/redefine itself",
10268 		NULL, NULL);
10269 	    goto exit;
10270 	}
10271     }
10272     /*
10273     * Create a relation for the graph of schemas.
10274     */
10275     relation = xmlSchemaSchemaRelationCreate();
10276     if (relation == NULL)
10277 	return(-1);
10278     xmlSchemaSchemaRelationAddChild(pctxt->constructor->bucket,
10279 	relation);
10280     relation->type = type;
10281 
10282     /*
10283     * Save the namespace import information.
10284     */
10285     if (WXS_IS_BUCKET_IMPMAIN(type)) {
10286 	relation->importNamespace = importNamespace;
10287 	if (schemaLocation == NULL) {
10288 	    /*
10289 	    * No location; this is just an import of the namespace.
10290 	    * Note that we don't assign a bucket to the relation
10291 	    * in this case.
10292 	    */
10293 	    goto exit;
10294 	}
10295 	targetNamespace = importNamespace;
10296     }
10297 
10298     /* Did we already fetch the doc? */
10299     if (bkt != NULL) {
10300 	if ((WXS_IS_BUCKET_IMPMAIN(type)) && (! bkt->imported)) {
10301 	    /*
10302 	    * We included/redefined and then try to import a schema,
10303 	    * but the new location provided for import was different.
10304 	    */
10305 	    if (schemaLocation == NULL)
10306 		schemaLocation = BAD_CAST "in_memory_buffer";
10307 	    if (!xmlStrEqual(schemaLocation,
10308 		bkt->schemaLocation)) {
10309 		xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10310 		    invokingNode, NULL,
10311 		    "The schema document '%s' cannot be imported, since "
10312 		    "it was already included or redefined",
10313 		    schemaLocation, NULL);
10314 		goto exit;
10315 	    }
10316 	} else if ((! WXS_IS_BUCKET_IMPMAIN(type)) && (bkt->imported)) {
10317 	    /*
10318 	    * We imported and then try to include/redefine a schema,
10319 	    * but the new location provided for the include/redefine
10320 	    * was different.
10321 	    */
10322 	    if (schemaLocation == NULL)
10323 		schemaLocation = BAD_CAST "in_memory_buffer";
10324 	    if (!xmlStrEqual(schemaLocation,
10325 		bkt->schemaLocation)) {
10326 		xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10327 		    invokingNode, NULL,
10328 		    "The schema document '%s' cannot be included or "
10329 		    "redefined, since it was already imported",
10330 		    schemaLocation, NULL);
10331 		goto exit;
10332 	    }
10333 	}
10334     }
10335 
10336     if (WXS_IS_BUCKET_IMPMAIN(type)) {
10337 	/*
10338 	* Given that the schemaLocation [attribute] is only a hint, it is open
10339 	* to applications to ignore all but the first <import> for a given
10340 	* namespace, regardless of the `actual value` of schemaLocation, but
10341 	* such a strategy risks missing useful information when new
10342 	* schemaLocations are offered.
10343 	*
10344 	* We will use the first <import> that comes with a location.
10345 	* Further <import>s *with* a location, will result in an error.
10346 	* TODO: Better would be to just report a warning here, but
10347 	* we'll try it this way until someone complains.
10348 	*
10349 	* Schema Document Location Strategy:
10350 	* 3 Based on the namespace name, identify an existing schema document,
10351 	* either as a resource which is an XML document or a <schema> element
10352 	* information item, in some local schema repository;
10353 	* 5 Attempt to resolve the namespace name to locate such a resource.
10354 	*
10355 	* NOTE: (3) and (5) are not supported.
10356 	*/
10357 	if (bkt != NULL) {
10358 	    relation->bucket = bkt;
10359 	    goto exit;
10360 	}
10361 	bkt = xmlSchemaGetSchemaBucketByTNS(pctxt,
10362 	    importNamespace, 1);
10363 
10364 	if (bkt != NULL) {
10365 	    relation->bucket = bkt;
10366 	    if (bkt->schemaLocation == NULL) {
10367 		/* First given location of the schema; load the doc. */
10368 		bkt->schemaLocation = schemaLocation;
10369 	    } else {
10370 		if (!xmlStrEqual(schemaLocation,
10371 		    bkt->schemaLocation)) {
10372 		    /*
10373 		    * Additional location given; just skip it.
10374 		    * URGENT TODO: We should report a warning here.
10375 		    * res = XML_SCHEMAP_SRC_IMPORT;
10376 		    */
10377 		    if (schemaLocation == NULL)
10378 			schemaLocation = BAD_CAST "in_memory_buffer";
10379 
10380 		    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10381 			XML_SCHEMAP_WARN_SKIP_SCHEMA,
10382 			invokingNode, NULL,
10383 			"Skipping import of schema located at '%s' for the "
10384 			"namespace '%s', since this namespace was already "
10385 			"imported with the schema located at '%s'",
10386 			schemaLocation, importNamespace, bkt->schemaLocation);
10387 		}
10388 		goto exit;
10389 	    }
10390 	}
10391 	/*
10392 	* No bucket + first location: load the doc and create a
10393 	* bucket.
10394 	*/
10395     } else {
10396 	/* <include> and <redefine> */
10397 	if (bkt != NULL) {
10398 
10399 	    if ((bkt->origTargetNamespace == NULL) &&
10400 		(bkt->targetNamespace != sourceTargetNamespace)) {
10401 		xmlSchemaBucketPtr chamel;
10402 
10403 		/*
10404 		* Chameleon include/redefine: skip loading only if it was
10405 		* already build for the targetNamespace of the including
10406 		* schema.
10407 		*/
10408 		/*
10409 		* URGENT TODO: If the schema is a chameleon-include then copy
10410 		* the components into the including schema and modify the
10411 		* targetNamespace of those components, do nothing otherwise.
10412 		* NOTE: This is currently worked-around by compiling the
10413 		* chameleon for every distinct including targetNamespace; thus
10414 		* not performant at the moment.
10415 		* TODO: Check when the namespace in wildcards for chameleons
10416 		* needs to be converted: before we built wildcard intersections
10417 		* or after.
10418 		*   Answer: after!
10419 		*/
10420 		chamel = xmlSchemaGetChameleonSchemaBucket(pctxt,
10421 		    schemaLocation, sourceTargetNamespace);
10422 		if (chamel != NULL) {
10423 		    /* A fitting chameleon was already parsed; NOP. */
10424 		    relation->bucket = chamel;
10425 		    goto exit;
10426 		}
10427 		/*
10428 		* We need to parse the chameleon again for a different
10429 		* targetNamespace.
10430 		* CHAMELEON TODO: Optimize this by only parsing the
10431 		* chameleon once, and then copying the components to
10432 		* the new targetNamespace.
10433 		*/
10434 		bkt = NULL;
10435 	    } else {
10436 		relation->bucket = bkt;
10437 		goto exit;
10438 	    }
10439 	}
10440     }
10441     if ((bkt != NULL) && (bkt->doc != NULL)) {
10442 	PERROR_INT("xmlSchemaAddSchemaDoc",
10443 	    "trying to load a schema doc, but a doc is already "
10444 	    "assigned to the schema bucket");
10445 	goto exit_failure;
10446     }
10447 
10448 doc_load:
10449     /*
10450     * Load the document.
10451     */
10452     if (schemaDoc != NULL) {
10453 	doc = schemaDoc;
10454 	/* Don' free this one, since it was provided by the caller. */
10455 	preserveDoc = 1;
10456 	/* TODO: Does the context or the doc hold the location? */
10457 	if (schemaDoc->URL != NULL)
10458 	    schemaLocation = xmlDictLookup(pctxt->dict,
10459 		schemaDoc->URL, -1);
10460         else
10461 	    schemaLocation = BAD_CAST "in_memory_buffer";
10462     } else if ((schemaLocation != NULL) || (schemaBuffer != NULL)) {
10463 	xmlParserCtxtPtr parserCtxt;
10464 
10465 	parserCtxt = xmlNewParserCtxt();
10466 	if (parserCtxt == NULL) {
10467 	    xmlSchemaPErrMemory(NULL);
10468 	    goto exit_failure;
10469 	}
10470 
10471         if (pctxt->serror != NULL)
10472             xmlCtxtSetErrorHandler(parserCtxt, pctxt->serror, pctxt->errCtxt);
10473         if (pctxt->resourceLoader != NULL)
10474             xmlCtxtSetResourceLoader(parserCtxt, pctxt->resourceLoader,
10475                                      pctxt->resourceCtxt);
10476 
10477 	if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
10478 	    /*
10479 	    * TODO: Do we have to burden the schema parser dict with all
10480 	    * the content of the schema doc?
10481 	    */
10482 	    xmlDictFree(parserCtxt->dict);
10483 	    parserCtxt->dict = pctxt->dict;
10484 	    xmlDictReference(parserCtxt->dict);
10485 	}
10486 	if (schemaLocation != NULL) {
10487 	    /* Parse from file. */
10488 	    doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
10489 		NULL, SCHEMAS_PARSE_OPTIONS);
10490 	} else if (schemaBuffer != NULL) {
10491 	    /* Parse from memory buffer. */
10492 	    doc = xmlCtxtReadMemory(parserCtxt, schemaBuffer, schemaBufferLen,
10493 		NULL, NULL, SCHEMAS_PARSE_OPTIONS);
10494 	    schemaLocation = BAD_CAST "in_memory_buffer";
10495 	    if (doc != NULL)
10496 		doc->URL = xmlStrdup(schemaLocation);
10497 	}
10498 	/*
10499 	* For <import>:
10500 	* 2.1 The referent is (a fragment of) a resource which is an
10501 	* XML document (see clause 1.1), which in turn corresponds to
10502 	* a <schema> element information item in a well-formed information
10503 	* set, which in turn corresponds to a valid schema.
10504 	* TODO: (2.1) fragments of XML documents are not supported.
10505 	*
10506 	* 2.2 The referent is a <schema> element information item in
10507 	* a well-formed information set, which in turn corresponds
10508 	* to a valid schema.
10509 	* TODO: (2.2) is not supported.
10510 	*/
10511 	if (doc == NULL) {
10512 	    const xmlError *lerr;
10513 	    lerr = xmlGetLastError();
10514 	    /*
10515 	    * Check if this a parser error, or if the document could
10516 	    * just not be located.
10517 	    * TODO: Try to find specific error codes to react only on
10518 	    * localisation failures.
10519 	    */
10520 	    if ((lerr == NULL) || (lerr->domain != XML_FROM_IO)) {
10521 		/*
10522 		* We assume a parser error here.
10523 		*/
10524 		located = 1;
10525 		/* TODO: Error code ?? */
10526 		res = XML_SCHEMAP_SRC_IMPORT_2_1;
10527 		xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10528 		    invokingNode, NULL,
10529 		    "Failed to parse the XML resource '%s'",
10530 		    schemaLocation, NULL);
10531 	    }
10532 	}
10533 	xmlFreeParserCtxt(parserCtxt);
10534 	if ((doc == NULL) && located)
10535 	    goto exit_error;
10536     } else {
10537 	xmlSchemaPErr(pctxt, NULL,
10538 	    XML_SCHEMAP_NOTHING_TO_PARSE,
10539 	    "No information for parsing was provided with the "
10540 	    "given schema parser context.\n",
10541 	    NULL, NULL);
10542 	goto exit_failure;
10543     }
10544     /*
10545     * Preprocess the document.
10546     */
10547     if (doc != NULL) {
10548 	xmlNodePtr docElem = NULL;
10549 
10550 	located = 1;
10551 	docElem = xmlDocGetRootElement(doc);
10552 	if (docElem == NULL) {
10553 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOROOT,
10554 		invokingNode, NULL,
10555 		"The document '%s' has no document element",
10556 		schemaLocation, NULL);
10557 	    goto exit_error;
10558 	}
10559 	/*
10560 	* Remove all the blank text nodes.
10561 	*/
10562 	xmlSchemaCleanupDoc(pctxt, docElem);
10563 	/*
10564 	* Check the schema's top level element.
10565 	*/
10566 	if (!IS_SCHEMA(docElem, "schema")) {
10567 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOT_SCHEMA,
10568 		invokingNode, NULL,
10569 		"The XML document '%s' is not a schema document",
10570 		schemaLocation, NULL);
10571 	    goto exit_error;
10572 	}
10573 	/*
10574 	* Note that we don't apply a type check for the
10575 	* targetNamespace value here.
10576 	*/
10577 	targetNamespace = xmlSchemaGetProp(pctxt, docElem,
10578 	    "targetNamespace");
10579     }
10580 
10581 /* after_doc_loading: */
10582     if ((bkt == NULL) && located) {
10583 	/* Only create a bucket if the schema was located. */
10584         bkt = xmlSchemaBucketCreate(pctxt, type,
10585 	    targetNamespace);
10586 	if (bkt == NULL)
10587 	    goto exit_failure;
10588     }
10589     if (bkt != NULL) {
10590 	bkt->schemaLocation = schemaLocation;
10591 	bkt->located = located;
10592 	if (doc != NULL) {
10593 	    bkt->doc = doc;
10594 	    bkt->targetNamespace = targetNamespace;
10595 	    bkt->origTargetNamespace = targetNamespace;
10596 	    if (preserveDoc)
10597 		bkt->preserveDoc = 1;
10598 	}
10599 	if (WXS_IS_BUCKET_IMPMAIN(type))
10600 	    bkt->imported++;
10601 	    /*
10602 	    * Add it to the graph of schemas.
10603 	    */
10604 	if (relation != NULL)
10605 	    relation->bucket = bkt;
10606     }
10607 
10608 exit:
10609     /*
10610     * Return the bucket explicitly; this is needed for the
10611     * main schema.
10612     */
10613     if (bucket != NULL)
10614 	*bucket = bkt;
10615     return (0);
10616 
10617 exit_error:
10618     if ((doc != NULL) && (! preserveDoc)) {
10619 	xmlFreeDoc(doc);
10620 	if (bkt != NULL)
10621 	    bkt->doc = NULL;
10622     }
10623     return(pctxt->err);
10624 
10625 exit_failure:
10626     if ((doc != NULL) && (! preserveDoc)) {
10627 	xmlFreeDoc(doc);
10628 	if (bkt != NULL)
10629 	    bkt->doc = NULL;
10630     }
10631     return (-1);
10632 }
10633 
10634 /**
10635  * xmlSchemaParseImport:
10636  * @ctxt:  a schema validation context
10637  * @schema:  the schema being built
10638  * @node:  a subtree containing XML Schema information
10639  *
10640  * parse a XML schema Import definition
10641  * *WARNING* this interface is highly subject to change
10642  *
10643  * Returns 0 in case of success, a positive error code if
10644  * not valid and -1 in case of an internal error.
10645  */
10646 static int
xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)10647 xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
10648                      xmlNodePtr node)
10649 {
10650     xmlNodePtr child;
10651     const xmlChar *namespaceName = NULL, *schemaLocation = NULL;
10652     const xmlChar *thisTargetNamespace;
10653     xmlAttrPtr attr;
10654     int ret = 0;
10655     xmlSchemaBucketPtr bucket = NULL;
10656 
10657     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10658         return (-1);
10659 
10660     /*
10661     * Check for illegal attributes.
10662     */
10663     attr = node->properties;
10664     while (attr != NULL) {
10665 	if (attr->ns == NULL) {
10666 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10667 		(!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
10668 		(!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10669 		xmlSchemaPIllegalAttrErr(pctxt,
10670 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10671 	    }
10672 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10673 	    xmlSchemaPIllegalAttrErr(pctxt,
10674 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10675 	}
10676 	attr = attr->next;
10677     }
10678     /*
10679     * Extract and validate attributes.
10680     */
10681     if (xmlSchemaPValAttr(pctxt, NULL, node,
10682 	"namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10683 	&namespaceName) != 0) {
10684 	xmlSchemaPSimpleTypeErr(pctxt,
10685 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10686 	    NULL, node,
10687 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10688 	    NULL, namespaceName, NULL, NULL, NULL);
10689 	return (pctxt->err);
10690     }
10691 
10692     if (xmlSchemaPValAttr(pctxt, NULL, node,
10693 	"schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10694 	&schemaLocation) != 0) {
10695 	xmlSchemaPSimpleTypeErr(pctxt,
10696 	    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10697 	    NULL, node,
10698 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10699 	    NULL, schemaLocation, NULL, NULL, NULL);
10700 	return (pctxt->err);
10701     }
10702     /*
10703     * And now for the children...
10704     */
10705     child = node->children;
10706     if (IS_SCHEMA(child, "annotation")) {
10707         /*
10708          * the annotation here is simply discarded ...
10709 	 * TODO: really?
10710          */
10711         child = child->next;
10712     }
10713     if (child != NULL) {
10714 	xmlSchemaPContentErr(pctxt,
10715 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10716 	    NULL, node, child, NULL,
10717 	    "(annotation?)");
10718     }
10719     /*
10720     * Apply additional constraints.
10721     *
10722     * Note that it is important to use the original @targetNamespace
10723     * (or none at all), to rule out imports of schemas _with_ a
10724     * @targetNamespace if the importing schema is a chameleon schema
10725     * (with no @targetNamespace).
10726     */
10727     thisTargetNamespace = WXS_BUCKET(pctxt)->origTargetNamespace;
10728     if (namespaceName != NULL) {
10729 	/*
10730 	* 1.1 If the namespace [attribute] is present, then its `actual value`
10731 	* must not match the `actual value` of the enclosing <schema>'s
10732 	* targetNamespace [attribute].
10733 	*/
10734 	if (xmlStrEqual(thisTargetNamespace, namespaceName)) {
10735 	    xmlSchemaPCustomErr(pctxt,
10736 		XML_SCHEMAP_SRC_IMPORT_1_1,
10737 		NULL, node,
10738 		"The value of the attribute 'namespace' must not match "
10739 		"the target namespace '%s' of the importing schema",
10740 		thisTargetNamespace);
10741 	    return (pctxt->err);
10742 	}
10743     } else {
10744 	/*
10745 	* 1.2 If the namespace [attribute] is not present, then the enclosing
10746 	* <schema> must have a targetNamespace [attribute].
10747 	*/
10748 	if (thisTargetNamespace == NULL) {
10749 	    xmlSchemaPCustomErr(pctxt,
10750 		XML_SCHEMAP_SRC_IMPORT_1_2,
10751 		NULL, node,
10752 		"The attribute 'namespace' must be existent if "
10753 		"the importing schema has no target namespace",
10754 		NULL);
10755 	    return (pctxt->err);
10756 	}
10757     }
10758     /*
10759     * Locate and acquire the schema document.
10760     */
10761     if (schemaLocation != NULL)
10762 	schemaLocation = xmlSchemaBuildAbsoluteURI(pctxt->dict,
10763 	    schemaLocation, node);
10764     ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
10765 	schemaLocation, NULL, NULL, 0, node, thisTargetNamespace,
10766 	namespaceName, &bucket);
10767 
10768     if (ret != 0)
10769 	return(ret);
10770 
10771     /*
10772     * For <import>: "It is *not* an error for the application
10773     * schema reference strategy to fail."
10774     * So just don't parse if no schema document was found.
10775     * Note that we will get no bucket if the schema could not be
10776     * located or if there was no schemaLocation.
10777     */
10778     if ((bucket == NULL) && (schemaLocation != NULL)) {
10779 	xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10780 	    XML_SCHEMAP_WARN_UNLOCATED_SCHEMA,
10781 	    node, NULL,
10782 	    "Failed to locate a schema at location '%s'. "
10783 	    "Skipping the import", schemaLocation, NULL, NULL);
10784     }
10785 
10786     if ((bucket != NULL) && CAN_PARSE_SCHEMA(bucket)) {
10787 	ret = xmlSchemaParseNewDoc(pctxt, schema, bucket);
10788     }
10789 
10790     return (ret);
10791 }
10792 
10793 static int
xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlChar ** schemaLocation,int type)10794 xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,
10795 				     xmlSchemaPtr schema,
10796 				     xmlNodePtr node,
10797 				     xmlChar **schemaLocation,
10798 				     int type)
10799 {
10800     xmlAttrPtr attr;
10801 
10802     if ((pctxt == NULL) || (schema == NULL) || (node == NULL) ||
10803 	(schemaLocation == NULL))
10804         return (-1);
10805 
10806     *schemaLocation = NULL;
10807     /*
10808     * Check for illegal attributes.
10809     * Applies for both <include> and <redefine>.
10810     */
10811     attr = node->properties;
10812     while (attr != NULL) {
10813 	if (attr->ns == NULL) {
10814 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10815 		(!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10816 		xmlSchemaPIllegalAttrErr(pctxt,
10817 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10818 	    }
10819 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10820 	    xmlSchemaPIllegalAttrErr(pctxt,
10821 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10822 	}
10823 	attr = attr->next;
10824     }
10825     xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
10826     /*
10827     * Preliminary step, extract the URI-Reference and make an URI
10828     * from the base.
10829     */
10830     /*
10831     * Attribute "schemaLocation" is mandatory.
10832     */
10833     attr = xmlSchemaGetPropNode(node, "schemaLocation");
10834     if (attr != NULL) {
10835         xmlChar *base = NULL;
10836         xmlChar *uri = NULL;
10837 
10838 	if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
10839 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10840 	    (const xmlChar **) schemaLocation) != 0)
10841 	    goto exit_error;
10842 	base = xmlNodeGetBase(node->doc, node);
10843 	if (base == NULL) {
10844 	    uri = xmlBuildURI(*schemaLocation, node->doc->URL);
10845 	} else {
10846 	    uri = xmlBuildURI(*schemaLocation, base);
10847 	    xmlFree(base);
10848 	}
10849 	if (uri == NULL) {
10850 	    PERROR_INT("xmlSchemaParseIncludeOrRedefine",
10851 		"could not build an URI from the schemaLocation")
10852 	    goto exit_failure;
10853 	}
10854 	(*schemaLocation) = (xmlChar *) xmlDictLookup(pctxt->dict, uri, -1);
10855 	xmlFree(uri);
10856     } else {
10857 	xmlSchemaPMissingAttrErr(pctxt,
10858 	    XML_SCHEMAP_S4S_ATTR_MISSING,
10859 	    NULL, node, "schemaLocation", NULL);
10860 	goto exit_error;
10861     }
10862     /*
10863     * Report self-inclusion and self-redefinition.
10864     */
10865     if (xmlStrEqual(*schemaLocation, pctxt->URL)) {
10866 	if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
10867 	    xmlSchemaPCustomErr(pctxt,
10868 		XML_SCHEMAP_SRC_REDEFINE,
10869 		NULL, node,
10870 		"The schema document '%s' cannot redefine itself.",
10871 		*schemaLocation);
10872 	} else {
10873 	    xmlSchemaPCustomErr(pctxt,
10874 		XML_SCHEMAP_SRC_INCLUDE,
10875 		NULL, node,
10876 		"The schema document '%s' cannot include itself.",
10877 		*schemaLocation);
10878 	}
10879 	goto exit_error;
10880     }
10881 
10882     return(0);
10883 exit_error:
10884     return(pctxt->err);
10885 exit_failure:
10886     return(-1);
10887 }
10888 
10889 static int
xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node,int type)10890 xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,
10891 				xmlSchemaPtr schema,
10892 				xmlNodePtr node,
10893 				int type)
10894 {
10895     xmlNodePtr child = NULL;
10896     const xmlChar *schemaLocation = NULL;
10897     int res = 0; /* hasRedefinitions = 0 */
10898     int isChameleon = 0, wasChameleon = 0;
10899     xmlSchemaBucketPtr bucket = NULL;
10900 
10901     if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10902         return (-1);
10903 
10904     /*
10905     * Parse attributes. Note that the returned schemaLocation will
10906     * be already converted to an absolute URI.
10907     */
10908     res = xmlSchemaParseIncludeOrRedefineAttrs(pctxt, schema,
10909 	node, (xmlChar **) (&schemaLocation), type);
10910     if (res != 0)
10911 	return(res);
10912     /*
10913     * Load and add the schema document.
10914     */
10915     res = xmlSchemaAddSchemaDoc(pctxt, type, schemaLocation, NULL,
10916 	NULL, 0, node, pctxt->targetNamespace, NULL, &bucket);
10917     if (res != 0)
10918 	return(res);
10919     /*
10920     * If we get no schema bucket back, then this means that the schema
10921     * document could not be located or was broken XML or was not
10922     * a schema document.
10923     */
10924     if ((bucket == NULL) || (bucket->doc == NULL)) {
10925 	if (type == XML_SCHEMA_SCHEMA_INCLUDE) {
10926 	    /*
10927 	    * WARNING for <include>:
10928 	    * We will raise an error if the schema cannot be located
10929 	    * for inclusions, since the that was the feedback from the
10930 	    * schema people. I.e. the following spec piece will *not* be
10931 	    * satisfied:
10932 	    * SPEC src-include: "It is not an error for the `actual value` of the
10933 	    * schemaLocation [attribute] to fail to resolve it all, in which
10934 	    * case no corresponding inclusion is performed.
10935 	    * So do we need a warning report here?"
10936 	    */
10937 	    res = XML_SCHEMAP_SRC_INCLUDE;
10938 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10939 		node, NULL,
10940 		"Failed to load the document '%s' for inclusion",
10941 		schemaLocation, NULL);
10942 	} else {
10943 	    /*
10944 	    * NOTE: This was changed to raise an error even if no redefinitions
10945 	    * are specified.
10946 	    *
10947 	    * SPEC src-redefine (1)
10948 	    * "If there are any element information items among the [children]
10949 	    * other than <annotation> then the `actual value` of the
10950 	    * schemaLocation [attribute] must successfully resolve."
10951 	    * TODO: Ask the WG if a the location has always to resolve
10952 	    * here as well!
10953 	    */
10954 	    res = XML_SCHEMAP_SRC_REDEFINE;
10955 	    xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10956 		node, NULL,
10957 		"Failed to load the document '%s' for redefinition",
10958 		schemaLocation, NULL);
10959 	}
10960     } else {
10961 	/*
10962 	* Check targetNamespace sanity before parsing the new schema.
10963 	* TODO: Note that we won't check further content if the
10964 	* targetNamespace was bad.
10965 	*/
10966 	if (bucket->origTargetNamespace != NULL) {
10967 	    /*
10968 	    * SPEC src-include (2.1)
10969 	    * "SII has a targetNamespace [attribute], and its `actual
10970 	    * value` is identical to the `actual value` of the targetNamespace
10971 	    * [attribute] of SII' (which must have such an [attribute])."
10972 	    */
10973 	    if (pctxt->targetNamespace == NULL) {
10974 		xmlSchemaCustomErr(ACTXT_CAST pctxt,
10975 		    XML_SCHEMAP_SRC_INCLUDE,
10976 		    node, NULL,
10977 		    "The target namespace of the included/redefined schema "
10978 		    "'%s' has to be absent, since the including/redefining "
10979 		    "schema has no target namespace",
10980 		    schemaLocation, NULL);
10981 		goto exit_error;
10982 	    } else if (!xmlStrEqual(bucket->origTargetNamespace,
10983 		pctxt->targetNamespace)) {
10984 		/* TODO: Change error function. */
10985 		xmlSchemaPCustomErrExt(pctxt,
10986 		    XML_SCHEMAP_SRC_INCLUDE,
10987 		    NULL, node,
10988 		    "The target namespace '%s' of the included/redefined "
10989 		    "schema '%s' differs from '%s' of the "
10990 		    "including/redefining schema",
10991 		    bucket->origTargetNamespace, schemaLocation,
10992 		    pctxt->targetNamespace);
10993 		goto exit_error;
10994 	    }
10995 	} else if (pctxt->targetNamespace != NULL) {
10996 	    /*
10997 	    * Chameleons: the original target namespace will
10998 	    * differ from the resulting namespace.
10999 	    */
11000 	    isChameleon = 1;
11001 	    bucket->targetNamespace = pctxt->targetNamespace;
11002 	}
11003     }
11004     /*
11005     * Parse the schema.
11006     */
11007     if (bucket && (!bucket->parsed) && (bucket->doc != NULL)) {
11008 	if (isChameleon) {
11009 	    /* TODO: Get rid of this flag on the schema itself. */
11010 	    if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
11011 		schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11012 	    } else
11013 		wasChameleon = 1;
11014 	}
11015 	xmlSchemaParseNewDoc(pctxt, schema, bucket);
11016 	/* Restore chameleon flag. */
11017 	if (isChameleon && (!wasChameleon))
11018 	    schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11019     }
11020     /*
11021     * And now for the children...
11022     */
11023     child = node->children;
11024     if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11025 	/*
11026 	* Parse (simpleType | complexType | group | attributeGroup))*
11027 	*/
11028 	pctxt->redefined = bucket;
11029 	/*
11030 	* How to proceed if the redefined schema was not located?
11031 	*/
11032 	pctxt->isRedefine = 1;
11033 	while (IS_SCHEMA(child, "annotation") ||
11034 	    IS_SCHEMA(child, "simpleType") ||
11035 	    IS_SCHEMA(child, "complexType") ||
11036 	    IS_SCHEMA(child, "group") ||
11037 	    IS_SCHEMA(child, "attributeGroup")) {
11038 	    if (IS_SCHEMA(child, "annotation")) {
11039 		/*
11040 		* TODO: discard or not?
11041 		*/
11042 	    } else if (IS_SCHEMA(child, "simpleType")) {
11043 		xmlSchemaParseSimpleType(pctxt, schema, child, 1);
11044 	    } else if (IS_SCHEMA(child, "complexType")) {
11045 		xmlSchemaParseComplexType(pctxt, schema, child, 1);
11046 		/* hasRedefinitions = 1; */
11047 	    } else if (IS_SCHEMA(child, "group")) {
11048 		/* hasRedefinitions = 1; */
11049 		xmlSchemaParseModelGroupDefinition(pctxt,
11050 		    schema, child);
11051 	    } else if (IS_SCHEMA(child, "attributeGroup")) {
11052 		/* hasRedefinitions = 1; */
11053 		xmlSchemaParseAttributeGroupDefinition(pctxt, schema,
11054 		    child);
11055 	    }
11056 	    child = child->next;
11057 	}
11058 	pctxt->redefined = NULL;
11059 	pctxt->isRedefine = 0;
11060     } else {
11061 	if (IS_SCHEMA(child, "annotation")) {
11062 	    /*
11063 	    * TODO: discard or not?
11064 	    */
11065 	    child = child->next;
11066 	}
11067     }
11068     if (child != NULL) {
11069 	res = XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED;
11070 	if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11071 	    xmlSchemaPContentErr(pctxt, res,
11072 		NULL, node, child, NULL,
11073 		"(annotation | (simpleType | complexType | group | attributeGroup))*");
11074 	} else {
11075 	     xmlSchemaPContentErr(pctxt, res,
11076 		NULL, node, child, NULL,
11077 		"(annotation?)");
11078 	}
11079     }
11080     return(res);
11081 
11082 exit_error:
11083     return(pctxt->err);
11084 }
11085 
11086 static int
xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)11087 xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11088                        xmlNodePtr node)
11089 {
11090     int res;
11091 #ifndef ENABLE_REDEFINE
11092     TODO
11093     return(0);
11094 #endif
11095     res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11096 	XML_SCHEMA_SCHEMA_REDEFINE);
11097     if (res != 0)
11098 	return(res);
11099     return(0);
11100 }
11101 
11102 static int
xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt,xmlSchemaPtr schema,xmlNodePtr node)11103 xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11104                        xmlNodePtr node)
11105 {
11106     int res;
11107 
11108     res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11109 	XML_SCHEMA_SCHEMA_INCLUDE);
11110     if (res != 0)
11111 	return(res);
11112     return(0);
11113 }
11114 
11115 /**
11116  * xmlSchemaParseModelGroup:
11117  * @ctxt:  a schema validation context
11118  * @schema:  the schema being built
11119  * @node:  a subtree containing XML Schema information
11120  * @type: the "compositor" type
11121  * @particleNeeded: if a a model group with a particle
11122  *
11123  * parse a XML schema Sequence definition.
11124  * Applies parts of:
11125  *   Schema Representation Constraint:
11126  *     Redefinition Constraints and Semantics (src-redefine)
11127  *     (6.1), (6.1.1), (6.1.2)
11128  *
11129  *   Schema Component Constraint:
11130  *     All Group Limited (cos-all-limited) (2)
11131  *     TODO: Actually this should go to component-level checks,
11132  *     but is done here due to performance. Move it to an other layer
11133  *     is schema construction via an API is implemented.
11134  *
11135  * *WARNING* this interface is highly subject to change
11136  *
11137  * Returns -1 in case of error, 0 if the declaration is improper and
11138  *         1 in case of success.
11139  */
11140 static xmlSchemaTreeItemPtr
xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlSchemaTypeType type,int withParticle)11141 xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11142 			 xmlNodePtr node, xmlSchemaTypeType type,
11143 			 int withParticle)
11144 {
11145     xmlSchemaModelGroupPtr item;
11146     xmlSchemaParticlePtr particle = NULL;
11147     xmlNodePtr child = NULL;
11148     xmlAttrPtr attr;
11149     int min = 1, max = 1, isElemRef, hasRefs = 0;
11150 
11151     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11152         return (NULL);
11153     /*
11154     * Create a model group with the given compositor.
11155     */
11156     item = xmlSchemaAddModelGroup(ctxt, schema, type, node);
11157     if (item == NULL)
11158 	return (NULL);
11159 
11160     if (withParticle) {
11161 	if (type == XML_SCHEMA_TYPE_ALL) {
11162 	    min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
11163 	    max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
11164 	} else {
11165 	    /* choice + sequence */
11166 	    min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
11167 	    max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
11168 		"(xs:nonNegativeInteger | unbounded)");
11169 	}
11170 	xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
11171 	/*
11172 	* Create a particle
11173 	*/
11174 	particle = xmlSchemaAddParticle(ctxt, node, min, max);
11175 	if (particle == NULL)
11176 	    return (NULL);
11177 	particle->children = (xmlSchemaTreeItemPtr) item;
11178 	/*
11179 	* Check for illegal attributes.
11180 	*/
11181 	attr = node->properties;
11182 	while (attr != NULL) {
11183 	    if (attr->ns == NULL) {
11184 		if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11185 		    (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
11186 		    (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
11187 		    xmlSchemaPIllegalAttrErr(ctxt,
11188 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11189 		}
11190 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11191 		xmlSchemaPIllegalAttrErr(ctxt,
11192 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11193 	    }
11194 	    attr = attr->next;
11195 	}
11196     } else {
11197 	/*
11198 	* Check for illegal attributes.
11199 	*/
11200 	attr = node->properties;
11201 	while (attr != NULL) {
11202 	    if (attr->ns == NULL) {
11203 		if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
11204 		    xmlSchemaPIllegalAttrErr(ctxt,
11205 			XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11206 		}
11207 	    } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11208 		xmlSchemaPIllegalAttrErr(ctxt,
11209 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11210 	    }
11211 	    attr = attr->next;
11212 	}
11213     }
11214 
11215     /*
11216     * Extract and validate attributes.
11217     */
11218     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11219     /*
11220     * And now for the children...
11221     */
11222     child = node->children;
11223     if (IS_SCHEMA(child, "annotation")) {
11224         item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
11225         child = child->next;
11226     }
11227     if (type == XML_SCHEMA_TYPE_ALL) {
11228 	xmlSchemaParticlePtr part, last = NULL;
11229 
11230 	while (IS_SCHEMA(child, "element")) {
11231 	    part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
11232 		schema, child, &isElemRef, 0);
11233 	    /*
11234 	    * SPEC cos-all-limited (2)
11235 	    * "The {max occurs} of all the particles in the {particles}
11236 	    * of the ('all') group must be 0 or 1.
11237 	    */
11238 	    if (part != NULL) {
11239 		if (isElemRef)
11240 		    hasRefs++;
11241 		if (part->minOccurs > 1) {
11242 		    xmlSchemaPCustomErr(ctxt,
11243 			XML_SCHEMAP_COS_ALL_LIMITED,
11244 			NULL, child,
11245 			"Invalid value for minOccurs (must be 0 or 1)",
11246 			NULL);
11247 		    /* Reset to 1. */
11248 		    part->minOccurs = 1;
11249 		}
11250 		if (part->maxOccurs > 1) {
11251 		    xmlSchemaPCustomErr(ctxt,
11252 			XML_SCHEMAP_COS_ALL_LIMITED,
11253 			NULL, child,
11254 			"Invalid value for maxOccurs (must be 0 or 1)",
11255 			NULL);
11256 		    /* Reset to 1. */
11257 		    part->maxOccurs = 1;
11258 		}
11259 		if (last == NULL)
11260 		    item->children = (xmlSchemaTreeItemPtr) part;
11261 		else
11262 		    last->next = (xmlSchemaTreeItemPtr) part;
11263 		last = part;
11264 	    }
11265 	    child = child->next;
11266 	}
11267 	if (child != NULL) {
11268 	    xmlSchemaPContentErr(ctxt,
11269 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11270 		NULL, node, child, NULL,
11271 		"(annotation?, (annotation?, element*)");
11272 	}
11273     } else {
11274 	/* choice + sequence */
11275 	xmlSchemaTreeItemPtr part = NULL, last = NULL;
11276 
11277 	while ((IS_SCHEMA(child, "element")) ||
11278 	    (IS_SCHEMA(child, "group")) ||
11279 	    (IS_SCHEMA(child, "any")) ||
11280 	    (IS_SCHEMA(child, "choice")) ||
11281 	    (IS_SCHEMA(child, "sequence"))) {
11282 
11283 	    if (IS_SCHEMA(child, "element")) {
11284 		part = (xmlSchemaTreeItemPtr)
11285 		    xmlSchemaParseElement(ctxt, schema, child, &isElemRef, 0);
11286 		if (part && isElemRef)
11287 		    hasRefs++;
11288 	    } else if (IS_SCHEMA(child, "group")) {
11289 		part =
11290 		    xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11291 		if (part != NULL)
11292 		    hasRefs++;
11293 		/*
11294 		* Handle redefinitions.
11295 		*/
11296 		if (ctxt->isRedefine && ctxt->redef &&
11297 		    (ctxt->redef->item->type == XML_SCHEMA_TYPE_GROUP) &&
11298 		    part && part->children)
11299 		{
11300 		    if ((xmlSchemaGetQNameRefName(part->children) ==
11301 			    ctxt->redef->refName) &&
11302 			(xmlSchemaGetQNameRefTargetNs(part->children) ==
11303 			    ctxt->redef->refTargetNs))
11304 		    {
11305 			/*
11306 			* SPEC src-redefine:
11307 			* (6.1) "If it has a <group> among its contents at
11308 			* some level the `actual value` of whose ref
11309 			* [attribute] is the same as the `actual value` of
11310 			* its own name attribute plus target namespace, then
11311 			* all of the following must be true:"
11312 			* (6.1.1) "It must have exactly one such group."
11313 			*/
11314 			if (ctxt->redefCounter != 0) {
11315 			    xmlChar *str = NULL;
11316 
11317 			    xmlSchemaCustomErr(ACTXT_CAST ctxt,
11318 				XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11319 				"The redefining model group definition "
11320 				"'%s' must not contain more than one "
11321 				"reference to the redefined definition",
11322 				xmlSchemaFormatQName(&str,
11323 				    ctxt->redef->refTargetNs,
11324 				    ctxt->redef->refName),
11325 				NULL);
11326 			    FREE_AND_NULL(str)
11327 			    part = NULL;
11328 			} else if (((WXS_PARTICLE(part))->minOccurs != 1) ||
11329 			    ((WXS_PARTICLE(part))->maxOccurs != 1))
11330 			{
11331 			    xmlChar *str = NULL;
11332 			    /*
11333 			    * SPEC src-redefine:
11334 			    * (6.1.2) "The `actual value` of both that
11335 			    * group's minOccurs and maxOccurs [attribute]
11336 			    * must be 1 (or `absent`).
11337 			    */
11338 			    xmlSchemaCustomErr(ACTXT_CAST ctxt,
11339 				XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11340 				"The redefining model group definition "
11341 				"'%s' must not contain a reference to the "
11342 				"redefined definition with a "
11343 				"maxOccurs/minOccurs other than 1",
11344 				xmlSchemaFormatQName(&str,
11345 				    ctxt->redef->refTargetNs,
11346 				    ctxt->redef->refName),
11347 				NULL);
11348 			    FREE_AND_NULL(str)
11349 			    part = NULL;
11350 			}
11351 			ctxt->redef->reference = WXS_BASIC_CAST part;
11352 			ctxt->redefCounter++;
11353 		    }
11354 		}
11355 	    } else if (IS_SCHEMA(child, "any")) {
11356 		part = (xmlSchemaTreeItemPtr)
11357 		    xmlSchemaParseAny(ctxt, schema, child);
11358 	    } else if (IS_SCHEMA(child, "choice")) {
11359 		part = xmlSchemaParseModelGroup(ctxt, schema, child,
11360 		    XML_SCHEMA_TYPE_CHOICE, 1);
11361 	    } else if (IS_SCHEMA(child, "sequence")) {
11362 		part = xmlSchemaParseModelGroup(ctxt, schema, child,
11363 		    XML_SCHEMA_TYPE_SEQUENCE, 1);
11364 	    }
11365 	    if (part != NULL) {
11366 		if (last == NULL)
11367 		    item->children = part;
11368 		else
11369 		    last->next = part;
11370 		last = part;
11371 	    }
11372 	    child = child->next;
11373 	}
11374 	if (child != NULL) {
11375 	    xmlSchemaPContentErr(ctxt,
11376 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11377 		NULL, node, child, NULL,
11378 		"(annotation?, (element | group | choice | sequence | any)*)");
11379 	}
11380     }
11381     if ((max == 0) && (min == 0))
11382 	return (NULL);
11383     if (hasRefs) {
11384 	/*
11385 	* We need to resolve references.
11386 	*/
11387 	WXS_ADD_PENDING(ctxt, item);
11388     }
11389     if (withParticle)
11390 	return ((xmlSchemaTreeItemPtr) particle);
11391     else
11392 	return ((xmlSchemaTreeItemPtr) item);
11393 }
11394 
11395 /**
11396  * xmlSchemaParseRestriction:
11397  * @ctxt:  a schema validation context
11398  * @schema:  the schema being built
11399  * @node:  a subtree containing XML Schema information
11400  *
11401  * parse a XML schema Restriction definition
11402  * *WARNING* this interface is highly subject to change
11403  *
11404  * Returns the type definition or NULL in case of error
11405  */
11406 static xmlSchemaTypePtr
xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlSchemaTypeType parentType)11407 xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11408                           xmlNodePtr node, xmlSchemaTypeType parentType)
11409 {
11410     xmlSchemaTypePtr type;
11411     xmlNodePtr child = NULL;
11412     xmlAttrPtr attr;
11413 
11414     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11415         return (NULL);
11416     /* Not a component, don't create it. */
11417     type = ctxt->ctxtType;
11418     type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
11419 
11420     /*
11421     * Check for illegal attributes.
11422     */
11423     attr = node->properties;
11424     while (attr != NULL) {
11425 	if (attr->ns == NULL) {
11426 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11427 		(!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11428 		xmlSchemaPIllegalAttrErr(ctxt,
11429 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11430 	    }
11431 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11432 	    xmlSchemaPIllegalAttrErr(ctxt,
11433 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11434 	}
11435 	attr = attr->next;
11436     }
11437     /*
11438     * Extract and validate attributes.
11439     */
11440     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11441     /*
11442     * Attribute
11443     */
11444     /*
11445     * Extract the base type. The "base" attribute is mandatory if inside
11446     * a complex type or if redefining.
11447     *
11448     * SPEC (1.2) "...otherwise (<restriction> has no <simpleType> "
11449     * among its [children]), the simple type definition which is
11450     * the {content type} of the type definition `resolved` to by
11451     * the `actual value` of the base [attribute]"
11452     */
11453     if (xmlSchemaPValAttrQName(ctxt, schema, NULL, node, "base",
11454 	&(type->baseNs), &(type->base)) == 0)
11455     {
11456 	if ((type->base == NULL) && (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
11457 	    xmlSchemaPMissingAttrErr(ctxt,
11458 		XML_SCHEMAP_S4S_ATTR_MISSING,
11459 		NULL, node, "base", NULL);
11460 	} else if ((ctxt->isRedefine) &&
11461 	    (type->flags & XML_SCHEMAS_TYPE_GLOBAL))
11462 	{
11463 	    if (type->base == NULL) {
11464 		xmlSchemaPMissingAttrErr(ctxt,
11465 		    XML_SCHEMAP_S4S_ATTR_MISSING,
11466 		    NULL, node, "base", NULL);
11467 	    } else if ((! xmlStrEqual(type->base, type->name)) ||
11468 		(! xmlStrEqual(type->baseNs, type->targetNamespace)))
11469 	    {
11470 		xmlChar *str1 = NULL, *str2 = NULL;
11471 		/*
11472 		* REDEFINE: SPEC src-redefine (5)
11473 		* "Within the [children], each <simpleType> must have a
11474 		* <restriction> among its [children] ... the `actual value` of
11475 		* whose base [attribute] must be the same as the `actual value`
11476 		* of its own name attribute plus target namespace;"
11477 		*/
11478 		xmlSchemaPCustomErrExt(ctxt, XML_SCHEMAP_SRC_REDEFINE,
11479 		    NULL, node, "This is a redefinition, but the QName "
11480 		    "value '%s' of the 'base' attribute does not match the "
11481 		    "type's designation '%s'",
11482 		    xmlSchemaFormatQName(&str1, type->baseNs, type->base),
11483 		    xmlSchemaFormatQName(&str2, type->targetNamespace,
11484 			type->name), NULL);
11485 		FREE_AND_NULL(str1);
11486 		FREE_AND_NULL(str2);
11487 		/* Avoid confusion and erase the values. */
11488 		type->base = NULL;
11489 		type->baseNs = NULL;
11490 	    }
11491 	}
11492     }
11493     /*
11494     * And now for the children...
11495     */
11496     child = node->children;
11497     if (IS_SCHEMA(child, "annotation")) {
11498 	/*
11499 	* Add the annotation to the simple type ancestor.
11500 	*/
11501 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11502 	    xmlSchemaParseAnnotation(ctxt, child, 1));
11503         child = child->next;
11504     }
11505     if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
11506 	/*
11507 	* Corresponds to <simpleType><restriction><simpleType>.
11508 	*/
11509 	if (IS_SCHEMA(child, "simpleType")) {
11510 	    if (type->base != NULL) {
11511 		/*
11512 		* src-restriction-base-or-simpleType
11513 		* Either the base [attribute] or the simpleType [child] of the
11514 		* <restriction> element must be present, but not both.
11515 		*/
11516 		xmlSchemaPContentErr(ctxt,
11517 		    XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11518 		    NULL, node, child,
11519 		    "The attribute 'base' and the <simpleType> child are "
11520 		    "mutually exclusive", NULL);
11521 	    } else {
11522 		type->baseType = (xmlSchemaTypePtr)
11523 		    xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11524 	    }
11525 	    child = child->next;
11526 	} else if (type->base == NULL) {
11527 	    xmlSchemaPContentErr(ctxt,
11528 		XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11529 		NULL, node, child,
11530 		"Either the attribute 'base' or a <simpleType> child "
11531 		"must be present", NULL);
11532 	}
11533     } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11534 	/*
11535 	* Corresponds to <complexType><complexContent><restriction>...
11536 	* followed by:
11537 	*
11538 	* Model groups <all>, <choice> and <sequence>.
11539 	*/
11540 	if (IS_SCHEMA(child, "all")) {
11541 	    type->subtypes = (xmlSchemaTypePtr)
11542 		xmlSchemaParseModelGroup(ctxt, schema, child,
11543 		    XML_SCHEMA_TYPE_ALL, 1);
11544 	    child = child->next;
11545 	} else if (IS_SCHEMA(child, "choice")) {
11546 	    type->subtypes = (xmlSchemaTypePtr)
11547 		xmlSchemaParseModelGroup(ctxt,
11548 		    schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
11549 	    child = child->next;
11550 	} else if (IS_SCHEMA(child, "sequence")) {
11551 	    type->subtypes = (xmlSchemaTypePtr)
11552 		xmlSchemaParseModelGroup(ctxt, schema, child,
11553 		    XML_SCHEMA_TYPE_SEQUENCE, 1);
11554 	    child = child->next;
11555 	/*
11556 	* Model group reference <group>.
11557 	*/
11558 	} else if (IS_SCHEMA(child, "group")) {
11559 	    type->subtypes = (xmlSchemaTypePtr)
11560 		xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11561 	    /*
11562 	    * Note that the reference will be resolved in
11563 	    * xmlSchemaResolveTypeReferences();
11564 	    */
11565 	    child = child->next;
11566 	}
11567     } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11568 	/*
11569 	* Corresponds to <complexType><simpleContent><restriction>...
11570 	*
11571 	* "1.1 the simple type definition corresponding to the <simpleType>
11572 	* among the [children] of <restriction> if there is one;"
11573 	*/
11574 	if (IS_SCHEMA(child, "simpleType")) {
11575 	    /*
11576 	    * We will store the to-be-restricted simple type in
11577 	    * type->contentTypeDef *temporarily*.
11578 	    */
11579 	    type->contentTypeDef = (xmlSchemaTypePtr)
11580 		xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11581 	    if ( type->contentTypeDef == NULL)
11582 		return (NULL);
11583 	    child = child->next;
11584 	}
11585     }
11586 
11587     if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
11588 	(parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
11589 	xmlSchemaFacetPtr facet, lastfacet = NULL;
11590 	/*
11591 	* Corresponds to <complexType><simpleContent><restriction>...
11592 	* <simpleType><restriction>...
11593 	*/
11594 
11595 	/*
11596 	* Add the facets to the simple type ancestor.
11597 	*/
11598 	/*
11599 	* TODO: Datatypes: 4.1.3 Constraints on XML Representation of
11600 	* Simple Type Definition Schema Representation Constraint:
11601 	* *Single Facet Value*
11602 	*/
11603 	while ((IS_SCHEMA(child, "minInclusive")) ||
11604 	    (IS_SCHEMA(child, "minExclusive")) ||
11605 	    (IS_SCHEMA(child, "maxInclusive")) ||
11606 	    (IS_SCHEMA(child, "maxExclusive")) ||
11607 	    (IS_SCHEMA(child, "totalDigits")) ||
11608 	    (IS_SCHEMA(child, "fractionDigits")) ||
11609 	    (IS_SCHEMA(child, "pattern")) ||
11610 	    (IS_SCHEMA(child, "enumeration")) ||
11611 	    (IS_SCHEMA(child, "whiteSpace")) ||
11612 	    (IS_SCHEMA(child, "length")) ||
11613 	    (IS_SCHEMA(child, "maxLength")) ||
11614 	    (IS_SCHEMA(child, "minLength"))) {
11615 	    facet = xmlSchemaParseFacet(ctxt, schema, child);
11616 	    if (facet != NULL) {
11617 		if (lastfacet == NULL)
11618 		    type->facets = facet;
11619 		else
11620 		    lastfacet->next = facet;
11621 		lastfacet = facet;
11622 		lastfacet->next = NULL;
11623 	    }
11624 	    child = child->next;
11625 	}
11626 	/*
11627 	* Create links for derivation and validation.
11628 	*/
11629 	if (type->facets != NULL) {
11630 	    xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
11631 
11632 	    facet = type->facets;
11633 	    do {
11634 		facetLink = (xmlSchemaFacetLinkPtr)
11635 		    xmlMalloc(sizeof(xmlSchemaFacetLink));
11636 		if (facetLink == NULL) {
11637 		    xmlSchemaPErrMemory(ctxt);
11638 		    xmlFree(facetLink);
11639 		    return (NULL);
11640 		}
11641 		facetLink->facet = facet;
11642 		facetLink->next = NULL;
11643 		if (lastFacetLink == NULL)
11644 		    type->facetSet = facetLink;
11645 		else
11646 		    lastFacetLink->next = facetLink;
11647 		lastFacetLink = facetLink;
11648 		facet = facet->next;
11649 	    } while (facet != NULL);
11650 	}
11651     }
11652     if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
11653 	/*
11654 	* Attribute uses/declarations.
11655 	*/
11656 	if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11657 	    (xmlSchemaItemListPtr *) &(type->attrUses),
11658 	    XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
11659 	    return(NULL);
11660 	/*
11661 	* Attribute wildcard.
11662 	*/
11663 	if (IS_SCHEMA(child, "anyAttribute")) {
11664 	    type->attributeWildcard =
11665 		xmlSchemaParseAnyAttribute(ctxt, schema, child);
11666 	    child = child->next;
11667 	}
11668     }
11669     if (child != NULL) {
11670 	if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11671 	    xmlSchemaPContentErr(ctxt,
11672 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11673 		NULL, node, child, NULL,
11674 		"annotation?, (group | all | choice | sequence)?, "
11675 		"((attribute | attributeGroup)*, anyAttribute?))");
11676 	} else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11677 	     xmlSchemaPContentErr(ctxt,
11678 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11679 		NULL, node, child, NULL,
11680 		"(annotation?, (simpleType?, (minExclusive | minInclusive | "
11681 		"maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11682 		"length | minLength | maxLength | enumeration | whiteSpace | "
11683 		"pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
11684 	} else {
11685 	    /* Simple type */
11686 	    xmlSchemaPContentErr(ctxt,
11687 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11688 		NULL, node, child, NULL,
11689 		"(annotation?, (simpleType?, (minExclusive | minInclusive | "
11690 		"maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11691 		"length | minLength | maxLength | enumeration | whiteSpace | "
11692 		"pattern)*))");
11693 	}
11694     }
11695     return (NULL);
11696 }
11697 
11698 /**
11699  * xmlSchemaParseExtension:
11700  * @ctxt:  a schema validation context
11701  * @schema:  the schema being built
11702  * @node:  a subtree containing XML Schema information
11703  *
11704  * Parses an <extension>, which is found inside a
11705  * <simpleContent> or <complexContent>.
11706  * *WARNING* this interface is highly subject to change.
11707  *
11708  * TODO: Returns the type definition or NULL in case of error
11709  */
11710 static xmlSchemaTypePtr
xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,xmlSchemaTypeType parentType)11711 xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11712                         xmlNodePtr node, xmlSchemaTypeType parentType)
11713 {
11714     xmlSchemaTypePtr type;
11715     xmlNodePtr child = NULL;
11716     xmlAttrPtr attr;
11717 
11718     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11719         return (NULL);
11720     /* Not a component, don't create it. */
11721     type = ctxt->ctxtType;
11722     type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
11723 
11724     /*
11725     * Check for illegal attributes.
11726     */
11727     attr = node->properties;
11728     while (attr != NULL) {
11729 	if (attr->ns == NULL) {
11730 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11731 		(!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11732 		xmlSchemaPIllegalAttrErr(ctxt,
11733 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11734 	    }
11735 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11736 	    xmlSchemaPIllegalAttrErr(ctxt,
11737 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11738 	}
11739 	attr = attr->next;
11740     }
11741 
11742     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11743 
11744     /*
11745     * Attribute "base" - mandatory.
11746     */
11747     if ((xmlSchemaPValAttrQName(ctxt, schema, NULL, node,
11748 	"base", &(type->baseNs), &(type->base)) == 0) &&
11749 	(type->base == NULL)) {
11750 	xmlSchemaPMissingAttrErr(ctxt,
11751 	    XML_SCHEMAP_S4S_ATTR_MISSING,
11752 	    NULL, node, "base", NULL);
11753     }
11754     /*
11755     * And now for the children...
11756     */
11757     child = node->children;
11758     if (IS_SCHEMA(child, "annotation")) {
11759 	/*
11760 	* Add the annotation to the type ancestor.
11761 	*/
11762 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11763 	    xmlSchemaParseAnnotation(ctxt, child, 1));
11764         child = child->next;
11765     }
11766     if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11767 	/*
11768 	* Corresponds to <complexType><complexContent><extension>... and:
11769 	*
11770 	* Model groups <all>, <choice>, <sequence> and <group>.
11771 	*/
11772 	if (IS_SCHEMA(child, "all")) {
11773 	    type->subtypes = (xmlSchemaTypePtr)
11774 		xmlSchemaParseModelGroup(ctxt, schema,
11775 		    child, XML_SCHEMA_TYPE_ALL, 1);
11776 	    child = child->next;
11777 	} else if (IS_SCHEMA(child, "choice")) {
11778 	    type->subtypes = (xmlSchemaTypePtr)
11779 		xmlSchemaParseModelGroup(ctxt, schema,
11780 		    child, XML_SCHEMA_TYPE_CHOICE, 1);
11781 	    child = child->next;
11782 	} else if (IS_SCHEMA(child, "sequence")) {
11783 	    type->subtypes = (xmlSchemaTypePtr)
11784 		xmlSchemaParseModelGroup(ctxt, schema,
11785 		child, XML_SCHEMA_TYPE_SEQUENCE, 1);
11786 	    child = child->next;
11787 	} else if (IS_SCHEMA(child, "group")) {
11788 	    type->subtypes = (xmlSchemaTypePtr)
11789 		xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11790 	    /*
11791 	    * Note that the reference will be resolved in
11792 	    * xmlSchemaResolveTypeReferences();
11793 	    */
11794 	    child = child->next;
11795 	}
11796     }
11797     if (child != NULL) {
11798 	/*
11799 	* Attribute uses/declarations.
11800 	*/
11801 	if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11802 	    (xmlSchemaItemListPtr *) &(type->attrUses),
11803 	    XML_SCHEMA_TYPE_EXTENSION, NULL) == -1)
11804 	    return(NULL);
11805 	/*
11806 	* Attribute wildcard.
11807 	*/
11808 	if (IS_SCHEMA(child, "anyAttribute")) {
11809 	    ctxt->ctxtType->attributeWildcard =
11810 		xmlSchemaParseAnyAttribute(ctxt, schema, child);
11811 	    child = child->next;
11812 	}
11813     }
11814     if (child != NULL) {
11815 	if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11816 	    /* Complex content extension. */
11817 	    xmlSchemaPContentErr(ctxt,
11818 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11819 		NULL, node, child, NULL,
11820 		"(annotation?, ((group | all | choice | sequence)?, "
11821 		"((attribute | attributeGroup)*, anyAttribute?)))");
11822 	} else {
11823 	    /* Simple content extension. */
11824 	    xmlSchemaPContentErr(ctxt,
11825 		XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11826 		NULL, node, child, NULL,
11827 		"(annotation?, ((attribute | attributeGroup)*, "
11828 		"anyAttribute?))");
11829 	}
11830     }
11831     return (NULL);
11832 }
11833 
11834 /**
11835  * xmlSchemaParseSimpleContent:
11836  * @ctxt:  a schema validation context
11837  * @schema:  the schema being built
11838  * @node:  a subtree containing XML Schema information
11839  *
11840  * parse a XML schema SimpleContent definition
11841  * *WARNING* this interface is highly subject to change
11842  *
11843  * Returns the type definition or NULL in case of error
11844  */
11845 static int
xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int * hasRestrictionOrExtension)11846 xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
11847                             xmlSchemaPtr schema, xmlNodePtr node,
11848 			    int *hasRestrictionOrExtension)
11849 {
11850     xmlSchemaTypePtr type;
11851     xmlNodePtr child = NULL;
11852     xmlAttrPtr attr;
11853 
11854     if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11855 	(hasRestrictionOrExtension == NULL))
11856         return (-1);
11857     *hasRestrictionOrExtension = 0;
11858     /* Not a component, don't create it. */
11859     type = ctxt->ctxtType;
11860     type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
11861     /*
11862     * Check for illegal attributes.
11863     */
11864     attr = node->properties;
11865     while (attr != NULL) {
11866 	if (attr->ns == NULL) {
11867 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
11868 		xmlSchemaPIllegalAttrErr(ctxt,
11869 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11870 	    }
11871 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11872 	    xmlSchemaPIllegalAttrErr(ctxt,
11873 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11874 	}
11875 	attr = attr->next;
11876     }
11877 
11878     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11879 
11880     /*
11881     * And now for the children...
11882     */
11883     child = node->children;
11884     if (IS_SCHEMA(child, "annotation")) {
11885 	/*
11886 	* Add the annotation to the complex type ancestor.
11887 	*/
11888 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11889 	    xmlSchemaParseAnnotation(ctxt, child, 1));
11890         child = child->next;
11891     }
11892     if (child == NULL) {
11893 	xmlSchemaPContentErr(ctxt,
11894 	    XML_SCHEMAP_S4S_ELEM_MISSING,
11895 	    NULL, node, NULL, NULL,
11896 	    "(annotation?, (restriction | extension))");
11897     }
11898     if (child == NULL) {
11899 	xmlSchemaPContentErr(ctxt,
11900 	    XML_SCHEMAP_S4S_ELEM_MISSING,
11901 	    NULL, node, NULL, NULL,
11902 	    "(annotation?, (restriction | extension))");
11903     }
11904     if (IS_SCHEMA(child, "restriction")) {
11905         xmlSchemaParseRestriction(ctxt, schema, child,
11906 	    XML_SCHEMA_TYPE_SIMPLE_CONTENT);
11907 	(*hasRestrictionOrExtension) = 1;
11908         child = child->next;
11909     } else if (IS_SCHEMA(child, "extension")) {
11910         xmlSchemaParseExtension(ctxt, schema, child,
11911 	    XML_SCHEMA_TYPE_SIMPLE_CONTENT);
11912 	(*hasRestrictionOrExtension) = 1;
11913         child = child->next;
11914     }
11915     if (child != NULL) {
11916 	xmlSchemaPContentErr(ctxt,
11917 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11918 	    NULL, node, child, NULL,
11919 	    "(annotation?, (restriction | extension))");
11920     }
11921     return (0);
11922 }
11923 
11924 /**
11925  * xmlSchemaParseComplexContent:
11926  * @ctxt:  a schema validation context
11927  * @schema:  the schema being built
11928  * @node:  a subtree containing XML Schema information
11929  *
11930  * parse a XML schema ComplexContent definition
11931  * *WARNING* this interface is highly subject to change
11932  *
11933  * Returns the type definition or NULL in case of error
11934  */
11935 static int
xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int * hasRestrictionOrExtension)11936 xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
11937                              xmlSchemaPtr schema, xmlNodePtr node,
11938 			     int *hasRestrictionOrExtension)
11939 {
11940     xmlSchemaTypePtr type;
11941     xmlNodePtr child = NULL;
11942     xmlAttrPtr attr;
11943 
11944     if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11945 	(hasRestrictionOrExtension == NULL))
11946         return (-1);
11947     *hasRestrictionOrExtension = 0;
11948     /* Not a component, don't create it. */
11949     type = ctxt->ctxtType;
11950     /*
11951     * Check for illegal attributes.
11952     */
11953     attr = node->properties;
11954     while (attr != NULL) {
11955 	if (attr->ns == NULL) {
11956 	    if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11957 		(!xmlStrEqual(attr->name, BAD_CAST "mixed")))
11958 	    {
11959 		xmlSchemaPIllegalAttrErr(ctxt,
11960 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11961 	    }
11962 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11963 	    xmlSchemaPIllegalAttrErr(ctxt,
11964 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11965 	}
11966 	attr = attr->next;
11967     }
11968 
11969     xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11970 
11971     /*
11972     * Set the 'mixed' on the complex type ancestor.
11973     */
11974     if (xmlGetBooleanProp(ctxt, node, "mixed", 0))  {
11975 	if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
11976 	    type->flags |= XML_SCHEMAS_TYPE_MIXED;
11977     }
11978     child = node->children;
11979     if (IS_SCHEMA(child, "annotation")) {
11980 	/*
11981 	* Add the annotation to the complex type ancestor.
11982 	*/
11983 	xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11984 	    xmlSchemaParseAnnotation(ctxt, child, 1));
11985         child = child->next;
11986     }
11987     if (child == NULL) {
11988 	xmlSchemaPContentErr(ctxt,
11989 	    XML_SCHEMAP_S4S_ELEM_MISSING,
11990 	    NULL, node, NULL,
11991 	    NULL, "(annotation?, (restriction | extension))");
11992     }
11993     if (child == NULL) {
11994 	xmlSchemaPContentErr(ctxt,
11995 	    XML_SCHEMAP_S4S_ELEM_MISSING,
11996 	    NULL, node, NULL,
11997 	    NULL, "(annotation?, (restriction | extension))");
11998     }
11999     if (IS_SCHEMA(child, "restriction")) {
12000         xmlSchemaParseRestriction(ctxt, schema, child,
12001 	    XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12002 	(*hasRestrictionOrExtension) = 1;
12003         child = child->next;
12004     } else if (IS_SCHEMA(child, "extension")) {
12005         xmlSchemaParseExtension(ctxt, schema, child,
12006 	    XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12007 	(*hasRestrictionOrExtension) = 1;
12008         child = child->next;
12009     }
12010     if (child != NULL) {
12011 	xmlSchemaPContentErr(ctxt,
12012 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12013 	    NULL, node, child,
12014 	    NULL, "(annotation?, (restriction | extension))");
12015     }
12016     return (0);
12017 }
12018 
12019 /**
12020  * xmlSchemaParseComplexType:
12021  * @ctxt:  a schema validation context
12022  * @schema:  the schema being built
12023  * @node:  a subtree containing XML Schema information
12024  *
12025  * parse a XML schema Complex Type definition
12026  * *WARNING* this interface is highly subject to change
12027  *
12028  * Returns the type definition or NULL in case of error
12029  */
12030 static xmlSchemaTypePtr
xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt,xmlSchemaPtr schema,xmlNodePtr node,int topLevel)12031 xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
12032                           xmlNodePtr node, int topLevel)
12033 {
12034     xmlSchemaTypePtr type, ctxtType;
12035     xmlNodePtr child = NULL;
12036     const xmlChar *name = NULL;
12037     xmlAttrPtr attr;
12038     const xmlChar *attrValue;
12039 #ifdef ENABLE_NAMED_LOCALS
12040     char buf[40];
12041 #endif
12042     int final = 0, block = 0, hasRestrictionOrExtension = 0;
12043 
12044 
12045     if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
12046         return (NULL);
12047 
12048     ctxtType = ctxt->ctxtType;
12049 
12050     if (topLevel) {
12051 	attr = xmlSchemaGetPropNode(node, "name");
12052 	if (attr == NULL) {
12053 	    xmlSchemaPMissingAttrErr(ctxt,
12054 		XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
12055 	    return (NULL);
12056 	} else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
12057 	    xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
12058 	    return (NULL);
12059 	}
12060     }
12061 
12062     if (topLevel == 0) {
12063 	/*
12064 	* Parse as local complex type definition.
12065 	*/
12066 #ifdef ENABLE_NAMED_LOCALS
12067         snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
12068 	type = xmlSchemaAddType(ctxt, schema,
12069 	    XML_SCHEMA_TYPE_COMPLEX,
12070 	    xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
12071 	    ctxt->targetNamespace, node, 0);
12072 #else
12073 	type = xmlSchemaAddType(ctxt, schema,
12074 	    XML_SCHEMA_TYPE_COMPLEX,
12075 	    NULL, ctxt->targetNamespace, node, 0);
12076 #endif
12077 	if (type == NULL)
12078 	    return (NULL);
12079 	name = type->name;
12080 	type->node = node;
12081 	type->type = XML_SCHEMA_TYPE_COMPLEX;
12082 	/*
12083 	* TODO: We need the target namespace.
12084 	*/
12085     } else {
12086 	/*
12087 	* Parse as global complex type definition.
12088 	*/
12089 	type = xmlSchemaAddType(ctxt, schema,
12090 	    XML_SCHEMA_TYPE_COMPLEX,
12091 	    name, ctxt->targetNamespace, node, 1);
12092 	if (type == NULL)
12093 	    return (NULL);
12094 	type->node = node;
12095 	type->type = XML_SCHEMA_TYPE_COMPLEX;
12096 	type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
12097     }
12098     type->targetNamespace = ctxt->targetNamespace;
12099     /*
12100     * Handle attributes.
12101     */
12102     attr = node->properties;
12103     while (attr != NULL) {
12104 	if (attr->ns == NULL) {
12105 	    if (xmlStrEqual(attr->name, BAD_CAST "id")) {
12106 		/*
12107 		* Attribute "id".
12108 		*/
12109 		xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12110 	    } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
12111 		/*
12112 		* Attribute "mixed".
12113 		*/
12114 		if (xmlSchemaPGetBoolNodeValue(ctxt,
12115 			NULL, (xmlNodePtr) attr))
12116 		    type->flags |= XML_SCHEMAS_TYPE_MIXED;
12117 	    } else if (topLevel) {
12118 		/*
12119 		* Attributes of global complex type definitions.
12120 		*/
12121 		if (xmlStrEqual(attr->name, BAD_CAST "name")) {
12122 		    /* Pass. */
12123 		} else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
12124 		    /*
12125 		    * Attribute "abstract".
12126 		    */
12127 		    if (xmlSchemaPGetBoolNodeValue(ctxt,
12128 			    NULL, (xmlNodePtr) attr))
12129 			type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
12130 		} else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
12131 		    /*
12132 		    * Attribute "final".
12133 		    */
12134 		    attrValue = xmlSchemaGetNodeContent(ctxt,
12135 			(xmlNodePtr) attr);
12136 		    if (xmlSchemaPValAttrBlockFinal(attrValue,
12137 			&(type->flags),
12138 			-1,
12139 			XML_SCHEMAS_TYPE_FINAL_EXTENSION,
12140 			XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
12141 			-1, -1, -1) != 0)
12142 		    {
12143 			xmlSchemaPSimpleTypeErr(ctxt,
12144 			    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12145 			    NULL, (xmlNodePtr) attr, NULL,
12146 			    "(#all | List of (extension | restriction))",
12147 			    attrValue, NULL, NULL, NULL);
12148 		    } else
12149 			final = 1;
12150 		} else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
12151 		    /*
12152 		    * Attribute "block".
12153 		    */
12154 		    attrValue = xmlSchemaGetNodeContent(ctxt,
12155 			(xmlNodePtr) attr);
12156 		    if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
12157 			-1,
12158 			XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
12159 			XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
12160 			-1, -1, -1) != 0) {
12161 			xmlSchemaPSimpleTypeErr(ctxt,
12162 			    XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12163 			    NULL, (xmlNodePtr) attr, NULL,
12164 			    "(#all | List of (extension | restriction)) ",
12165 			    attrValue, NULL, NULL, NULL);
12166 		    } else
12167 			block = 1;
12168 		} else {
12169 			xmlSchemaPIllegalAttrErr(ctxt,
12170 			    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12171 		}
12172 	    } else {
12173 		xmlSchemaPIllegalAttrErr(ctxt,
12174 		    XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12175 	    }
12176 	} else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12177 	    xmlSchemaPIllegalAttrErr(ctxt,
12178 		XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12179 	}
12180 	attr = attr->next;
12181     }
12182     if (! block) {
12183 	/*
12184 	* Apply default "block" values.
12185 	*/
12186 	if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
12187 	    type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
12188 	if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
12189 	    type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
12190     }
12191     if (! final) {
12192 	/*
12193 	* Apply default "block" values.
12194 	*/
12195 	if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
12196 	    type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
12197 	if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
12198 	    type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
12199     }
12200     /*
12201     * And now for the children...
12202     */
12203     child = node->children;
12204     if (IS_SCHEMA(child, "annotation")) {
12205         type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
12206         child = child->next;
12207     }
12208     ctxt->ctxtType = type;
12209     if (IS_SCHEMA(child, "simpleContent")) {
12210 	/*
12211 	* <complexType><simpleContent>...
12212 	* 3.4.3 : 2.2
12213 	* Specifying mixed='true' when the <simpleContent>
12214 	* alternative is chosen has no effect
12215 	*/
12216 	if (type->flags & XML_SCHEMAS_TYPE_MIXED)
12217 	    type->flags ^= XML_SCHEMAS_TYPE_MIXED;
12218         xmlSchemaParseSimpleContent(ctxt, schema, child,
12219 	    &hasRestrictionOrExtension);
12220         child = child->next;
12221     } else if (IS_SCHEMA(child, "complexContent")) {
12222 	/*
12223 	* <complexType><complexContent>...
12224 	*/
12225 	type->contentType = XML_SCHEMA_CONTENT_EMPTY;
12226         xmlSchemaParseComplexContent(ctxt, schema, child,
12227 	    &hasRestrictionOrExtension);
12228         child = child->next;
12229     } else {
12230 	/*
12231 	* E.g <complexType><sequence>... or <complexType><attribute>... etc.
12232 	*
12233 	* SPEC
12234 	* "...the third alternative (neither <simpleContent> nor
12235 	* <complexContent>) is chosen. This case is understood as shorthand
12236 	* for complex content restricting the `ur-type definition`, and the
12237 	* details of the mappings should be modified as necessary.
12238 	*/
12239 	type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12240 	type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
12241 	/*
12242 	* Parse model groups.
12243 	*/
12244         if (IS_SCHEMA(child, "all")) {
12245             type->subtypes = (xmlSchemaTypePtr)
12246 		xmlSchemaParseModelGroup(ctxt, schema, child,
12247 		    XML_SCHEMA_TYPE_ALL, 1);
12248             child = child->next;
12249         } else if (IS_SCHEMA(child, "choice")) {
12250             type->subtypes = (xmlSchemaTypePtr)
12251 		xmlSchemaParseModelGroup(ctxt, schema, child,
12252 		    XML_SCHEMA_TYPE_CHOICE, 1);
12253             child = child->next;
12254         } else if (IS_SCHEMA(child, "sequence")) {
12255             type->subtypes = (xmlSchemaTypePtr)
12256 		xmlSchemaParseModelGroup(ctxt, schema, child,
12257 		    XML_SCHEMA_TYPE_SEQUENCE, 1);
12258             child = child->next;
12259         } else if (IS_SCHEMA(child, "group")) {
12260             type->subtypes = (xmlSchemaTypePtr)
12261 		xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
12262 	    /*
12263 	    * Note that the reference will be resolved in
12264 	    * xmlSchemaResolveTypeReferences();
12265 	    */
12266             child = child->next;
12267         }
12268 	/*
12269 	* Parse attribute decls/refs.
12270 	*/
12271         if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
12272 	    (xmlSchemaItemListPtr *) &(type->attrUses),
12273 	    XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
12274 	    return(NULL);
12275 	/*
12276 	* Parse attribute wildcard.
12277 	*/
12278 	if (IS_SCHEMA(child, "anyAttribute")) {
12279 	    type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
12280 	    child = child->next;
12281 	}
12282     }
12283     if (child != NULL) {
12284 	xmlSchemaPContentErr(ctxt,
12285 	    XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12286 	    NULL, node, child,
12287 	    NULL, "(annotation?, (simpleContent | complexContent | "
12288 	    "((group | all | choice | sequence)?, ((attribute | "
12289 	    "attributeGroup)*, anyAttribute?))))");
12290     }
12291     /*
12292     * REDEFINE: SPEC src-redefine (5)
12293     */
12294     if (topLevel && ctxt->isRedefine && (! hasRestrictionOrExtension)) {
12295 	xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
12296 	    NULL, node, "This is a redefinition, thus the "
12297 	    "<complexType> must have a <restriction> or <extension> "
12298 	    "grand-child", NULL);
12299     }
12300     ctxt->ctxtType = ctxtType;
12301     return (type);
12302 }
12303 
12304 /************************************************************************
12305  *									*
12306  *			Validating using Schemas			*
12307  *									*
12308  ************************************************************************/
12309 
12310 /************************************************************************
12311  *									*
12312  *			Reading/Writing Schemas				*
12313  *									*
12314  ************************************************************************/
12315 
12316 #if 0 /* Will be enabled if it is clear what options are needed. */
12317 /**
12318  * xmlSchemaParserCtxtSetOptions:
12319  * @ctxt:	a schema parser context
12320  * @options: a combination of xmlSchemaParserOption
12321  *
12322  * Sets the options to be used during the parse.
12323  *
12324  * Returns 0 in case of success, -1 in case of an
12325  * API error.
12326  */
12327 static int
12328 xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
12329 			      int options)
12330 
12331 {
12332     int i;
12333 
12334     if (ctxt == NULL)
12335 	return (-1);
12336     /*
12337     * WARNING: Change the start value if adding to the
12338     * xmlSchemaParseOption.
12339     */
12340     for (i = 1; i < (int) sizeof(int) * 8; i++) {
12341         if (options & 1<<i) {
12342 	    return (-1);
12343         }
12344     }
12345     ctxt->options = options;
12346     return (0);
12347 }
12348 
12349 /**
12350  * xmlSchemaValidCtxtGetOptions:
12351  * @ctxt: a schema parser context
12352  *
12353  * Returns the option combination of the parser context.
12354  */
12355 static int
12356 xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
12357 
12358 {
12359     if (ctxt == NULL)
12360 	return (-1);
12361     else
12362 	return (ctxt->options);
12363 }
12364 #endif
12365 
12366 /**
12367  * xmlSchemaNewParserCtxt:
12368  * @URL:  the location of the schema
12369  *
12370  * Create an XML Schemas parse context for that file/resource expected
12371  * to contain an XML Schemas file.
12372  *
12373  * Returns the parser context or NULL in case of error
12374  */
12375 xmlSchemaParserCtxtPtr
xmlSchemaNewParserCtxt(const char * URL)12376 xmlSchemaNewParserCtxt(const char *URL)
12377 {
12378     xmlSchemaParserCtxtPtr ret;
12379 
12380     if (URL == NULL)
12381         return (NULL);
12382 
12383     ret = xmlSchemaParserCtxtCreate();
12384     if (ret == NULL)
12385 	return(NULL);
12386     ret->dict = xmlDictCreate();
12387     ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
12388     return (ret);
12389 }
12390 
12391 /**
12392  * xmlSchemaNewMemParserCtxt:
12393  * @buffer:  a pointer to a char array containing the schemas
12394  * @size:  the size of the array
12395  *
12396  * Create an XML Schemas parse context for that memory buffer expected
12397  * to contain an XML Schemas file.
12398  *
12399  * Returns the parser context or NULL in case of error
12400  */
12401 xmlSchemaParserCtxtPtr
xmlSchemaNewMemParserCtxt(const char * buffer,int size)12402 xmlSchemaNewMemParserCtxt(const char *buffer, int size)
12403 {
12404     xmlSchemaParserCtxtPtr ret;
12405 
12406     if ((buffer == NULL) || (size <= 0))
12407         return (NULL);
12408     ret = xmlSchemaParserCtxtCreate();
12409     if (ret == NULL)
12410 	return(NULL);
12411     ret->buffer = buffer;
12412     ret->size = size;
12413     ret->dict = xmlDictCreate();
12414     return (ret);
12415 }
12416 
12417 /**
12418  * xmlSchemaNewDocParserCtxt:
12419  * @doc:  a preparsed document tree
12420  *
12421  * Create an XML Schemas parse context for that document.
12422  * NB. The document may be modified during the parsing process.
12423  *
12424  * Returns the parser context or NULL in case of error
12425  */
12426 xmlSchemaParserCtxtPtr
xmlSchemaNewDocParserCtxt(xmlDocPtr doc)12427 xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
12428 {
12429     xmlSchemaParserCtxtPtr ret;
12430 
12431     if (doc == NULL)
12432       return (NULL);
12433     ret = xmlSchemaParserCtxtCreate();
12434     if (ret == NULL)
12435 	return(NULL);
12436     ret->doc = doc;
12437     ret->dict = xmlDictCreate();
12438     /* The application has responsibility for the document */
12439     ret->preserve = 1;
12440 
12441     return (ret);
12442 }
12443 
12444 /**
12445  * xmlSchemaFreeParserCtxt:
12446  * @ctxt:  the schema parser context
12447  *
12448  * Free the resources associated to the schema parser context
12449  */
12450 void
xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)12451 xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
12452 {
12453     if (ctxt == NULL)
12454         return;
12455     if (ctxt->doc != NULL && !ctxt->preserve)
12456         xmlFreeDoc(ctxt->doc);
12457     if (ctxt->vctxt != NULL) {
12458 	xmlSchemaFreeValidCtxt(ctxt->vctxt);
12459     }
12460     if (ctxt->ownsConstructor && (ctxt->constructor != NULL)) {
12461 	xmlSchemaConstructionCtxtFree(ctxt->constructor);
12462 	ctxt->constructor = NULL;
12463 	ctxt->ownsConstructor = 0;
12464     }
12465     if (ctxt->attrProhibs != NULL)
12466 	xmlSchemaItemListFree(ctxt->attrProhibs);
12467     xmlDictFree(ctxt->dict);
12468     xmlFree(ctxt);
12469 }
12470 
12471 /************************************************************************
12472  *									*
12473  *			Building the content models			*
12474  *									*
12475  ************************************************************************/
12476 
12477 /**
12478  * xmlSchemaBuildContentModelForSubstGroup:
12479  *
12480  * Returns 1 if nillable, 0 otherwise
12481  */
12482 static int
xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,xmlSchemaParticlePtr particle,int counter,xmlAutomataStatePtr end)12483 xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
12484 	xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end)
12485 {
12486     xmlAutomataStatePtr start, tmp;
12487     xmlSchemaElementPtr elemDecl, member;
12488     xmlSchemaSubstGroupPtr substGroup;
12489     int i;
12490     int ret = 0;
12491 
12492     elemDecl = (xmlSchemaElementPtr) particle->children;
12493     /*
12494     * Wrap the substitution group with a CHOICE.
12495     */
12496     start = pctxt->state;
12497     if (end == NULL)
12498 	end = xmlAutomataNewState(pctxt->am);
12499     substGroup = xmlSchemaSubstGroupGet(pctxt, elemDecl);
12500     if (substGroup == NULL) {
12501 	xmlSchemaPErr(pctxt, WXS_ITEM_NODE(particle),
12502 	    XML_SCHEMAP_INTERNAL,
12503 	    "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
12504 	    "declaration is marked having a subst. group but none "
12505 	    "available.\n", elemDecl->name, NULL);
12506 	return(0);
12507     }
12508     if (counter >= 0) {
12509 	/*
12510 	* NOTE that we put the declaration in, even if it's abstract.
12511 	* However, an error will be raised during *validation* if an element
12512 	* information item shall be validated against an abstract element
12513 	* declaration.
12514 	*/
12515 	tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter);
12516         xmlAutomataNewTransition2(pctxt->am, tmp, end,
12517 	            elemDecl->name, elemDecl->targetNamespace, elemDecl);
12518 	/*
12519 	* Add subst. group members.
12520 	*/
12521 	for (i = 0; i < substGroup->members->nbItems; i++) {
12522 	    member = (xmlSchemaElementPtr) substGroup->members->items[i];
12523             xmlAutomataNewTransition2(pctxt->am, tmp, end,
12524 		               member->name, member->targetNamespace, member);
12525 	}
12526     } else if (particle->maxOccurs == 1) {
12527 	/*
12528 	* NOTE that we put the declaration in, even if it's abstract,
12529 	*/
12530 	xmlAutomataNewEpsilon(pctxt->am,
12531 	    xmlAutomataNewTransition2(pctxt->am,
12532 	    start, NULL,
12533 	    elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
12534 	/*
12535 	* Add subst. group members.
12536 	*/
12537 	for (i = 0; i < substGroup->members->nbItems; i++) {
12538 	    member = (xmlSchemaElementPtr) substGroup->members->items[i];
12539 	    /*
12540 	    * NOTE: This fixes bug #341150. xmlAutomataNewOnceTrans2()
12541 	    *  was incorrectly used instead of xmlAutomataNewTransition2()
12542 	    *  (seems like a copy&paste bug from the XML_SCHEMA_TYPE_ALL
12543 	    *  section in xmlSchemaBuildAContentModel() ).
12544 	    * TODO: Check if xmlAutomataNewOnceTrans2() was instead
12545 	    *  intended for the above "counter" section originally. I.e.,
12546 	    *  check xs:all with subst-groups.
12547 	    *
12548 	    * tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL,
12549 	    *	               member->name, member->targetNamespace,
12550 	    *		       1, 1, member);
12551 	    */
12552 	    tmp = xmlAutomataNewTransition2(pctxt->am, start, NULL,
12553 		member->name, member->targetNamespace, member);
12554 	    xmlAutomataNewEpsilon(pctxt->am, tmp, end);
12555 	}
12556     } else {
12557 	xmlAutomataStatePtr hop;
12558 	int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12559 	    UNBOUNDED : particle->maxOccurs - 1;
12560 	int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12561 
12562 	counter =
12563 	    xmlAutomataNewCounter(pctxt->am, minOccurs,
12564 	    maxOccurs);
12565 	hop = xmlAutomataNewState(pctxt->am);
12566 
12567 	xmlAutomataNewEpsilon(pctxt->am,
12568 	    xmlAutomataNewTransition2(pctxt->am,
12569 	    start, NULL,
12570 	    elemDecl->name, elemDecl->targetNamespace, elemDecl),
12571 	    hop);
12572 	/*
12573 	 * Add subst. group members.
12574 	 */
12575 	for (i = 0; i < substGroup->members->nbItems; i++) {
12576 	    member = (xmlSchemaElementPtr) substGroup->members->items[i];
12577 	    xmlAutomataNewEpsilon(pctxt->am,
12578 		xmlAutomataNewTransition2(pctxt->am,
12579 		start, NULL,
12580 		member->name, member->targetNamespace, member),
12581 		hop);
12582 	}
12583 	xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12584 	xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12585     }
12586     if (particle->minOccurs == 0) {
12587 	xmlAutomataNewEpsilon(pctxt->am, start, end);
12588         ret = 1;
12589     }
12590     pctxt->state = end;
12591     return(ret);
12592 }
12593 
12594 /**
12595  * xmlSchemaBuildContentModelForElement:
12596  *
12597  * Returns 1 if nillable, 0 otherwise
12598  */
12599 static int
xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr particle)12600 xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
12601 				     xmlSchemaParticlePtr particle)
12602 {
12603     int ret = 0;
12604 
12605     if (((xmlSchemaElementPtr) particle->children)->flags &
12606 	XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
12607 	/*
12608 	* Substitution groups.
12609 	*/
12610 	ret = xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
12611     } else {
12612 	xmlSchemaElementPtr elemDecl;
12613 	xmlAutomataStatePtr start;
12614 
12615 	elemDecl = (xmlSchemaElementPtr) particle->children;
12616 
12617 	if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
12618 	    return(0);
12619 	if (particle->maxOccurs == 1) {
12620 	    start = ctxt->state;
12621 	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12622 		    elemDecl->name, elemDecl->targetNamespace, elemDecl);
12623 	} else if ((particle->maxOccurs >= UNBOUNDED) &&
12624 	           (particle->minOccurs < 2)) {
12625 	    /* Special case. */
12626 	    start = ctxt->state;
12627 	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12628 		elemDecl->name, elemDecl->targetNamespace, elemDecl);
12629 	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, ctxt->state, ctxt->state,
12630 		elemDecl->name, elemDecl->targetNamespace, elemDecl);
12631 	} else {
12632 	    int counter;
12633 	    int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12634 			    UNBOUNDED : particle->maxOccurs - 1;
12635 	    int minOccurs = particle->minOccurs < 1 ?
12636 			    0 : particle->minOccurs - 1;
12637 
12638 	    start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
12639 	    counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
12640 	    ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12641 		elemDecl->name, elemDecl->targetNamespace, elemDecl);
12642 	    xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
12643 	    ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
12644 		NULL, counter);
12645 	}
12646 	if (particle->minOccurs == 0) {
12647 	    xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
12648             ret = 1;
12649         }
12650     }
12651     return(ret);
12652 }
12653 
12654 /**
12655  * xmlSchemaBuildAContentModel:
12656  * @ctxt:  the schema parser context
12657  * @particle:  the particle component
12658  * @name:  the complex type's name whose content is being built
12659  *
12660  * Create the automaton for the {content type} of a complex type.
12661  *
12662  * Returns 1 if the content is nillable, 0 otherwise
12663  */
12664 static int
xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,xmlSchemaParticlePtr particle)12665 xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
12666 			    xmlSchemaParticlePtr particle)
12667 {
12668     int ret = 0, tmp2;
12669 
12670     if (particle == NULL) {
12671 	PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL");
12672 	return(1);
12673     }
12674     if (particle->children == NULL) {
12675 	/*
12676 	* Just return in this case. A missing "term" of the particle
12677 	* might arise due to an invalid "term" component.
12678 	*/
12679 	return(1);
12680     }
12681 
12682     switch (particle->children->type) {
12683 	case XML_SCHEMA_TYPE_ANY: {
12684 	    xmlAutomataStatePtr start, end;
12685 	    xmlSchemaWildcardPtr wild;
12686 	    xmlSchemaWildcardNsPtr ns;
12687 
12688 	    wild = (xmlSchemaWildcardPtr) particle->children;
12689 
12690 	    start = pctxt->state;
12691 	    end = xmlAutomataNewState(pctxt->am);
12692 
12693 	    if (particle->maxOccurs == 1) {
12694 		if (wild->any == 1) {
12695 		    /*
12696 		    * We need to add both transitions:
12697 		    *
12698 		    * 1. the {"*", "*"} for elements in a namespace.
12699 		    */
12700 		    pctxt->state =
12701 			xmlAutomataNewTransition2(pctxt->am,
12702 			start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12703 		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12704 		    /*
12705 		    * 2. the {"*"} for elements in no namespace.
12706 		    */
12707 		    pctxt->state =
12708 			xmlAutomataNewTransition2(pctxt->am,
12709 			start, NULL, BAD_CAST "*", NULL, wild);
12710 		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12711 
12712 		} else if (wild->nsSet != NULL) {
12713 		    ns = wild->nsSet;
12714 		    do {
12715 			pctxt->state = start;
12716 			pctxt->state = xmlAutomataNewTransition2(pctxt->am,
12717 			    pctxt->state, NULL, BAD_CAST "*", ns->value, wild);
12718 			xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12719 			ns = ns->next;
12720 		    } while (ns != NULL);
12721 
12722 		} else if (wild->negNsSet != NULL) {
12723 		    pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12724 			start, end, BAD_CAST "*", wild->negNsSet->value,
12725 			wild);
12726 		}
12727 	    } else {
12728 		int counter;
12729 		xmlAutomataStatePtr hop;
12730 		int maxOccurs =
12731 		    particle->maxOccurs == UNBOUNDED ? UNBOUNDED :
12732                                            particle->maxOccurs - 1;
12733 		int minOccurs =
12734 		    particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12735 
12736 		counter = xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12737 		hop = xmlAutomataNewState(pctxt->am);
12738 		if (wild->any == 1) {
12739 		    pctxt->state =
12740 			xmlAutomataNewTransition2(pctxt->am,
12741 			start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12742 		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12743 		    pctxt->state =
12744 			xmlAutomataNewTransition2(pctxt->am,
12745 			start, NULL, BAD_CAST "*", NULL, wild);
12746 		    xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12747 		} else if (wild->nsSet != NULL) {
12748 		    ns = wild->nsSet;
12749 		    do {
12750 			pctxt->state =
12751 			    xmlAutomataNewTransition2(pctxt->am,
12752 				start, NULL, BAD_CAST "*", ns->value, wild);
12753 			xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12754 			ns = ns->next;
12755 		    } while (ns != NULL);
12756 
12757 		} else if (wild->negNsSet != NULL) {
12758 		    pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12759 			start, hop, BAD_CAST "*", wild->negNsSet->value,
12760 			wild);
12761 		}
12762 		xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12763 		xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12764 	    }
12765 	    if (particle->minOccurs == 0) {
12766 		xmlAutomataNewEpsilon(pctxt->am, start, end);
12767                 ret = 1;
12768 	    }
12769 	    pctxt->state = end;
12770             break;
12771 	}
12772         case XML_SCHEMA_TYPE_ELEMENT:
12773 	    ret = xmlSchemaBuildContentModelForElement(pctxt, particle);
12774 	    break;
12775         case XML_SCHEMA_TYPE_SEQUENCE:{
12776             xmlSchemaTreeItemPtr sub;
12777 
12778             ret = 1;
12779             /*
12780              * If max and min occurrences are default (1) then
12781              * simply iterate over the particles of the <sequence>.
12782              */
12783             if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
12784                 sub = particle->children->children;
12785 
12786                 while (sub != NULL) {
12787                     tmp2 = xmlSchemaBuildAContentModel(pctxt,
12788                                         (xmlSchemaParticlePtr) sub);
12789                     if (tmp2 != 1) ret = 0;
12790                     sub = sub->next;
12791                 }
12792             } else {
12793                 xmlAutomataStatePtr oldstate = pctxt->state;
12794 
12795                 if (particle->maxOccurs >= UNBOUNDED) {
12796                     if (particle->minOccurs > 1) {
12797                         xmlAutomataStatePtr tmp;
12798                         int counter;
12799 
12800                         pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12801                             oldstate, NULL);
12802                         oldstate = pctxt->state;
12803 
12804                         counter = xmlAutomataNewCounter(pctxt->am,
12805                             particle->minOccurs - 1, UNBOUNDED);
12806 
12807                         sub = particle->children->children;
12808                         while (sub != NULL) {
12809                             tmp2 = xmlSchemaBuildAContentModel(pctxt,
12810                                             (xmlSchemaParticlePtr) sub);
12811                             if (tmp2 != 1) ret = 0;
12812                             sub = sub->next;
12813                         }
12814                         tmp = pctxt->state;
12815                         xmlAutomataNewCountedTrans(pctxt->am, tmp,
12816                                                    oldstate, counter);
12817                         pctxt->state =
12818                             xmlAutomataNewCounterTrans(pctxt->am, tmp,
12819                                                        NULL, counter);
12820                         if (ret == 1)
12821                             xmlAutomataNewEpsilon(pctxt->am,
12822                                                 oldstate, pctxt->state);
12823 
12824                     } else {
12825                         pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12826                             oldstate, NULL);
12827                         oldstate = pctxt->state;
12828 
12829                         sub = particle->children->children;
12830                         while (sub != NULL) {
12831                             tmp2 = xmlSchemaBuildAContentModel(pctxt,
12832                                         (xmlSchemaParticlePtr) sub);
12833                             if (tmp2 != 1) ret = 0;
12834                             sub = sub->next;
12835                         }
12836                         xmlAutomataNewEpsilon(pctxt->am, pctxt->state,
12837                                               oldstate);
12838                         /*
12839                          * epsilon needed to block previous trans from
12840                          * being allowed to enter back from another
12841                          * construct
12842                          */
12843                         pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12844                                             pctxt->state, NULL);
12845                         if (particle->minOccurs == 0) {
12846                             xmlAutomataNewEpsilon(pctxt->am,
12847                                 oldstate, pctxt->state);
12848                             ret = 1;
12849                         }
12850                     }
12851                 } else if ((particle->maxOccurs > 1)
12852                            || (particle->minOccurs > 1)) {
12853                     xmlAutomataStatePtr tmp;
12854                     int counter;
12855 
12856                     pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12857                         oldstate, NULL);
12858                     oldstate = pctxt->state;
12859 
12860                     counter = xmlAutomataNewCounter(pctxt->am,
12861                         particle->minOccurs - 1,
12862                         particle->maxOccurs - 1);
12863 
12864                     sub = particle->children->children;
12865                     while (sub != NULL) {
12866                         tmp2 = xmlSchemaBuildAContentModel(pctxt,
12867                                         (xmlSchemaParticlePtr) sub);
12868                         if (tmp2 != 1) ret = 0;
12869                         sub = sub->next;
12870                     }
12871                     tmp = pctxt->state;
12872                     xmlAutomataNewCountedTrans(pctxt->am,
12873                         tmp, oldstate, counter);
12874                     pctxt->state =
12875                         xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL,
12876                                                    counter);
12877                     if ((particle->minOccurs == 0) || (ret == 1)) {
12878                         xmlAutomataNewEpsilon(pctxt->am,
12879                                             oldstate, pctxt->state);
12880                         ret = 1;
12881                     }
12882                 } else {
12883                     sub = particle->children->children;
12884                     while (sub != NULL) {
12885                         tmp2 = xmlSchemaBuildAContentModel(pctxt,
12886                                         (xmlSchemaParticlePtr) sub);
12887                         if (tmp2 != 1) ret = 0;
12888                         sub = sub->next;
12889                     }
12890 
12891 		    /*
12892 		     * epsilon needed to block previous trans from
12893 		     * being allowed to enter back from another
12894 		     * construct
12895 		     */
12896 		    pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12897 					pctxt->state, NULL);
12898 
12899                     if (particle->minOccurs == 0) {
12900                         xmlAutomataNewEpsilon(pctxt->am, oldstate,
12901                                               pctxt->state);
12902                         ret = 1;
12903                     }
12904                 }
12905             }
12906             break;
12907         }
12908         case XML_SCHEMA_TYPE_CHOICE:{
12909             xmlSchemaTreeItemPtr sub;
12910             xmlAutomataStatePtr start, end;
12911 
12912             ret = 0;
12913             start = pctxt->state;
12914             end = xmlAutomataNewState(pctxt->am);
12915 
12916             /*
12917              * iterate over the subtypes and remerge the end with an
12918              * epsilon transition
12919              */
12920             if (particle->maxOccurs == 1) {
12921                 sub = particle->children->children;
12922                 while (sub != NULL) {
12923                     pctxt->state = start;
12924                     tmp2 = xmlSchemaBuildAContentModel(pctxt,
12925                                         (xmlSchemaParticlePtr) sub);
12926                     if (tmp2 == 1) ret = 1;
12927                     xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12928                     sub = sub->next;
12929                 }
12930             } else {
12931                 int counter;
12932                 xmlAutomataStatePtr hop, base;
12933                 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12934                     UNBOUNDED : particle->maxOccurs - 1;
12935                 int minOccurs =
12936                     particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12937 
12938                 /*
12939                  * use a counter to keep track of the number of transitions
12940                  * which went through the choice.
12941                  */
12942                 counter =
12943                     xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12944                 hop = xmlAutomataNewState(pctxt->am);
12945                 base = xmlAutomataNewState(pctxt->am);
12946 
12947                 sub = particle->children->children;
12948                 while (sub != NULL) {
12949                     pctxt->state = base;
12950                     tmp2 = xmlSchemaBuildAContentModel(pctxt,
12951                                         (xmlSchemaParticlePtr) sub);
12952                     if (tmp2 == 1) ret = 1;
12953                     xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12954                     sub = sub->next;
12955                 }
12956                 xmlAutomataNewEpsilon(pctxt->am, start, base);
12957                 xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter);
12958                 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12959                 if (ret == 1)
12960                     xmlAutomataNewEpsilon(pctxt->am, base, end);
12961             }
12962             if (particle->minOccurs == 0) {
12963                 xmlAutomataNewEpsilon(pctxt->am, start, end);
12964                 ret = 1;
12965             }
12966             pctxt->state = end;
12967             break;
12968         }
12969         case XML_SCHEMA_TYPE_ALL:{
12970             xmlAutomataStatePtr start, tmp;
12971             xmlSchemaParticlePtr sub;
12972             xmlSchemaElementPtr elemDecl;
12973 
12974             ret = 1;
12975 
12976             sub = (xmlSchemaParticlePtr) particle->children->children;
12977             if (sub == NULL)
12978                 break;
12979 
12980             ret = 0;
12981 
12982             start = pctxt->state;
12983             tmp = xmlAutomataNewState(pctxt->am);
12984             xmlAutomataNewEpsilon(pctxt->am, pctxt->state, tmp);
12985             pctxt->state = tmp;
12986             while (sub != NULL) {
12987                 pctxt->state = tmp;
12988 
12989                 elemDecl = (xmlSchemaElementPtr) sub->children;
12990                 if (elemDecl == NULL) {
12991                     PERROR_INT("xmlSchemaBuildAContentModel",
12992                         "<element> particle has no term");
12993                     return(ret);
12994                 };
12995                 /*
12996                 * NOTE: The {max occurs} of all the particles in the
12997                 * {particles} of the group must be 0 or 1; this is
12998                 * already ensured during the parse of the content of
12999                 * <all>.
13000                 */
13001                 if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
13002                     int counter;
13003 
13004                     /*
13005                      * This is an abstract group, we need to share
13006                      * the same counter for all the element transitions
13007                      * derived from the group
13008                      */
13009                     counter = xmlAutomataNewCounter(pctxt->am,
13010                                        sub->minOccurs, sub->maxOccurs);
13011                     xmlSchemaBuildContentModelForSubstGroup(pctxt,
13012                                        sub, counter, pctxt->state);
13013                 } else {
13014                     if ((sub->minOccurs == 1) &&
13015                         (sub->maxOccurs == 1)) {
13016                         xmlAutomataNewOnceTrans2(pctxt->am, pctxt->state,
13017                                                 pctxt->state,
13018                                                 elemDecl->name,
13019                                                 elemDecl->targetNamespace,
13020                                                 1, 1, elemDecl);
13021                     } else if ((sub->minOccurs == 0) &&
13022                         (sub->maxOccurs == 1)) {
13023 
13024                         xmlAutomataNewCountTrans2(pctxt->am, pctxt->state,
13025                                                  pctxt->state,
13026                                                  elemDecl->name,
13027                                                  elemDecl->targetNamespace,
13028                                                  0,
13029                                                  1,
13030                                                  elemDecl);
13031                     }
13032                 }
13033                 sub = (xmlSchemaParticlePtr) sub->next;
13034             }
13035             pctxt->state =
13036                 xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, 0);
13037             if (particle->minOccurs == 0) {
13038                 xmlAutomataNewEpsilon(pctxt->am, start, pctxt->state);
13039                 ret = 1;
13040             }
13041             break;
13042         }
13043 	case XML_SCHEMA_TYPE_GROUP:
13044 	    /*
13045 	    * If we hit a model group definition, then this means that
13046 	    * it was empty, thus was not substituted for the containing
13047 	    * model group. Just do nothing in this case.
13048 	    * TODO: But the group should be substituted and not occur at
13049 	    * all in the content model at this point. Fix this.
13050 	    */
13051             ret = 1;
13052 	    break;
13053         default:
13054 	    xmlSchemaInternalErr2(ACTXT_CAST pctxt,
13055 		"xmlSchemaBuildAContentModel",
13056 		"found unexpected term of type '%s' in content model",
13057 		WXS_ITEM_TYPE_NAME(particle->children), NULL);
13058             return(ret);
13059     }
13060     return(ret);
13061 }
13062 
13063 /**
13064  * xmlSchemaBuildContentModel:
13065  * @ctxt:  the schema parser context
13066  * @type:  the complex type definition
13067  * @name:  the element name
13068  *
13069  * Builds the content model of the complex type.
13070  */
13071 static void
xmlSchemaBuildContentModel(xmlSchemaTypePtr type,xmlSchemaParserCtxtPtr ctxt)13072 xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
13073 			   xmlSchemaParserCtxtPtr ctxt)
13074 {
13075     if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
13076 	(type->contModel != NULL) ||
13077 	((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
13078 	(type->contentType != XML_SCHEMA_CONTENT_MIXED)))
13079 	return;
13080 
13081     ctxt->am = NULL;
13082     ctxt->am = xmlNewAutomata();
13083     if (ctxt->am == NULL) {
13084 	xmlSchemaPErrMemory(ctxt);
13085         return;
13086     }
13087     ctxt->state = xmlAutomataGetInitState(ctxt->am);
13088     /*
13089     * Build the automaton.
13090     */
13091     xmlSchemaBuildAContentModel(ctxt, WXS_TYPE_PARTICLE(type));
13092     xmlAutomataSetFinalState(ctxt->am, ctxt->state);
13093     type->contModel = xmlAutomataCompile(ctxt->am);
13094     if (type->contModel == NULL) {
13095         xmlSchemaPCustomErr(ctxt,
13096 	    XML_SCHEMAP_INTERNAL,
13097 	    WXS_BASIC_CAST type, type->node,
13098 	    "Failed to compile the content model", NULL);
13099     } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
13100         xmlSchemaPCustomErr(ctxt,
13101 	    XML_SCHEMAP_NOT_DETERMINISTIC,
13102 	    /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
13103 	    WXS_BASIC_CAST type, type->node,
13104 	    "The content model is not determinist", NULL);
13105     } else {
13106     }
13107     ctxt->state = NULL;
13108     xmlFreeAutomata(ctxt->am);
13109     ctxt->am = NULL;
13110 }
13111 
13112 /**
13113  * xmlSchemaResolveElementReferences:
13114  * @elem:  the schema element context
13115  * @ctxt:  the schema parser context
13116  *
13117  * Resolves the references of an element declaration
13118  * or particle, which has an element declaration as it's
13119  * term.
13120  */
13121 static void
xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,xmlSchemaParserCtxtPtr ctxt)13122 xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,
13123 				  xmlSchemaParserCtxtPtr ctxt)
13124 {
13125     if ((ctxt == NULL) || (elemDecl == NULL) ||
13126 	((elemDecl != NULL) &&
13127 	(elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
13128         return;
13129     elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
13130 
13131     if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
13132 	xmlSchemaTypePtr type;
13133 
13134 	/* (type definition) ... otherwise the type definition `resolved`
13135 	* to by the `actual value` of the type [attribute] ...
13136 	*/
13137 	type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
13138 	    elemDecl->namedTypeNs);
13139 	if (type == NULL) {
13140 	    xmlSchemaPResCompAttrErr(ctxt,
13141 		XML_SCHEMAP_SRC_RESOLVE,
13142 		WXS_BASIC_CAST elemDecl, elemDecl->node,
13143 		"type", elemDecl->namedType, elemDecl->namedTypeNs,
13144 		XML_SCHEMA_TYPE_BASIC, "type definition");
13145 	} else
13146 	    elemDecl->subtypes = type;
13147     }
13148     if (elemDecl->substGroup != NULL) {
13149 	xmlSchemaElementPtr substHead;
13150 
13151 	/*
13152 	* FIXME TODO: Do we need a new field in _xmlSchemaElement for
13153 	* substitutionGroup?
13154 	*/
13155 	substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
13156 	    elemDecl->substGroupNs);
13157 	if (substHead == NULL) {
13158 	    xmlSchemaPResCompAttrErr(ctxt,
13159 		XML_SCHEMAP_SRC_RESOLVE,
13160 		WXS_BASIC_CAST elemDecl, NULL,
13161 		"substitutionGroup", elemDecl->substGroup,
13162 		elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
13163 	} else {
13164 	    xmlSchemaResolveElementReferences(substHead, ctxt);
13165 	    /*
13166 	    * Set the "substitution group affiliation".
13167 	    * NOTE that now we use the "refDecl" field for this.
13168 	    */
13169 	    WXS_SUBST_HEAD(elemDecl) = substHead;
13170 	    /*
13171 	    * The type definitions is set to:
13172 	    * SPEC "...the {type definition} of the element
13173 	    * declaration `resolved` to by the `actual value`
13174 	    * of the substitutionGroup [attribute], if present"
13175 	    */
13176 	    if (elemDecl->subtypes == NULL) {
13177                 if (substHead->subtypes == NULL) {
13178                     /*
13179                      * This can happen with self-referencing substitution
13180                      * groups. The cycle will be detected later, but we have
13181                      * to set subtypes to avoid null-pointer dereferences.
13182                      */
13183 	            elemDecl->subtypes = xmlSchemaGetBuiltInType(
13184                             XML_SCHEMAS_ANYTYPE);
13185                 } else {
13186 		    elemDecl->subtypes = substHead->subtypes;
13187                 }
13188             }
13189 	}
13190     }
13191     /*
13192     * SPEC "The definition of anyType serves as the default type definition
13193     * for element declarations whose XML representation does not specify one."
13194     */
13195     if ((elemDecl->subtypes == NULL) &&
13196 	(elemDecl->namedType == NULL) &&
13197 	(elemDecl->substGroup == NULL))
13198 	elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
13199 }
13200 
13201 /**
13202  * xmlSchemaResolveUnionMemberTypes:
13203  * @ctxt:  the schema parser context
13204  * @type:  the schema simple type definition
13205  *
13206  * Checks and builds the "member type definitions" property of the union
13207  * simple type. This handles part (1), part (2) is done in
13208  * xmlSchemaFinishMemberTypeDefinitionsProperty()
13209  *
13210  * Returns -1 in case of an internal error, 0 otherwise.
13211  */
13212 static int
xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)13213 xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
13214 				 xmlSchemaTypePtr type)
13215 {
13216 
13217     xmlSchemaTypeLinkPtr link, lastLink, newLink;
13218     xmlSchemaTypePtr memberType;
13219 
13220     /*
13221     * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
13222     * define the explicit members as the type definitions `resolved`
13223     * to by the items in the `actual value` of the memberTypes [attribute],
13224     * if any, followed by the type definitions corresponding to the
13225     * <simpleType>s among the [children] of <union>, if any."
13226     */
13227     /*
13228     * Resolve references.
13229     */
13230     link = type->memberTypes;
13231     lastLink = NULL;
13232     while (link != NULL) {
13233 	const xmlChar *name, *nsName;
13234 
13235 	name = ((xmlSchemaQNameRefPtr) link->type)->name;
13236 	nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
13237 
13238 	memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
13239 	if ((memberType == NULL) || (! WXS_IS_SIMPLE(memberType))) {
13240 	    xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
13241 		WXS_BASIC_CAST type, type->node, "memberTypes",
13242 		name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
13243 	    /*
13244 	    * Remove the member type link.
13245 	    */
13246 	    if (lastLink == NULL)
13247 		type->memberTypes = link->next;
13248 	    else
13249 		lastLink->next = link->next;
13250 	    newLink = link;
13251 	    link = link->next;
13252 	    xmlFree(newLink);
13253 	} else {
13254 	    link->type = memberType;
13255 	    lastLink = link;
13256 	    link = link->next;
13257 	}
13258     }
13259     /*
13260     * Add local simple types,
13261     */
13262     memberType = type->subtypes;
13263     while (memberType != NULL) {
13264 	link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
13265 	if (link == NULL) {
13266 	    xmlSchemaPErrMemory(ctxt);
13267 	    return (-1);
13268 	}
13269 	link->type = memberType;
13270 	link->next = NULL;
13271 	if (lastLink == NULL)
13272 	    type->memberTypes = link;
13273 	else
13274 	    lastLink->next = link;
13275 	lastLink = link;
13276 	memberType = memberType->next;
13277     }
13278     return (0);
13279 }
13280 
13281 /**
13282  * xmlSchemaIsDerivedFromBuiltInType:
13283  * @ctxt:  the schema parser context
13284  * @type:  the type definition
13285  * @valType: the value type
13286  *
13287  *
13288  * Returns 1 if the type has the given value type, or
13289  * is derived from such a type.
13290  */
13291 static int
xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type,int valType)13292 xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13293 {
13294     if (type == NULL)
13295 	return (0);
13296     if (WXS_IS_COMPLEX(type))
13297 	return (0);
13298     if (type->type == XML_SCHEMA_TYPE_BASIC) {
13299 	if (type->builtInType == valType)
13300 	    return(1);
13301 	if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13302 	    (type->builtInType == XML_SCHEMAS_ANYTYPE))
13303 	    return (0);
13304 	return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13305     }
13306     return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13307 }
13308 
13309 #if 0
13310 /**
13311  * xmlSchemaIsDerivedFromBuiltInType:
13312  * @ctxt:  the schema parser context
13313  * @type:  the type definition
13314  * @valType: the value type
13315  *
13316  *
13317  * Returns 1 if the type has the given value type, or
13318  * is derived from such a type.
13319  */
13320 static int
13321 xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13322 {
13323     if (type == NULL)
13324 	return (0);
13325     if (WXS_IS_COMPLEX(type))
13326 	return (0);
13327     if (type->type == XML_SCHEMA_TYPE_BASIC) {
13328 	if (type->builtInType == valType)
13329 	    return(1);
13330 	return (0);
13331     } else
13332 	return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13333 
13334     return (0);
13335 }
13336 
13337 static xmlSchemaTypePtr
13338 xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
13339 {
13340     if (type == NULL)
13341 	return (NULL);
13342     if (WXS_IS_COMPLEX(type))
13343 	return (NULL);
13344     if (type->type == XML_SCHEMA_TYPE_BASIC)
13345 	return(type);
13346     return(xmlSchemaQueryBuiltInType(type->subtypes));
13347 }
13348 #endif
13349 
13350 /**
13351  * xmlSchemaGetPrimitiveType:
13352  * @type:  the simpleType definition
13353  *
13354  * Returns the primitive type of the given type or
13355  * NULL in case of error.
13356  */
13357 static xmlSchemaTypePtr
xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)13358 xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
13359 {
13360 
13361     while (type != NULL) {
13362 	/*
13363 	* Note that anySimpleType is actually not a primitive type
13364 	* but we need that here.
13365 	*/
13366 	if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13367 	   (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
13368 	    return (type);
13369 	type = type->baseType;
13370     }
13371 
13372     return (NULL);
13373 }
13374 
13375 #if 0
13376 /**
13377  * xmlSchemaGetBuiltInTypeAncestor:
13378  * @type:  the simpleType definition
13379  *
13380  * Returns the primitive type of the given type or
13381  * NULL in case of error.
13382  */
13383 static xmlSchemaTypePtr
13384 xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
13385 {
13386     if (WXS_IS_LIST(type) || WXS_IS_UNION(type))
13387 	return (0);
13388     while (type != NULL) {
13389 	if (type->type == XML_SCHEMA_TYPE_BASIC)
13390 	    return (type);
13391 	type = type->baseType;
13392     }
13393 
13394     return (NULL);
13395 }
13396 #endif
13397 
13398 /**
13399  * xmlSchemaCloneWildcardNsConstraints:
13400  * @ctxt:  the schema parser context
13401  * @dest:  the destination wildcard
13402  * @source: the source wildcard
13403  *
13404  * Clones the namespace constraints of source
13405  * and assigns them to dest.
13406  * Returns -1 on internal error, 0 otherwise.
13407  */
13408 static int
xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,xmlSchemaWildcardPtr dest,xmlSchemaWildcardPtr source)13409 xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
13410 				    xmlSchemaWildcardPtr dest,
13411 				    xmlSchemaWildcardPtr source)
13412 {
13413     xmlSchemaWildcardNsPtr cur, tmp, last;
13414 
13415     if ((source == NULL) || (dest == NULL))
13416 	return(-1);
13417     dest->any = source->any;
13418     cur = source->nsSet;
13419     last = NULL;
13420     while (cur != NULL) {
13421 	tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13422 	if (tmp == NULL)
13423 	    return(-1);
13424 	tmp->value = cur->value;
13425 	if (last == NULL)
13426 	    dest->nsSet = tmp;
13427 	else
13428 	    last->next = tmp;
13429 	last = tmp;
13430 	cur = cur->next;
13431     }
13432     if (dest->negNsSet != NULL)
13433 	xmlSchemaFreeWildcardNsSet(dest->negNsSet);
13434     if (source->negNsSet != NULL) {
13435 	dest->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13436 	if (dest->negNsSet == NULL)
13437 	    return(-1);
13438 	dest->negNsSet->value = source->negNsSet->value;
13439     } else
13440 	dest->negNsSet = NULL;
13441     return(0);
13442 }
13443 
13444 /**
13445  * xmlSchemaUnionWildcards:
13446  * @ctxt:  the schema parser context
13447  * @completeWild:  the first wildcard
13448  * @curWild: the second wildcard
13449  *
13450  * Unions the namespace constraints of the given wildcards.
13451  * @completeWild will hold the resulting union.
13452  * Returns a positive error code on failure, -1 in case of an
13453  * internal error, 0 otherwise.
13454  */
13455 static int
xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,xmlSchemaWildcardPtr completeWild,xmlSchemaWildcardPtr curWild)13456 xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
13457 			    xmlSchemaWildcardPtr completeWild,
13458 			    xmlSchemaWildcardPtr curWild)
13459 {
13460     xmlSchemaWildcardNsPtr cur, curB, tmp;
13461 
13462     /*
13463     * 1 If O1 and O2 are the same value, then that value must be the
13464     * value.
13465     */
13466     if ((completeWild->any == curWild->any) &&
13467 	((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13468 	((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13469 
13470 	if ((completeWild->negNsSet == NULL) ||
13471 	    (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13472 
13473 	    if (completeWild->nsSet != NULL) {
13474 		int found = 0;
13475 
13476 		/*
13477 		* Check equality of sets.
13478 		*/
13479 		cur = completeWild->nsSet;
13480 		while (cur != NULL) {
13481 		    found = 0;
13482 		    curB = curWild->nsSet;
13483 		    while (curB != NULL) {
13484 			if (cur->value == curB->value) {
13485 			    found = 1;
13486 			    break;
13487 			}
13488 			curB = curB->next;
13489 		    }
13490 		    if (!found)
13491 			break;
13492 		    cur = cur->next;
13493 		}
13494 		if (found)
13495 		    return(0);
13496 	    } else
13497 		return(0);
13498 	}
13499     }
13500     /*
13501     * 2 If either O1 or O2 is any, then any must be the value
13502     */
13503     if (completeWild->any != curWild->any) {
13504 	if (completeWild->any == 0) {
13505 	    completeWild->any = 1;
13506 	    if (completeWild->nsSet != NULL) {
13507 		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13508 		completeWild->nsSet = NULL;
13509 	    }
13510 	    if (completeWild->negNsSet != NULL) {
13511 		xmlFree(completeWild->negNsSet);
13512 		completeWild->negNsSet = NULL;
13513 	    }
13514 	}
13515 	return (0);
13516     }
13517     /*
13518     * 3 If both O1 and O2 are sets of (namespace names or `absent`),
13519     * then the union of those sets must be the value.
13520     */
13521     if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13522 	int found;
13523 	xmlSchemaWildcardNsPtr start;
13524 
13525 	cur = curWild->nsSet;
13526 	start = completeWild->nsSet;
13527 	while (cur != NULL) {
13528 	    found = 0;
13529 	    curB = start;
13530 	    while (curB != NULL) {
13531 		if (cur->value == curB->value) {
13532 		    found = 1;
13533 		    break;
13534 		}
13535 		curB = curB->next;
13536 	    }
13537 	    if (!found) {
13538 		tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13539 		if (tmp == NULL)
13540 		    return (-1);
13541 		tmp->value = cur->value;
13542 		tmp->next = completeWild->nsSet;
13543 		completeWild->nsSet = tmp;
13544 	    }
13545 	    cur = cur->next;
13546 	}
13547 
13548 	return(0);
13549     }
13550     /*
13551     * 4 If the two are negations of different values (namespace names
13552     * or `absent`), then a pair of not and `absent` must be the value.
13553     */
13554     if ((completeWild->negNsSet != NULL) &&
13555 	(curWild->negNsSet != NULL) &&
13556 	(completeWild->negNsSet->value != curWild->negNsSet->value)) {
13557 	completeWild->negNsSet->value = NULL;
13558 
13559 	return(0);
13560     }
13561     /*
13562      * 5.
13563      */
13564     if (((completeWild->negNsSet != NULL) &&
13565 	(completeWild->negNsSet->value != NULL) &&
13566 	(curWild->nsSet != NULL)) ||
13567 	((curWild->negNsSet != NULL) &&
13568 	(curWild->negNsSet->value != NULL) &&
13569 	(completeWild->nsSet != NULL))) {
13570 
13571 	int nsFound, absentFound = 0;
13572 
13573 	if (completeWild->nsSet != NULL) {
13574 	    cur = completeWild->nsSet;
13575 	    curB = curWild->negNsSet;
13576 	} else {
13577 	    cur = curWild->nsSet;
13578 	    curB = completeWild->negNsSet;
13579 	}
13580 	nsFound = 0;
13581 	while (cur != NULL) {
13582 	    if (cur->value == NULL)
13583 		absentFound = 1;
13584 	    else if (cur->value == curB->value)
13585 		nsFound = 1;
13586 	    if (nsFound && absentFound)
13587 		break;
13588 	    cur = cur->next;
13589 	}
13590 
13591 	if (nsFound && absentFound) {
13592 	    /*
13593 	    * 5.1 If the set S includes both the negated namespace
13594 	    * name and `absent`, then any must be the value.
13595 	    */
13596 	    completeWild->any = 1;
13597 	    if (completeWild->nsSet != NULL) {
13598 		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13599 		completeWild->nsSet = NULL;
13600 	    }
13601 	    if (completeWild->negNsSet != NULL) {
13602 		xmlFree(completeWild->negNsSet);
13603 		completeWild->negNsSet = NULL;
13604 	    }
13605 	} else if (nsFound && (!absentFound)) {
13606 	    /*
13607 	    * 5.2 If the set S includes the negated namespace name
13608 	    * but not `absent`, then a pair of not and `absent` must
13609 	    * be the value.
13610 	    */
13611 	    if (completeWild->nsSet != NULL) {
13612 		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13613 		completeWild->nsSet = NULL;
13614 	    }
13615 	    if (completeWild->negNsSet == NULL) {
13616 		completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13617 		if (completeWild->negNsSet == NULL)
13618 		    return (-1);
13619 	    }
13620 	    completeWild->negNsSet->value = NULL;
13621 	} else if ((!nsFound) && absentFound) {
13622 	    /*
13623 	    * 5.3 If the set S includes `absent` but not the negated
13624 	    * namespace name, then the union is not expressible.
13625 	    */
13626 	    xmlSchemaPErr(ctxt, completeWild->node,
13627 		XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
13628 		"The union of the wildcard is not expressible.\n",
13629 		NULL, NULL);
13630 	    return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
13631 	} else if ((!nsFound) && (!absentFound)) {
13632 	    /*
13633 	    * 5.4 If the set S does not include either the negated namespace
13634 	    * name or `absent`, then whichever of O1 or O2 is a pair of not
13635 	    * and a namespace name must be the value.
13636 	    */
13637 	    if (completeWild->negNsSet == NULL) {
13638 		if (completeWild->nsSet != NULL) {
13639 		    xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13640 		    completeWild->nsSet = NULL;
13641 		}
13642 		completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13643 		if (completeWild->negNsSet == NULL)
13644 		    return (-1);
13645 		completeWild->negNsSet->value = curWild->negNsSet->value;
13646 	    }
13647 	}
13648 	return (0);
13649     }
13650     /*
13651      * 6.
13652      */
13653     if (((completeWild->negNsSet != NULL) &&
13654 	(completeWild->negNsSet->value == NULL) &&
13655 	(curWild->nsSet != NULL)) ||
13656 	((curWild->negNsSet != NULL) &&
13657 	(curWild->negNsSet->value == NULL) &&
13658 	(completeWild->nsSet != NULL))) {
13659 
13660 	if (completeWild->nsSet != NULL) {
13661 	    cur = completeWild->nsSet;
13662 	} else {
13663 	    cur = curWild->nsSet;
13664 	}
13665 	while (cur != NULL) {
13666 	    if (cur->value == NULL) {
13667 		/*
13668 		* 6.1 If the set S includes `absent`, then any must be the
13669 		* value.
13670 		*/
13671 		completeWild->any = 1;
13672 		if (completeWild->nsSet != NULL) {
13673 		    xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13674 		    completeWild->nsSet = NULL;
13675 		}
13676 		if (completeWild->negNsSet != NULL) {
13677 		    xmlFree(completeWild->negNsSet);
13678 		    completeWild->negNsSet = NULL;
13679 		}
13680 		return (0);
13681 	    }
13682 	    cur = cur->next;
13683 	}
13684 	if (completeWild->negNsSet == NULL) {
13685 	    /*
13686 	    * 6.2 If the set S does not include `absent`, then a pair of not
13687 	    * and `absent` must be the value.
13688 	    */
13689 	    if (completeWild->nsSet != NULL) {
13690 		xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13691 		completeWild->nsSet = NULL;
13692 	    }
13693 	    completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13694 	    if (completeWild->negNsSet == NULL)
13695 		return (-1);
13696 	    completeWild->negNsSet->value = NULL;
13697 	}
13698 	return (0);
13699     }
13700     return (0);
13701 
13702 }
13703 
13704 /**
13705  * xmlSchemaIntersectWildcards:
13706  * @ctxt:  the schema parser context
13707  * @completeWild:  the first wildcard
13708  * @curWild: the second wildcard
13709  *
13710  * Intersects the namespace constraints of the given wildcards.
13711  * @completeWild will hold the resulting intersection.
13712  * Returns a positive error code on failure, -1 in case of an
13713  * internal error, 0 otherwise.
13714  */
13715 static int
xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,xmlSchemaWildcardPtr completeWild,xmlSchemaWildcardPtr curWild)13716 xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
13717 			    xmlSchemaWildcardPtr completeWild,
13718 			    xmlSchemaWildcardPtr curWild)
13719 {
13720     xmlSchemaWildcardNsPtr cur, curB, prev,  tmp;
13721 
13722     /*
13723     * 1 If O1 and O2 are the same value, then that value must be the
13724     * value.
13725     */
13726     if ((completeWild->any == curWild->any) &&
13727 	((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13728 	((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13729 
13730 	if ((completeWild->negNsSet == NULL) ||
13731 	    (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13732 
13733 	    if (completeWild->nsSet != NULL) {
13734 		int found = 0;
13735 
13736 		/*
13737 		* Check equality of sets.
13738 		*/
13739 		cur = completeWild->nsSet;
13740 		while (cur != NULL) {
13741 		    found = 0;
13742 		    curB = curWild->nsSet;
13743 		    while (curB != NULL) {
13744 			if (cur->value == curB->value) {
13745 			    found = 1;
13746 			    break;
13747 			}
13748 			curB = curB->next;
13749 		    }
13750 		    if (!found)
13751 			break;
13752 		    cur = cur->next;
13753 		}
13754 		if (found)
13755 		    return(0);
13756 	    } else
13757 		return(0);
13758 	}
13759     }
13760     /*
13761     * 2 If either O1 or O2 is any, then the other must be the value.
13762     */
13763     if ((completeWild->any != curWild->any) && (completeWild->any)) {
13764 	if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13765 	    return(-1);
13766 	return(0);
13767     }
13768     /*
13769     * 3 If either O1 or O2 is a pair of not and a value (a namespace
13770     * name or `absent`) and the other is a set of (namespace names or
13771     * `absent`), then that set, minus the negated value if it was in
13772     * the set, minus `absent` if it was in the set, must be the value.
13773     */
13774     if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
13775 	((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
13776 	const xmlChar *neg;
13777 
13778 	if (completeWild->nsSet == NULL) {
13779 	    neg = completeWild->negNsSet->value;
13780 	    if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13781 		return(-1);
13782 	} else
13783 	    neg = curWild->negNsSet->value;
13784 	/*
13785 	* Remove absent and negated.
13786 	*/
13787 	prev = NULL;
13788 	cur = completeWild->nsSet;
13789 	while (cur != NULL) {
13790 	    if (cur->value == NULL) {
13791 		if (prev == NULL)
13792 		    completeWild->nsSet = cur->next;
13793 		else
13794 		    prev->next = cur->next;
13795 		xmlFree(cur);
13796 		break;
13797 	    }
13798 	    prev = cur;
13799 	    cur = cur->next;
13800 	}
13801 	if (neg != NULL) {
13802 	    prev = NULL;
13803 	    cur = completeWild->nsSet;
13804 	    while (cur != NULL) {
13805 		if (cur->value == neg) {
13806 		    if (prev == NULL)
13807 			completeWild->nsSet = cur->next;
13808 		    else
13809 			prev->next = cur->next;
13810 		    xmlFree(cur);
13811 		    break;
13812 		}
13813 		prev = cur;
13814 		cur = cur->next;
13815 	    }
13816 	}
13817 
13818 	return(0);
13819     }
13820     /*
13821     * 4 If both O1 and O2 are sets of (namespace names or `absent`),
13822     * then the intersection of those sets must be the value.
13823     */
13824     if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13825 	int found;
13826 
13827 	cur = completeWild->nsSet;
13828 	prev = NULL;
13829 	while (cur != NULL) {
13830 	    found = 0;
13831 	    curB = curWild->nsSet;
13832 	    while (curB != NULL) {
13833 		if (cur->value == curB->value) {
13834 		    found = 1;
13835 		    break;
13836 		}
13837 		curB = curB->next;
13838 	    }
13839 	    if (!found) {
13840 		if (prev == NULL)
13841 		    completeWild->nsSet = cur->next;
13842 		else
13843 		    prev->next = cur->next;
13844 		tmp = cur->next;
13845 		xmlFree(cur);
13846 		cur = tmp;
13847 		continue;
13848 	    }
13849 	    prev = cur;
13850 	    cur = cur->next;
13851 	}
13852 
13853 	return(0);
13854     }
13855     /* 5 If the two are negations of different namespace names,
13856     * then the intersection is not expressible
13857     */
13858     if ((completeWild->negNsSet != NULL) &&
13859 	(curWild->negNsSet != NULL) &&
13860 	(completeWild->negNsSet->value != curWild->negNsSet->value) &&
13861 	(completeWild->negNsSet->value != NULL) &&
13862 	(curWild->negNsSet->value != NULL)) {
13863 
13864 	xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
13865 	    "The intersection of the wildcard is not expressible.\n",
13866 	    NULL, NULL);
13867 	return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
13868     }
13869     /*
13870     * 6 If the one is a negation of a namespace name and the other
13871     * is a negation of `absent`, then the one which is the negation
13872     * of a namespace name must be the value.
13873     */
13874     if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
13875 	(completeWild->negNsSet->value != curWild->negNsSet->value) &&
13876 	(completeWild->negNsSet->value == NULL)) {
13877 	completeWild->negNsSet->value =  curWild->negNsSet->value;
13878     }
13879     return(0);
13880 }
13881 
13882 /**
13883  * xmlSchemaIsWildcardNsConstraintSubset:
13884  * @ctxt:  the schema parser context
13885  * @sub:  the first wildcard
13886  * @super: the second wildcard
13887  *
13888  * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
13889  *
13890  * Returns 0 if the namespace constraint of @sub is an intensional
13891  * subset of @super, 1 otherwise.
13892  */
13893 static int
xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,xmlSchemaWildcardPtr super)13894 xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
13895 			  xmlSchemaWildcardPtr super)
13896 {
13897     /*
13898     * 1 super must be any.
13899     */
13900     if (super->any)
13901 	return (0);
13902     /*
13903     * 2.1 sub must be a pair of not and a namespace name or `absent`.
13904     * 2.2 super must be a pair of not and the same value.
13905     */
13906     if ((sub->negNsSet != NULL) &&
13907 	(super->negNsSet != NULL) &&
13908 	(sub->negNsSet->value == super->negNsSet->value))
13909 	return (0);
13910     /*
13911     * 3.1 sub must be a set whose members are either namespace names or `absent`.
13912     */
13913     if (sub->nsSet != NULL) {
13914 	/*
13915 	* 3.2.1 super must be the same set or a superset thereof.
13916 	*/
13917 	if (super->nsSet != NULL) {
13918 	    xmlSchemaWildcardNsPtr cur, curB;
13919 	    int found = 0;
13920 
13921 	    cur = sub->nsSet;
13922 	    while (cur != NULL) {
13923 		found = 0;
13924 		curB = super->nsSet;
13925 		while (curB != NULL) {
13926 		    if (cur->value == curB->value) {
13927 			found = 1;
13928 			break;
13929 		    }
13930 		    curB = curB->next;
13931 		}
13932 		if (!found)
13933 		    return (1);
13934 		cur = cur->next;
13935 	    }
13936 	    if (found)
13937 		return (0);
13938 	} else if (super->negNsSet != NULL) {
13939 	    xmlSchemaWildcardNsPtr cur;
13940 	    /*
13941 	    * 3.2.2 super must be a pair of not and a namespace name or
13942 	    * `absent` and that value must not be in sub's set.
13943 	    */
13944 	    cur = sub->nsSet;
13945 	    while (cur != NULL) {
13946 		if (cur->value == super->negNsSet->value)
13947 		    return (1);
13948 		cur = cur->next;
13949 	    }
13950 	    return (0);
13951 	}
13952     }
13953     return (1);
13954 }
13955 
13956 static int
xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse,int * fixed,const xmlChar ** value,xmlSchemaValPtr * val)13957 xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse,
13958 				     int *fixed,
13959 				     const xmlChar **value,
13960 				     xmlSchemaValPtr *val)
13961 {
13962     *fixed = 0;
13963     *value = NULL;
13964     if (val != 0)
13965 	*val = NULL;
13966 
13967     if (attruse->defValue != NULL) {
13968 	*value = attruse->defValue;
13969 	if (val != NULL)
13970 	    *val = attruse->defVal;
13971 	if (attruse->flags & XML_SCHEMA_ATTR_USE_FIXED)
13972 	    *fixed = 1;
13973 	return(1);
13974     } else if ((attruse->attrDecl != NULL) &&
13975 	(attruse->attrDecl->defValue != NULL)) {
13976 	*value = attruse->attrDecl->defValue;
13977 	if (val != NULL)
13978 	    *val = attruse->attrDecl->defVal;
13979 	if (attruse->attrDecl->flags & XML_SCHEMAS_ATTR_FIXED)
13980 	    *fixed = 1;
13981 	return(1);
13982     }
13983     return(0);
13984 }
13985 /**
13986  * xmlSchemaCheckCVCWildcardNamespace:
13987  * @wild:  the wildcard
13988  * @ns:  the namespace
13989  *
13990  * Validation Rule: Wildcard allows Namespace Name
13991  * (cvc-wildcard-namespace)
13992  *
13993  * Returns 0 if the given namespace matches the wildcard,
13994  * 1 otherwise and -1 on API errors.
13995  */
13996 static int
xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,const xmlChar * ns)13997 xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
13998 				   const xmlChar* ns)
13999 {
14000     if (wild == NULL)
14001 	return(-1);
14002 
14003     if (wild->any)
14004 	return(0);
14005     else if (wild->nsSet != NULL) {
14006 	xmlSchemaWildcardNsPtr cur;
14007 
14008 	cur = wild->nsSet;
14009 	while (cur != NULL) {
14010 	    if (xmlStrEqual(cur->value, ns))
14011 		return(0);
14012 	    cur = cur->next;
14013 	}
14014     } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
14015 	(!xmlStrEqual(wild->negNsSet->value, ns)))
14016 	return(0);
14017 
14018     return(1);
14019 }
14020 
14021 #define XML_SCHEMA_ACTION_DERIVE 0
14022 #define XML_SCHEMA_ACTION_REDEFINE 1
14023 
14024 #define WXS_ACTION_STR(a) \
14025 ((a) == XML_SCHEMA_ACTION_DERIVE) ? (const xmlChar *) "base" : (const xmlChar *) "redefined"
14026 
14027 /*
14028 * Schema Component Constraint:
14029 *   Derivation Valid (Restriction, Complex)
14030 *   derivation-ok-restriction (2) - (4)
14031 *
14032 * ATTENTION:
14033 * In XML Schema 1.1 this will be:
14034 * Validation Rule:
14035 *     Checking complex type subsumption (practicalSubsumption) (1, 2 and 3)
14036 *
14037 */
14038 static int
xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt,int action,xmlSchemaBasicItemPtr item,xmlSchemaBasicItemPtr baseItem,xmlSchemaItemListPtr uses,xmlSchemaItemListPtr baseUses,xmlSchemaWildcardPtr wild,xmlSchemaWildcardPtr baseWild)14039 xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt,
14040 				       int action,
14041 				       xmlSchemaBasicItemPtr item,
14042 				       xmlSchemaBasicItemPtr baseItem,
14043 				       xmlSchemaItemListPtr uses,
14044 				       xmlSchemaItemListPtr baseUses,
14045 				       xmlSchemaWildcardPtr wild,
14046 				       xmlSchemaWildcardPtr baseWild)
14047 {
14048     xmlSchemaAttributeUsePtr cur = NULL, bcur;
14049     int i, j, found; /* err = 0; */
14050     const xmlChar *bEffValue;
14051     int effFixed;
14052 
14053     if (uses != NULL) {
14054 	for (i = 0; i < uses->nbItems; i++) {
14055 	    cur = uses->items[i];
14056 	    found = 0;
14057 	    if (baseUses == NULL)
14058 		goto not_found;
14059 	    for (j = 0; j < baseUses->nbItems; j++) {
14060 		bcur = baseUses->items[j];
14061 		if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14062 			WXS_ATTRUSE_DECL_NAME(bcur)) &&
14063 		    (WXS_ATTRUSE_DECL_TNS(cur) ==
14064 			WXS_ATTRUSE_DECL_TNS(bcur)))
14065 		{
14066 		    /*
14067 		    * (2.1) "If there is an attribute use in the {attribute
14068 		    * uses} of the {base type definition} (call this B) whose
14069 		    * {attribute declaration} has the same {name} and {target
14070 		    * namespace}, then  all of the following must be true:"
14071 		    */
14072 		    found = 1;
14073 
14074 		    if ((cur->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
14075 			(bcur->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED))
14076 		    {
14077 			xmlChar *str = NULL;
14078 			/*
14079 			* (2.1.1) "one of the following must be true:"
14080 			* (2.1.1.1) "B's {required} is false."
14081 			* (2.1.1.2) "R's {required} is true."
14082 			*/
14083 			xmlSchemaPAttrUseErr4(pctxt,
14084 			    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
14085 			    WXS_ITEM_NODE(item), item, cur,
14086 			    "The 'optional' attribute use is inconsistent "
14087 			    "with the corresponding 'required' attribute use of "
14088 			    "the %s %s",
14089 			    WXS_ACTION_STR(action),
14090 			    xmlSchemaGetComponentDesignation(&str, baseItem),
14091 			    NULL, NULL);
14092 			FREE_AND_NULL(str);
14093 			/* err = pctxt->err; */
14094 		    } else if (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
14095 			WXS_ATTRUSE_TYPEDEF(cur),
14096 			WXS_ATTRUSE_TYPEDEF(bcur), 0) != 0)
14097 		    {
14098 			xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
14099 
14100 			/*
14101 			* SPEC (2.1.2) "R's {attribute declaration}'s
14102 			* {type definition} must be validly derived from
14103 			* B's {type definition} given the empty set as
14104 			* defined in Type Derivation OK (Simple) ($3.14.6)."
14105 			*/
14106 			xmlSchemaPAttrUseErr4(pctxt,
14107 			    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
14108 			    WXS_ITEM_NODE(item), item, cur,
14109 			    "The attribute declaration's %s "
14110 			    "is not validly derived from "
14111 			    "the corresponding %s of the "
14112 			    "attribute declaration in the %s %s",
14113 			    xmlSchemaGetComponentDesignation(&strA,
14114 				WXS_ATTRUSE_TYPEDEF(cur)),
14115 			    xmlSchemaGetComponentDesignation(&strB,
14116 				WXS_ATTRUSE_TYPEDEF(bcur)),
14117 			    WXS_ACTION_STR(action),
14118 			    xmlSchemaGetComponentDesignation(&strC, baseItem));
14119 			    /* xmlSchemaGetComponentDesignation(&str, baseItem), */
14120 			FREE_AND_NULL(strA);
14121 			FREE_AND_NULL(strB);
14122 			FREE_AND_NULL(strC);
14123 			/* err = pctxt->err; */
14124 		    } else {
14125 			/*
14126 			* 2.1.3 [Definition:]  Let the effective value
14127 			* constraint of an attribute use be its {value
14128 			* constraint}, if present, otherwise its {attribute
14129 			* declaration}'s {value constraint} .
14130 			*/
14131 			xmlSchemaGetEffectiveValueConstraint(bcur,
14132 			    &effFixed, &bEffValue, NULL);
14133 			/*
14134 			* 2.1.3 ... one of the following must be true
14135 			*
14136 			* 2.1.3.1 B's `effective value constraint` is
14137 			* `absent` or default.
14138 			*/
14139 			if ((bEffValue != NULL) &&
14140 			    (effFixed == 1)) {
14141 			    const xmlChar *rEffValue = NULL;
14142 
14143 			    xmlSchemaGetEffectiveValueConstraint(bcur,
14144 				&effFixed, &rEffValue, NULL);
14145 			    /*
14146 			    * 2.1.3.2 R's `effective value constraint` is
14147 			    * fixed with the same string as B's.
14148 			    * MAYBE TODO: Compare the computed values.
14149 			    *       Hmm, it says "same string" so
14150 			    *       string-equality might really be sufficient.
14151 			    */
14152 			    if ((effFixed == 0) ||
14153 				(! WXS_ARE_DEFAULT_STR_EQUAL(rEffValue, bEffValue)))
14154 			    {
14155 				xmlChar *str = NULL;
14156 
14157 				xmlSchemaPAttrUseErr4(pctxt,
14158 				    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
14159 				    WXS_ITEM_NODE(item), item, cur,
14160 				    "The effective value constraint of the "
14161 				    "attribute use is inconsistent with "
14162 				    "its correspondent in the %s %s",
14163 				    WXS_ACTION_STR(action),
14164 				    xmlSchemaGetComponentDesignation(&str,
14165 					baseItem),
14166 				    NULL, NULL);
14167 				FREE_AND_NULL(str);
14168 				/* err = pctxt->err; */
14169 			    }
14170 			}
14171 		    }
14172 		    break;
14173 		}
14174 	    }
14175 not_found:
14176 	    if (!found) {
14177 		/*
14178 		* (2.2) "otherwise the {base type definition} must have an
14179 		* {attribute wildcard} and the {target namespace} of the
14180 		* R's {attribute declaration} must be `valid` with respect
14181 		* to that wildcard, as defined in Wildcard allows Namespace
14182 		* Name ($3.10.4)."
14183 		*/
14184 		if ((baseWild == NULL) ||
14185 		    (xmlSchemaCheckCVCWildcardNamespace(baseWild,
14186 		    (WXS_ATTRUSE_DECL(cur))->targetNamespace) != 0))
14187 		{
14188 		    xmlChar *str = NULL;
14189 
14190 		    xmlSchemaPAttrUseErr4(pctxt,
14191 			XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
14192 			WXS_ITEM_NODE(item), item, cur,
14193 			"Neither a matching attribute use, "
14194 			"nor a matching wildcard exists in the %s %s",
14195 			WXS_ACTION_STR(action),
14196 			xmlSchemaGetComponentDesignation(&str, baseItem),
14197 			NULL, NULL);
14198 		    FREE_AND_NULL(str);
14199 		    /* err = pctxt->err; */
14200 		}
14201 	    }
14202 	}
14203     }
14204     /*
14205     * SPEC derivation-ok-restriction (3):
14206     * (3) "For each attribute use in the {attribute uses} of the {base type
14207     * definition} whose {required} is true, there must be an attribute
14208     * use with an {attribute declaration} with the same {name} and
14209     * {target namespace} as its {attribute declaration} in the {attribute
14210     * uses} of the complex type definition itself whose {required} is true.
14211     */
14212     if (baseUses != NULL) {
14213 	for (j = 0; j < baseUses->nbItems; j++) {
14214 	    bcur = baseUses->items[j];
14215 	    if (bcur->occurs != XML_SCHEMAS_ATTR_USE_REQUIRED)
14216 		continue;
14217 	    found = 0;
14218 	    if (uses != NULL) {
14219 		for (i = 0; i < uses->nbItems; i++) {
14220 		    cur = uses->items[i];
14221 		    if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14222 			WXS_ATTRUSE_DECL_NAME(bcur)) &&
14223 			(WXS_ATTRUSE_DECL_TNS(cur) ==
14224 			WXS_ATTRUSE_DECL_TNS(bcur))) {
14225 			found = 1;
14226 			break;
14227 		    }
14228 		}
14229 	    }
14230 	    if (!found) {
14231 		xmlChar *strA = NULL, *strB = NULL;
14232 
14233 		xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14234 		    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
14235 		    NULL, item,
14236 		    "A matching attribute use for the "
14237 		    "'required' %s of the %s %s is missing",
14238 		    xmlSchemaGetComponentDesignation(&strA, bcur),
14239 		    WXS_ACTION_STR(action),
14240 		    xmlSchemaGetComponentDesignation(&strB, baseItem),
14241 		    NULL);
14242 		FREE_AND_NULL(strA);
14243 		FREE_AND_NULL(strB);
14244 	    }
14245 	}
14246     }
14247     /*
14248     * derivation-ok-restriction (4)
14249     */
14250     if (wild != NULL) {
14251 	/*
14252 	* (4) "If there is an {attribute wildcard}, all of the
14253 	* following must be true:"
14254 	*/
14255 	if (baseWild == NULL) {
14256 	    xmlChar *str = NULL;
14257 
14258 	    /*
14259 	    * (4.1) "The {base type definition} must also have one."
14260 	    */
14261 	    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14262 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
14263 		NULL, item,
14264 		"The %s has an attribute wildcard, "
14265 		"but the %s %s '%s' does not have one",
14266 		WXS_ITEM_TYPE_NAME(item),
14267 		WXS_ACTION_STR(action),
14268 		WXS_ITEM_TYPE_NAME(baseItem),
14269 		xmlSchemaGetComponentQName(&str, baseItem));
14270 	    FREE_AND_NULL(str);
14271 	    return(pctxt->err);
14272 	} else if ((baseWild->any == 0) &&
14273 		xmlSchemaCheckCOSNSSubset(wild, baseWild))
14274 	{
14275 	    xmlChar *str = NULL;
14276 	    /*
14277 	    * (4.2) "The complex type definition's {attribute wildcard}'s
14278 	    * {namespace constraint} must be a subset of the {base type
14279 	    * definition}'s {attribute wildcard}'s {namespace constraint},
14280 	    * as defined by Wildcard Subset ($3.10.6)."
14281 	    */
14282 	    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14283 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
14284 		NULL, item,
14285 		"The attribute wildcard is not a valid "
14286 		"subset of the wildcard in the %s %s '%s'",
14287 		WXS_ACTION_STR(action),
14288 		WXS_ITEM_TYPE_NAME(baseItem),
14289 		xmlSchemaGetComponentQName(&str, baseItem),
14290 		NULL);
14291 	    FREE_AND_NULL(str);
14292 	    return(pctxt->err);
14293 	}
14294 	/* 4.3 Unless the {base type definition} is the `ur-type
14295 	* definition`, the complex type definition's {attribute
14296 	* wildcard}'s {process contents} must be identical to or
14297 	* stronger than the {base type definition}'s {attribute
14298 	* wildcard}'s {process contents}, where strict is stronger
14299 	* than lax is stronger than skip.
14300 	*/
14301 	if ((! WXS_IS_ANYTYPE(baseItem)) &&
14302 	    (wild->processContents < baseWild->processContents)) {
14303 	    xmlChar *str = NULL;
14304 	    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14305 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
14306 		NULL, baseItem,
14307 		"The {process contents} of the attribute wildcard is "
14308 		"weaker than the one in the %s %s '%s'",
14309 		WXS_ACTION_STR(action),
14310 		WXS_ITEM_TYPE_NAME(baseItem),
14311 		xmlSchemaGetComponentQName(&str, baseItem),
14312 		NULL);
14313 	    FREE_AND_NULL(str)
14314 		return(pctxt->err);
14315 	}
14316     }
14317     return(0);
14318 }
14319 
14320 
14321 static int
14322 xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
14323 				  xmlSchemaBasicItemPtr item,
14324 				  xmlSchemaWildcardPtr *completeWild,
14325 				  xmlSchemaItemListPtr list,
14326 				  xmlSchemaItemListPtr prohibs);
14327 /**
14328  * xmlSchemaFixupTypeAttributeUses:
14329  * @ctxt:  the schema parser context
14330  * @type:  the complex type definition
14331  *
14332  *
14333  * Builds the wildcard and the attribute uses on the given complex type.
14334  * Returns -1 if an internal error occurs, 0 otherwise.
14335  *
14336  * ATTENTION TODO: Experimentally this uses pointer comparisons for
14337  * strings, so recheck this if we start to hardcode some schemata, since
14338  * they might not be in the same dict.
14339  * NOTE: It is allowed to "extend" the xs:anyType type.
14340  */
14341 static int
xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)14342 xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt,
14343 				  xmlSchemaTypePtr type)
14344 {
14345     xmlSchemaTypePtr baseType = NULL;
14346     xmlSchemaAttributeUsePtr use;
14347     xmlSchemaItemListPtr uses, baseUses, prohibs = NULL;
14348 
14349     if (type->baseType == NULL) {
14350 	PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14351 	    "no base type");
14352         return (-1);
14353     }
14354     baseType = type->baseType;
14355     if (WXS_IS_TYPE_NOT_FIXED(baseType))
14356 	if (xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt) == -1)
14357 	    return(-1);
14358 
14359     uses = type->attrUses;
14360     baseUses = baseType->attrUses;
14361     /*
14362     * Expand attribute group references. And build the 'complete'
14363     * wildcard, i.e. intersect multiple wildcards.
14364     * Move attribute prohibitions into a separate list.
14365     */
14366     if (uses != NULL) {
14367 	if (WXS_IS_RESTRICTION(type)) {
14368 	    /*
14369 	    * This one will transfer all attr. prohibitions
14370 	    * into pctxt->attrProhibs.
14371 	    */
14372 	    if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14373 		WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14374 		pctxt->attrProhibs) == -1)
14375 	    {
14376 		PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14377 		"failed to expand attributes");
14378                 return(-1);
14379 	    }
14380 	    if (pctxt->attrProhibs->nbItems != 0)
14381 		prohibs = pctxt->attrProhibs;
14382 	} else {
14383 	    if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14384 		WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14385 		NULL) == -1)
14386 	    {
14387 		PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14388 		"failed to expand attributes");
14389                 return(-1);
14390 	    }
14391 	}
14392     }
14393     /*
14394     * Inherit the attribute uses of the base type.
14395     */
14396     if (baseUses != NULL) {
14397 	int i, j;
14398 	xmlSchemaAttributeUseProhibPtr pro;
14399 
14400 	if (WXS_IS_RESTRICTION(type)) {
14401 	    int usesCount;
14402 	    xmlSchemaAttributeUsePtr tmp;
14403 
14404 	    if (uses != NULL)
14405 		usesCount = uses->nbItems;
14406 	    else
14407 		usesCount = 0;
14408 
14409 	    /* Restriction. */
14410 	    for (i = 0; i < baseUses->nbItems; i++) {
14411 		use = baseUses->items[i];
14412 		if (prohibs) {
14413 		    /*
14414 		    * Filter out prohibited uses.
14415 		    */
14416 		    for (j = 0; j < prohibs->nbItems; j++) {
14417 			pro = prohibs->items[j];
14418 			if ((WXS_ATTRUSE_DECL_NAME(use) == pro->name) &&
14419 			    (WXS_ATTRUSE_DECL_TNS(use) ==
14420 				pro->targetNamespace))
14421 			{
14422 			    goto inherit_next;
14423 			}
14424 		    }
14425 		}
14426 		if (usesCount) {
14427 		    /*
14428 		    * Filter out existing uses.
14429 		    */
14430 		    for (j = 0; j < usesCount; j++) {
14431 			tmp = uses->items[j];
14432 			if ((WXS_ATTRUSE_DECL_NAME(use) ==
14433 				WXS_ATTRUSE_DECL_NAME(tmp)) &&
14434 			    (WXS_ATTRUSE_DECL_TNS(use) ==
14435 				WXS_ATTRUSE_DECL_TNS(tmp)))
14436 			{
14437 			    goto inherit_next;
14438 			}
14439 		    }
14440 		}
14441 		if (uses == NULL) {
14442 		    type->attrUses = xmlSchemaItemListCreate();
14443 		    if (type->attrUses == NULL)
14444 			goto exit_failure;
14445 		    uses = type->attrUses;
14446 		}
14447 		xmlSchemaItemListAddSize(uses, 2, use);
14448 inherit_next: {}
14449 	    }
14450 	} else {
14451 	    /* Extension. */
14452 	    for (i = 0; i < baseUses->nbItems; i++) {
14453 		use = baseUses->items[i];
14454 		if (uses == NULL) {
14455 		    type->attrUses = xmlSchemaItemListCreate();
14456 		    if (type->attrUses == NULL)
14457 			goto exit_failure;
14458 		    uses = type->attrUses;
14459 		}
14460 		xmlSchemaItemListAddSize(uses, baseUses->nbItems, use);
14461 	    }
14462 	}
14463     }
14464     /*
14465     * Shrink attr. uses.
14466     */
14467     if (uses) {
14468 	if (uses->nbItems == 0) {
14469 	    xmlSchemaItemListFree(uses);
14470 	    type->attrUses = NULL;
14471 	}
14472 	/*
14473 	* TODO: We could shrink the size of the array
14474 	* to fit the actual number of items.
14475 	*/
14476     }
14477     /*
14478     * Compute the complete wildcard.
14479     */
14480     if (WXS_IS_EXTENSION(type)) {
14481 	if (baseType->attributeWildcard != NULL) {
14482 	    /*
14483 	    * (3.2.2.1) "If the `base wildcard` is non-`absent`, then
14484 	    * the appropriate case among the following:"
14485 	    */
14486 	    if (type->attributeWildcard != NULL) {
14487 		/*
14488 		* Union the complete wildcard with the base wildcard.
14489 		* SPEC {attribute wildcard}
14490 		* (3.2.2.1.2) "otherwise a wildcard whose {process contents}
14491 		* and {annotation} are those of the `complete wildcard`,
14492 		* and whose {namespace constraint} is the intensional union
14493 		* of the {namespace constraint} of the `complete wildcard`
14494 		* and of the `base wildcard`, as defined in Attribute
14495 		* Wildcard Union ($3.10.6)."
14496 		*/
14497 		if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
14498 		    baseType->attributeWildcard) == -1)
14499 		    goto exit_failure;
14500 	    } else {
14501 		/*
14502 		* (3.2.2.1.1) "If the `complete wildcard` is `absent`,
14503 		* then the `base wildcard`."
14504 		*/
14505 		type->attributeWildcard = baseType->attributeWildcard;
14506 	    }
14507 	} else {
14508 	    /*
14509 	    * (3.2.2.2) "otherwise (the `base wildcard` is `absent`) the
14510 	    * `complete wildcard`"
14511 	    * NOOP
14512 	    */
14513 	}
14514     } else {
14515 	/*
14516 	* SPEC {attribute wildcard}
14517 	* (3.1) "If the <restriction> alternative is chosen, then the
14518 	* `complete wildcard`;"
14519 	* NOOP
14520 	*/
14521     }
14522 
14523     return (0);
14524 
14525 exit_failure:
14526     return(-1);
14527 }
14528 
14529 /**
14530  * xmlSchemaTypeFinalContains:
14531  * @schema:  the schema
14532  * @type:  the type definition
14533  * @final: the final
14534  *
14535  * Evaluates if a type definition contains the given "final".
14536  * This does take "finalDefault" into account as well.
14537  *
14538  * Returns 1 if the type does contain the given "final",
14539  * 0 otherwise.
14540  */
14541 static int
xmlSchemaTypeFinalContains(xmlSchemaTypePtr type,int final)14542 xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
14543 {
14544     if (type == NULL)
14545 	return (0);
14546     if (type->flags & final)
14547 	return (1);
14548     else
14549 	return (0);
14550 }
14551 
14552 /**
14553  * xmlSchemaGetUnionSimpleTypeMemberTypes:
14554  * @type:  the Union Simple Type
14555  *
14556  * Returns a list of member types of @type if existing,
14557  * returns NULL otherwise.
14558  */
14559 static xmlSchemaTypeLinkPtr
xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)14560 xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
14561 {
14562     while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
14563 	if (type->memberTypes != NULL)
14564 	    return (type->memberTypes);
14565 	else
14566 	    type = type->baseType;
14567     }
14568     return (NULL);
14569 }
14570 
14571 #if 0
14572 /**
14573  * xmlSchemaGetParticleTotalRangeMin:
14574  * @particle: the particle
14575  *
14576  * Schema Component Constraint: Effective Total Range
14577  * (all and sequence) + (choice)
14578  *
14579  * Returns the minimum Effective Total Range.
14580  */
14581 static int
14582 xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
14583 {
14584     if ((particle->children == NULL) ||
14585 	(particle->minOccurs == 0))
14586 	return (0);
14587     if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14588 	int min = -1, cur;
14589 	xmlSchemaParticlePtr part =
14590 	    (xmlSchemaParticlePtr) particle->children->children;
14591 
14592 	if (part == NULL)
14593 	    return (0);
14594 	while (part != NULL) {
14595 	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14596 		(part->children->type == XML_SCHEMA_TYPE_ANY))
14597 		cur = part->minOccurs;
14598 	    else
14599 		cur = xmlSchemaGetParticleTotalRangeMin(part);
14600 	    if (cur == 0)
14601 		return (0);
14602 	    if ((min > cur) || (min == -1))
14603 		min = cur;
14604 	    part = (xmlSchemaParticlePtr) part->next;
14605 	}
14606 	return (particle->minOccurs * min);
14607     } else {
14608 	/* <all> and <sequence> */
14609 	int sum = 0;
14610 	xmlSchemaParticlePtr part =
14611 	    (xmlSchemaParticlePtr) particle->children->children;
14612 
14613 	if (part == NULL)
14614 	    return (0);
14615 	do {
14616 	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14617 		(part->children->type == XML_SCHEMA_TYPE_ANY))
14618 		sum += part->minOccurs;
14619 	    else
14620 		sum += xmlSchemaGetParticleTotalRangeMin(part);
14621 	    part = (xmlSchemaParticlePtr) part->next;
14622 	} while (part != NULL);
14623 	return (particle->minOccurs * sum);
14624     }
14625 }
14626 
14627 /**
14628  * xmlSchemaGetParticleTotalRangeMax:
14629  * @particle: the particle
14630  *
14631  * Schema Component Constraint: Effective Total Range
14632  * (all and sequence) + (choice)
14633  *
14634  * Returns the maximum Effective Total Range.
14635  */
14636 static int
14637 xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
14638 {
14639     if ((particle->children == NULL) ||
14640 	(particle->children->children == NULL))
14641 	return (0);
14642     if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14643 	int max = -1, cur;
14644 	xmlSchemaParticlePtr part =
14645 	    (xmlSchemaParticlePtr) particle->children->children;
14646 
14647 	for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14648 	    if (part->children == NULL)
14649 		continue;
14650 	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14651 		(part->children->type == XML_SCHEMA_TYPE_ANY))
14652 		cur = part->maxOccurs;
14653 	    else
14654 		cur = xmlSchemaGetParticleTotalRangeMax(part);
14655 	    if (cur == UNBOUNDED)
14656 		return (UNBOUNDED);
14657 	    if ((max < cur) || (max == -1))
14658 		max = cur;
14659 	}
14660 	/* TODO: Handle overflows? */
14661 	return (particle->maxOccurs * max);
14662     } else {
14663 	/* <all> and <sequence> */
14664 	int sum = 0, cur;
14665 	xmlSchemaParticlePtr part =
14666 	    (xmlSchemaParticlePtr) particle->children->children;
14667 
14668 	for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14669 	    if (part->children == NULL)
14670 		continue;
14671 	    if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14672 		(part->children->type == XML_SCHEMA_TYPE_ANY))
14673 		cur = part->maxOccurs;
14674 	    else
14675 		cur = xmlSchemaGetParticleTotalRangeMax(part);
14676 	    if (cur == UNBOUNDED)
14677 		return (UNBOUNDED);
14678 	    if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
14679 		return (UNBOUNDED);
14680 	    sum += cur;
14681 	}
14682 	/* TODO: Handle overflows? */
14683 	return (particle->maxOccurs * sum);
14684     }
14685 }
14686 #endif
14687 
14688 /**
14689  * xmlSchemaGetParticleEmptiable:
14690  * @particle: the particle
14691  *
14692  * Returns 1 if emptiable, 0 otherwise.
14693  */
14694 static int
xmlSchemaGetParticleEmptiable(xmlSchemaParticlePtr particle)14695 xmlSchemaGetParticleEmptiable(xmlSchemaParticlePtr particle)
14696 {
14697     xmlSchemaParticlePtr part;
14698     int emptiable;
14699 
14700     if ((particle->children == NULL) || (particle->minOccurs == 0))
14701 	return (1);
14702 
14703     part = (xmlSchemaParticlePtr) particle->children->children;
14704     if (part == NULL)
14705         return (1);
14706 
14707     while (part != NULL) {
14708         if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14709             (part->children->type == XML_SCHEMA_TYPE_ANY))
14710             emptiable = (part->minOccurs == 0);
14711         else
14712             emptiable = xmlSchemaGetParticleEmptiable(part);
14713         if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14714             if (emptiable)
14715                 return (1);
14716         } else {
14717 	    /* <all> and <sequence> */
14718             if (!emptiable)
14719                 return (0);
14720         }
14721         part = (xmlSchemaParticlePtr) part->next;
14722     }
14723 
14724     if (particle->children->type == XML_SCHEMA_TYPE_CHOICE)
14725         return (0);
14726     else
14727         return (1);
14728 }
14729 
14730 /**
14731  * xmlSchemaIsParticleEmptiable:
14732  * @particle: the particle
14733  *
14734  * Schema Component Constraint: Particle Emptiable
14735  * Checks whether the given particle is emptiable.
14736  *
14737  * Returns 1 if emptiable, 0 otherwise.
14738  */
14739 static int
xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)14740 xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
14741 {
14742     /*
14743     * SPEC (1) "Its {min occurs} is 0."
14744     */
14745     if ((particle == NULL) || (particle->minOccurs == 0) ||
14746 	(particle->children == NULL))
14747 	return (1);
14748     /*
14749     * SPEC (2) "Its {term} is a group and the minimum part of the
14750     * effective total range of that group, [...] is 0."
14751     */
14752     if (WXS_IS_MODEL_GROUP(particle->children))
14753 	return (xmlSchemaGetParticleEmptiable(particle));
14754     return (0);
14755 }
14756 
14757 /**
14758  * xmlSchemaCheckCOSSTDerivedOK:
14759  * @actxt: a context
14760  * @type:  the derived simple type definition
14761  * @baseType:  the base type definition
14762  * @subset: the subset of ('restriction', etc.)
14763  *
14764  * Schema Component Constraint:
14765  * Type Derivation OK (Simple) (cos-st-derived-OK)
14766  *
14767  * Checks whether @type can be validly
14768  * derived from @baseType.
14769  *
14770  * Returns 0 on success, an positive error code otherwise.
14771  */
14772 static int
xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,xmlSchemaTypePtr type,xmlSchemaTypePtr baseType,int subset)14773 xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
14774 			     xmlSchemaTypePtr type,
14775 			     xmlSchemaTypePtr baseType,
14776 			     int subset)
14777 {
14778     /*
14779     * 1 They are the same type definition.
14780     * TODO: The identity check might have to be more complex than this.
14781     */
14782     if (type == baseType)
14783 	return (0);
14784     /*
14785     * 2.1 restriction is not in the subset, or in the {final}
14786     * of its own {base type definition};
14787     *
14788     * NOTE that this will be used also via "xsi:type".
14789     *
14790     * TODO: Revise this, it looks strange. How can the "type"
14791     * not be fixed or *in* fixing?
14792     */
14793     if (WXS_IS_TYPE_NOT_FIXED(type))
14794 	if (xmlSchemaTypeFixup(type, actxt) == -1)
14795 	    return(-1);
14796     if (WXS_IS_TYPE_NOT_FIXED(baseType))
14797 	if (xmlSchemaTypeFixup(baseType, actxt) == -1)
14798 	    return(-1);
14799     if ((subset & SUBSET_RESTRICTION) ||
14800 	(xmlSchemaTypeFinalContains(type->baseType,
14801 	    XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
14802 	return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
14803     }
14804     /* 2.2 */
14805     if (type->baseType == baseType) {
14806 	/*
14807 	* 2.2.1 D's `base type definition` is B.
14808 	*/
14809 	return (0);
14810     }
14811     /*
14812     * 2.2.2 D's `base type definition` is not the `ur-type definition`
14813     * and is validly derived from B given the subset, as defined by this
14814     * constraint.
14815     */
14816     if ((! WXS_IS_ANYTYPE(type->baseType)) &&
14817 	(xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
14818 	    baseType, subset) == 0)) {
14819 	return (0);
14820     }
14821     /*
14822     * 2.2.3 D's {variety} is list or union and B is the `simple ur-type
14823     * definition`.
14824     */
14825     if (WXS_IS_ANY_SIMPLE_TYPE(baseType) &&
14826 	(WXS_IS_LIST(type) || WXS_IS_UNION(type))) {
14827 	return (0);
14828     }
14829     /*
14830     * 2.2.4 B's {variety} is union and D is validly derived from a type
14831     * definition in B's {member type definitions} given the subset, as
14832     * defined by this constraint.
14833     *
14834     * NOTE: This seems not to involve built-in types, since there is no
14835     * built-in Union Simple Type.
14836     */
14837     if (WXS_IS_UNION(baseType)) {
14838 	xmlSchemaTypeLinkPtr cur;
14839 
14840 	cur = baseType->memberTypes;
14841 	while (cur != NULL) {
14842 	    if (WXS_IS_TYPE_NOT_FIXED(cur->type))
14843 		if (xmlSchemaTypeFixup(cur->type, actxt) == -1)
14844 		    return(-1);
14845 	    if (xmlSchemaCheckCOSSTDerivedOK(actxt,
14846 		    type, cur->type, subset) == 0)
14847 	    {
14848 		/*
14849 		* It just has to be validly derived from at least one
14850 		* member-type.
14851 		*/
14852 		return (0);
14853 	    }
14854 	    cur = cur->next;
14855 	}
14856     }
14857     return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
14858 }
14859 
14860 /**
14861  * xmlSchemaCheckTypeDefCircularInternal:
14862  * @pctxt:  the schema parser context
14863  * @ctxtType:  the type definition
14864  * @ancestor: an ancestor of @ctxtType
14865  *
14866  * Checks st-props-correct (2) + ct-props-correct (3).
14867  * Circular type definitions are not allowed.
14868  *
14869  * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
14870  * circular, 0 otherwise.
14871  */
14872 static int
xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr ctxtType,xmlSchemaTypePtr ancestor)14873 xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
14874 			   xmlSchemaTypePtr ctxtType,
14875 			   xmlSchemaTypePtr ancestor)
14876 {
14877     int ret;
14878 
14879     if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
14880 	return (0);
14881 
14882     if (ctxtType == ancestor) {
14883 	xmlSchemaPCustomErr(pctxt,
14884 	    XML_SCHEMAP_ST_PROPS_CORRECT_2,
14885 	    WXS_BASIC_CAST ctxtType, WXS_ITEM_NODE(ctxtType),
14886 	    "The definition is circular", NULL);
14887 	return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
14888     }
14889     if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
14890 	/*
14891 	* Avoid infinite recursion on circular types not yet checked.
14892 	*/
14893 	return (0);
14894     }
14895     ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
14896     ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
14897 	ancestor->baseType);
14898     ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
14899     return (ret);
14900 }
14901 
14902 /**
14903  * xmlSchemaCheckTypeDefCircular:
14904  * @item:  the complex/simple type definition
14905  * @ctxt:  the parser context
14906  * @name:  the name
14907  *
14908  * Checks for circular type definitions.
14909  */
14910 static void
xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,xmlSchemaParserCtxtPtr ctxt)14911 xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
14912 			      xmlSchemaParserCtxtPtr ctxt)
14913 {
14914     if ((item == NULL) ||
14915 	(item->type == XML_SCHEMA_TYPE_BASIC) ||
14916 	(item->baseType == NULL))
14917 	return;
14918     xmlSchemaCheckTypeDefCircularInternal(ctxt, item,
14919 	item->baseType);
14920 }
14921 
14922 /*
14923 * Simple Type Definition Representation OK (src-simple-type) 4
14924 *
14925 * "4 Circular union type definition is disallowed. That is, if the
14926 * <union> alternative is chosen, there must not be any entries in the
14927 * memberTypes [attribute] at any depth which resolve to the component
14928 * corresponding to the <simpleType>."
14929 *
14930 * Note that this should work on the *representation* of a component,
14931 * thus assumes any union types in the member types not being yet
14932 * substituted. At this stage we need the variety of the types
14933 * to be already computed.
14934 */
14935 static int
xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr ctxType,xmlSchemaTypeLinkPtr members)14936 xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,
14937 					xmlSchemaTypePtr ctxType,
14938 					xmlSchemaTypeLinkPtr members)
14939 {
14940     xmlSchemaTypeLinkPtr member;
14941     xmlSchemaTypePtr memberType;
14942 
14943     member = members;
14944     while (member != NULL) {
14945 	memberType = member->type;
14946 	while ((memberType != NULL) &&
14947 	    (memberType->type != XML_SCHEMA_TYPE_BASIC)) {
14948 	    if (memberType == ctxType) {
14949 		xmlSchemaPCustomErr(pctxt,
14950 		    XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
14951 		    WXS_BASIC_CAST ctxType, NULL,
14952 		    "The union type definition is circular", NULL);
14953 		return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
14954 	    }
14955 	    if ((WXS_IS_UNION(memberType)) &&
14956 		((memberType->flags & XML_SCHEMAS_TYPE_MARKED) == 0))
14957 	    {
14958 		int res;
14959 		memberType->flags |= XML_SCHEMAS_TYPE_MARKED;
14960 		res = xmlSchemaCheckUnionTypeDefCircularRecur(pctxt,
14961 		    ctxType,
14962 		    xmlSchemaGetUnionSimpleTypeMemberTypes(memberType));
14963 		memberType->flags ^= XML_SCHEMAS_TYPE_MARKED;
14964 		if (res != 0)
14965 		    return(res);
14966 	    }
14967 	    memberType = memberType->baseType;
14968 	}
14969 	member = member->next;
14970     }
14971     return(0);
14972 }
14973 
14974 static int
xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)14975 xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,
14976 				   xmlSchemaTypePtr type)
14977 {
14978     if (! WXS_IS_UNION(type))
14979 	return(0);
14980     return(xmlSchemaCheckUnionTypeDefCircularRecur(pctxt, type,
14981 	type->memberTypes));
14982 }
14983 
14984 /**
14985  * xmlSchemaResolveTypeReferences:
14986  * @item:  the complex/simple type definition
14987  * @ctxt:  the parser context
14988  * @name:  the name
14989  *
14990  * Resolves type definition references
14991  */
14992 static void
xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,xmlSchemaParserCtxtPtr ctxt)14993 xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,
14994 			 xmlSchemaParserCtxtPtr ctxt)
14995 {
14996     if (typeDef == NULL)
14997 	return;
14998 
14999     /*
15000     * Resolve the base type.
15001     */
15002     if (typeDef->baseType == NULL) {
15003 	typeDef->baseType = xmlSchemaGetType(ctxt->schema,
15004 	    typeDef->base, typeDef->baseNs);
15005 	if (typeDef->baseType == NULL) {
15006 	    xmlSchemaPResCompAttrErr(ctxt,
15007 		XML_SCHEMAP_SRC_RESOLVE,
15008 		WXS_BASIC_CAST typeDef, typeDef->node,
15009 		"base", typeDef->base, typeDef->baseNs,
15010 		XML_SCHEMA_TYPE_SIMPLE, NULL);
15011 	    return;
15012 	}
15013     }
15014     if (WXS_IS_SIMPLE(typeDef)) {
15015 	if (WXS_IS_UNION(typeDef)) {
15016 	    /*
15017 	    * Resolve the memberTypes.
15018 	    */
15019 	    xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
15020 	    return;
15021 	} else if (WXS_IS_LIST(typeDef)) {
15022 	    /*
15023 	    * Resolve the itemType.
15024 	    */
15025 	    if ((typeDef->subtypes == NULL) && (typeDef->base != NULL)) {
15026 
15027 		typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
15028 		    typeDef->base, typeDef->baseNs);
15029 
15030 		if ((typeDef->subtypes == NULL) ||
15031 		    (! WXS_IS_SIMPLE(typeDef->subtypes)))
15032 		{
15033 		    typeDef->subtypes = NULL;
15034 		    xmlSchemaPResCompAttrErr(ctxt,
15035 			XML_SCHEMAP_SRC_RESOLVE,
15036 			WXS_BASIC_CAST typeDef, typeDef->node,
15037 			"itemType", typeDef->base, typeDef->baseNs,
15038 			XML_SCHEMA_TYPE_SIMPLE, NULL);
15039 		}
15040 	    }
15041 	    return;
15042 	}
15043     }
15044     /*
15045     * The ball of letters below means, that if we have a particle
15046     * which has a QName-helper component as its {term}, we want
15047     * to resolve it...
15048     */
15049     else if ((WXS_TYPE_CONTENTTYPE(typeDef) != NULL) &&
15050 	((WXS_TYPE_CONTENTTYPE(typeDef))->type ==
15051 	    XML_SCHEMA_TYPE_PARTICLE) &&
15052 	(WXS_TYPE_PARTICLE_TERM(typeDef) != NULL) &&
15053 	((WXS_TYPE_PARTICLE_TERM(typeDef))->type ==
15054 	    XML_SCHEMA_EXTRA_QNAMEREF))
15055     {
15056 	xmlSchemaQNameRefPtr ref =
15057 	    WXS_QNAME_CAST WXS_TYPE_PARTICLE_TERM(typeDef);
15058 	xmlSchemaModelGroupDefPtr groupDef;
15059 
15060 	/*
15061 	* URGENT TODO: Test this.
15062 	*/
15063 	WXS_TYPE_PARTICLE_TERM(typeDef) = NULL;
15064 	/*
15065 	* Resolve the MG definition reference.
15066 	*/
15067 	groupDef =
15068 	    WXS_MODEL_GROUPDEF_CAST xmlSchemaGetNamedComponent(ctxt->schema,
15069 		ref->itemType, ref->name, ref->targetNamespace);
15070 	if (groupDef == NULL) {
15071 	    xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
15072 		NULL, WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)),
15073 		"ref", ref->name, ref->targetNamespace, ref->itemType,
15074 		NULL);
15075 	    /* Remove the particle. */
15076 	    WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15077 	} else if (WXS_MODELGROUPDEF_MODEL(groupDef) == NULL)
15078 	    /* Remove the particle. */
15079 	    WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15080 	else {
15081 	    /*
15082 	    * Assign the MG definition's {model group} to the
15083 	    * particle's {term}.
15084 	    */
15085 	    WXS_TYPE_PARTICLE_TERM(typeDef) = WXS_MODELGROUPDEF_MODEL(groupDef);
15086 
15087 	    if (WXS_MODELGROUPDEF_MODEL(groupDef)->type == XML_SCHEMA_TYPE_ALL) {
15088 		/*
15089 		* SPEC cos-all-limited (1.2)
15090 		* "1.2 the {term} property of a particle with
15091 		* {max occurs}=1 which is part of a pair which constitutes
15092 		* the {content type} of a complex type definition."
15093 		*/
15094 		if ((WXS_TYPE_PARTICLE(typeDef))->maxOccurs != 1) {
15095 		    xmlSchemaCustomErr(ACTXT_CAST ctxt,
15096 			/* TODO: error code */
15097 			XML_SCHEMAP_COS_ALL_LIMITED,
15098 			WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)), NULL,
15099 			"The particle's {max occurs} must be 1, since the "
15100 			"reference resolves to an 'all' model group",
15101 			NULL, NULL);
15102 		}
15103 	    }
15104 	}
15105     }
15106 }
15107 
15108 
15109 
15110 /**
15111  * xmlSchemaCheckSTPropsCorrect:
15112  * @ctxt:  the schema parser context
15113  * @type:  the simple type definition
15114  *
15115  * Checks st-props-correct.
15116  *
15117  * Returns 0 if the properties are correct,
15118  * if not, a positive error code and -1 on internal
15119  * errors.
15120  */
15121 static int
xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)15122 xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
15123 			     xmlSchemaTypePtr type)
15124 {
15125     xmlSchemaTypePtr baseType = type->baseType;
15126     xmlChar *str = NULL;
15127 
15128     /* STATE: error funcs converted. */
15129     /*
15130     * Schema Component Constraint: Simple Type Definition Properties Correct
15131     *
15132     * NOTE: This is somehow redundant, since we actually built a simple type
15133     * to have all the needed information; this acts as an self test.
15134     */
15135     /* Base type: If the datatype has been `derived` by `restriction`
15136     * then the Simple Type Definition component from which it is `derived`,
15137     * otherwise the Simple Type Definition for anySimpleType ($4.1.6).
15138     */
15139     if (baseType == NULL) {
15140 	/*
15141 	* TODO: Think about: "modulo the impact of Missing
15142 	* Sub-components ($5.3)."
15143 	*/
15144 	xmlSchemaPCustomErr(ctxt,
15145 	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15146 	    WXS_BASIC_CAST type, NULL,
15147 	    "No base type existent", NULL);
15148 	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15149 
15150     }
15151     if (! WXS_IS_SIMPLE(baseType)) {
15152 	xmlSchemaPCustomErr(ctxt,
15153 	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15154 	    WXS_BASIC_CAST type, NULL,
15155 	    "The base type '%s' is not a simple type",
15156 	    xmlSchemaGetComponentQName(&str, baseType));
15157 	FREE_AND_NULL(str)
15158 	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15159     }
15160     if ((WXS_IS_LIST(type) || WXS_IS_UNION(type)) &&
15161 	(WXS_IS_RESTRICTION(type) == 0) &&
15162 	((! WXS_IS_ANY_SIMPLE_TYPE(baseType)) &&
15163          (baseType->type != XML_SCHEMA_TYPE_SIMPLE))) {
15164 	xmlSchemaPCustomErr(ctxt,
15165 	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15166 	    WXS_BASIC_CAST type, NULL,
15167 	    "A type, derived by list or union, must have "
15168 	    "the simple ur-type definition as base type, not '%s'",
15169 	    xmlSchemaGetComponentQName(&str, baseType));
15170 	FREE_AND_NULL(str)
15171 	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15172     }
15173     /*
15174     * Variety: One of {atomic, list, union}.
15175     */
15176     if ((! WXS_IS_ATOMIC(type)) && (! WXS_IS_UNION(type)) &&
15177 	(! WXS_IS_LIST(type))) {
15178 	xmlSchemaPCustomErr(ctxt,
15179 	    XML_SCHEMAP_ST_PROPS_CORRECT_1,
15180 	    WXS_BASIC_CAST type, NULL,
15181 	    "The variety is absent", NULL);
15182 	return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15183     }
15184     /* TODO: Finish this. Hmm, is this finished? */
15185 
15186     /*
15187     * 3 The {final} of the {base type definition} must not contain restriction.
15188     */
15189     if (xmlSchemaTypeFinalContains(baseType,
15190 	XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15191 	xmlSchemaPCustomErr(ctxt,
15192 	    XML_SCHEMAP_ST_PROPS_CORRECT_3,
15193 	    WXS_BASIC_CAST type, NULL,
15194 	    "The 'final' of its base type '%s' must not contain "
15195 	    "'restriction'",
15196 	    xmlSchemaGetComponentQName(&str, baseType));
15197 	FREE_AND_NULL(str)
15198 	return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
15199     }
15200 
15201     /*
15202     * 2 All simple type definitions must be derived ultimately from the `simple
15203     * ur-type definition` (so circular definitions are disallowed). That is, it
15204     * must be possible to reach a built-in primitive datatype or the `simple
15205     * ur-type definition` by repeatedly following the {base type definition}.
15206     *
15207     * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
15208     */
15209     return (0);
15210 }
15211 
15212 /**
15213  * xmlSchemaCheckCOSSTRestricts:
15214  * @ctxt:  the schema parser context
15215  * @type:  the simple type definition
15216  *
15217  * Schema Component Constraint:
15218  * Derivation Valid (Restriction, Simple) (cos-st-restricts)
15219 
15220  * Checks if the given @type (simpleType) is derived validly by restriction.
15221  * STATUS:
15222  *
15223  * Returns -1 on internal errors, 0 if the type is validly derived,
15224  * a positive error code otherwise.
15225  */
15226 static int
xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)15227 xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
15228 			     xmlSchemaTypePtr type)
15229 {
15230     xmlChar *str = NULL;
15231 
15232     if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
15233 	PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15234 	    "given type is not a user-derived simpleType");
15235 	return (-1);
15236     }
15237 
15238     if (WXS_IS_ATOMIC(type)) {
15239 	xmlSchemaTypePtr primitive;
15240 	/*
15241 	* 1.1 The {base type definition} must be an atomic simple
15242 	* type definition or a built-in primitive datatype.
15243 	*/
15244 	if (! WXS_IS_ATOMIC(type->baseType)) {
15245 	    xmlSchemaPCustomErr(pctxt,
15246 		XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
15247 		WXS_BASIC_CAST type, NULL,
15248 		"The base type '%s' is not an atomic simple type",
15249 		xmlSchemaGetComponentQName(&str, type->baseType));
15250 	    FREE_AND_NULL(str)
15251 	    return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
15252 	}
15253 	/* 1.2 The {final} of the {base type definition} must not contain
15254 	* restriction.
15255 	*/
15256 	/* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
15257 	if (xmlSchemaTypeFinalContains(type->baseType,
15258 	    XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15259 	    xmlSchemaPCustomErr(pctxt,
15260 		XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
15261 		WXS_BASIC_CAST type, NULL,
15262 		"The final of its base type '%s' must not contain 'restriction'",
15263 		xmlSchemaGetComponentQName(&str, type->baseType));
15264 	    FREE_AND_NULL(str)
15265 	    return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
15266 	}
15267 
15268 	/*
15269 	* 1.3.1 DF must be an allowed constraining facet for the {primitive
15270 	* type definition}, as specified in the appropriate subsection of 3.2
15271 	* Primitive datatypes.
15272 	*/
15273 	if (type->facets != NULL) {
15274 	    xmlSchemaFacetPtr facet;
15275 	    int ok = 1;
15276 
15277 	    primitive = xmlSchemaGetPrimitiveType(type);
15278 	    if (primitive == NULL) {
15279 		PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15280 		    "failed to get primitive type");
15281 		return (-1);
15282 	    }
15283 	    facet = type->facets;
15284 	    do {
15285 		if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
15286 		    ok = 0;
15287 		    xmlSchemaPIllegalFacetAtomicErr(pctxt,
15288 			XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
15289 			type, primitive, facet);
15290 		}
15291 		facet = facet->next;
15292 	    } while (facet != NULL);
15293 	    if (ok == 0)
15294 		return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
15295 	}
15296 	/*
15297 	* SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
15298 	* of the {base type definition} (call this BF),then the DF's {value}
15299 	* must be a valid restriction of BF's {value} as defined in
15300 	* [XML Schemas: Datatypes]."
15301 	*
15302 	* NOTE (1.3.2) Facet derivation constraints are currently handled in
15303 	* xmlSchemaDeriveAndValidateFacets()
15304 	*/
15305     } else if (WXS_IS_LIST(type)) {
15306 	xmlSchemaTypePtr itemType = NULL;
15307 
15308 	itemType = type->subtypes;
15309 	if ((itemType == NULL) || (! WXS_IS_SIMPLE(itemType))) {
15310 	    PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15311 		"failed to evaluate the item type");
15312 	    return (-1);
15313 	}
15314 	if (WXS_IS_TYPE_NOT_FIXED(itemType))
15315 	    xmlSchemaTypeFixup(itemType, ACTXT_CAST pctxt);
15316 	/*
15317 	* 2.1 The {item type definition} must have a {variety} of atomic or
15318 	* union (in which case all the {member type definitions}
15319 	* must be atomic).
15320 	*/
15321 	if ((! WXS_IS_ATOMIC(itemType)) &&
15322 	    (! WXS_IS_UNION(itemType))) {
15323 	    xmlSchemaPCustomErr(pctxt,
15324 		XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15325 		WXS_BASIC_CAST type, NULL,
15326 		"The item type '%s' does not have a variety of atomic or union",
15327 		xmlSchemaGetComponentQName(&str, itemType));
15328 	    FREE_AND_NULL(str)
15329 	    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15330 	} else if (WXS_IS_UNION(itemType)) {
15331 	    xmlSchemaTypeLinkPtr member;
15332 
15333 	    member = itemType->memberTypes;
15334 	    while (member != NULL) {
15335 		if (! WXS_IS_ATOMIC(member->type)) {
15336 		    xmlSchemaPCustomErr(pctxt,
15337 			XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15338 			WXS_BASIC_CAST type, NULL,
15339 			"The item type is a union type, but the "
15340 			"member type '%s' of this item type is not atomic",
15341 			xmlSchemaGetComponentQName(&str, member->type));
15342 		    FREE_AND_NULL(str)
15343 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15344 		}
15345 		member = member->next;
15346 	    }
15347 	}
15348 
15349 	if (WXS_IS_ANY_SIMPLE_TYPE(type->baseType)) {
15350 	    xmlSchemaFacetPtr facet;
15351 	    /*
15352 	    * This is the case if we have: <simpleType><list ..
15353 	    */
15354 	    /*
15355 	    * 2.3.1
15356 	    * 2.3.1.1 The {final} of the {item type definition} must not
15357 	    * contain list.
15358 	    */
15359 	    if (xmlSchemaTypeFinalContains(itemType,
15360 		XML_SCHEMAS_TYPE_FINAL_LIST)) {
15361 		xmlSchemaPCustomErr(pctxt,
15362 		    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
15363 		    WXS_BASIC_CAST type, NULL,
15364 		    "The final of its item type '%s' must not contain 'list'",
15365 		    xmlSchemaGetComponentQName(&str, itemType));
15366 		FREE_AND_NULL(str)
15367 		return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
15368 	    }
15369 	    /*
15370 	    * 2.3.1.2 The {facets} must only contain the whiteSpace
15371 	    * facet component.
15372 	    * OPTIMIZE TODO: the S4S already disallows any facet
15373 	    * to be specified.
15374 	    */
15375 	    if (type->facets != NULL) {
15376 		facet = type->facets;
15377 		do {
15378 		    if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
15379 			xmlSchemaPIllegalFacetListUnionErr(pctxt,
15380 			    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
15381 			    type, facet);
15382 			return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
15383 		    }
15384 		    facet = facet->next;
15385 		} while (facet != NULL);
15386 	    }
15387 	    /*
15388 	    * MAYBE TODO: (Hmm, not really) Datatypes states:
15389 	    * A `list` datatype can be `derived` from an `atomic` datatype
15390 	    * whose `lexical space` allows space (such as string or anyURI)or
15391 	    * a `union` datatype any of whose {member type definitions}'s
15392 	    * `lexical space` allows space.
15393 	    */
15394 	} else {
15395 	    /*
15396 	    * This is the case if we have: <simpleType><restriction ...
15397 	    * I.e. the variety of "list" is inherited.
15398 	    */
15399 	    /*
15400 	    * 2.3.2
15401 	    * 2.3.2.1 The {base type definition} must have a {variety} of list.
15402 	    */
15403 	    if (! WXS_IS_LIST(type->baseType)) {
15404 		xmlSchemaPCustomErr(pctxt,
15405 		    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
15406 		    WXS_BASIC_CAST type, NULL,
15407 		    "The base type '%s' must be a list type",
15408 		    xmlSchemaGetComponentQName(&str, type->baseType));
15409 		FREE_AND_NULL(str)
15410 		return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
15411 	    }
15412 	    /*
15413 	    * 2.3.2.2 The {final} of the {base type definition} must not
15414 	    * contain restriction.
15415 	    */
15416 	    if (xmlSchemaTypeFinalContains(type->baseType,
15417 		XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15418 		xmlSchemaPCustomErr(pctxt,
15419 		    XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
15420 		    WXS_BASIC_CAST type, NULL,
15421 		    "The 'final' of the base type '%s' must not contain 'restriction'",
15422 		    xmlSchemaGetComponentQName(&str, type->baseType));
15423 		FREE_AND_NULL(str)
15424 		return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
15425 	    }
15426 	    /*
15427 	    * 2.3.2.3 The {item type definition} must be validly derived
15428 	    * from the {base type definition}'s {item type definition} given
15429 	    * the empty set, as defined in Type Derivation OK (Simple) ($3.14.6).
15430 	    */
15431 	    {
15432 		xmlSchemaTypePtr baseItemType;
15433 
15434 		baseItemType = type->baseType->subtypes;
15435 		if ((baseItemType == NULL) || (! WXS_IS_SIMPLE(baseItemType))) {
15436 		    PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15437 			"failed to eval the item type of a base type");
15438 		    return (-1);
15439 		}
15440 		if ((itemType != baseItemType) &&
15441 		    (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt, itemType,
15442 			baseItemType, 0) != 0)) {
15443 		    xmlChar *strBIT = NULL, *strBT = NULL;
15444 		    xmlSchemaPCustomErrExt(pctxt,
15445 			XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
15446 			WXS_BASIC_CAST type, NULL,
15447 			"The item type '%s' is not validly derived from "
15448 			"the item type '%s' of the base type '%s'",
15449 			xmlSchemaGetComponentQName(&str, itemType),
15450 			xmlSchemaGetComponentQName(&strBIT, baseItemType),
15451 			xmlSchemaGetComponentQName(&strBT, type->baseType));
15452 
15453 		    FREE_AND_NULL(str)
15454 		    FREE_AND_NULL(strBIT)
15455 		    FREE_AND_NULL(strBT)
15456 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
15457 		}
15458 	    }
15459 
15460 	    if (type->facets != NULL) {
15461 		xmlSchemaFacetPtr facet;
15462 		int ok = 1;
15463 		/*
15464 		* 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
15465 		* and enumeration facet components are allowed among the {facets}.
15466 		*/
15467 		facet = type->facets;
15468 		do {
15469 		    switch (facet->type) {
15470 			case XML_SCHEMA_FACET_LENGTH:
15471 			case XML_SCHEMA_FACET_MINLENGTH:
15472 			case XML_SCHEMA_FACET_MAXLENGTH:
15473 			case XML_SCHEMA_FACET_WHITESPACE:
15474 			    /*
15475 			    * TODO: 2.5.1.2 List datatypes
15476 			    * The value of `whiteSpace` is fixed to the value collapse.
15477 			    */
15478 			case XML_SCHEMA_FACET_PATTERN:
15479 			case XML_SCHEMA_FACET_ENUMERATION:
15480 			    break;
15481 			default: {
15482 			    xmlSchemaPIllegalFacetListUnionErr(pctxt,
15483 				XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
15484 				type, facet);
15485 			    /*
15486 			    * We could return, but it's nicer to report all
15487 			    * invalid facets.
15488 			    */
15489 			    ok = 0;
15490 			}
15491 		    }
15492 		    facet = facet->next;
15493 		} while (facet != NULL);
15494 		if (ok == 0)
15495 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
15496 		/*
15497 		* SPEC (2.3.2.5) (same as 1.3.2)
15498 		*
15499 		* NOTE (2.3.2.5) This is currently done in
15500 		* xmlSchemaDeriveAndValidateFacets()
15501 		*/
15502 	    }
15503 	}
15504     } else if (WXS_IS_UNION(type)) {
15505 	/*
15506 	* 3.1 The {member type definitions} must all have {variety} of
15507 	* atomic or list.
15508 	*/
15509 	xmlSchemaTypeLinkPtr member;
15510 
15511 	member = type->memberTypes;
15512 	while (member != NULL) {
15513 	    if (WXS_IS_TYPE_NOT_FIXED(member->type))
15514 		xmlSchemaTypeFixup(member->type, ACTXT_CAST pctxt);
15515 
15516 	    if ((! WXS_IS_ATOMIC(member->type)) &&
15517 		(! WXS_IS_LIST(member->type))) {
15518 		xmlSchemaPCustomErr(pctxt,
15519 		    XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
15520 		    WXS_BASIC_CAST type, NULL,
15521 		    "The member type '%s' is neither an atomic, nor a list type",
15522 		    xmlSchemaGetComponentQName(&str, member->type));
15523 		FREE_AND_NULL(str)
15524 		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
15525 	    }
15526 	    member = member->next;
15527 	}
15528 	/*
15529 	* 3.3.1 If the {base type definition} is the `simple ur-type
15530 	* definition`
15531 	*/
15532 	if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
15533 	    /*
15534 	    * 3.3.1.1 All of the {member type definitions} must have a
15535 	    * {final} which does not contain union.
15536 	    */
15537 	    member = type->memberTypes;
15538 	    while (member != NULL) {
15539 		if (xmlSchemaTypeFinalContains(member->type,
15540 		    XML_SCHEMAS_TYPE_FINAL_UNION)) {
15541 		    xmlSchemaPCustomErr(pctxt,
15542 			XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
15543 			WXS_BASIC_CAST type, NULL,
15544 			"The 'final' of member type '%s' contains 'union'",
15545 			xmlSchemaGetComponentQName(&str, member->type));
15546 		    FREE_AND_NULL(str)
15547 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
15548 		}
15549 		member = member->next;
15550 	    }
15551 	    /*
15552 	    * 3.3.1.2 The {facets} must be empty.
15553 	    */
15554 	    if (type->facetSet != NULL) {
15555 		xmlSchemaPCustomErr(pctxt,
15556 		    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
15557 		    WXS_BASIC_CAST type, NULL,
15558 		    "No facets allowed", NULL);
15559 		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
15560 	    }
15561 	} else {
15562 	    /*
15563 	    * 3.3.2.1 The {base type definition} must have a {variety} of union.
15564 	    * I.e. the variety of "list" is inherited.
15565 	    */
15566 	    if (! WXS_IS_UNION(type->baseType)) {
15567 		xmlSchemaPCustomErr(pctxt,
15568 		    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
15569 		    WXS_BASIC_CAST type, NULL,
15570 		    "The base type '%s' is not a union type",
15571 		    xmlSchemaGetComponentQName(&str, type->baseType));
15572 		FREE_AND_NULL(str)
15573 		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
15574 	    }
15575 	    /*
15576 	    * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
15577 	    */
15578 	    if (xmlSchemaTypeFinalContains(type->baseType,
15579 		XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15580 		xmlSchemaPCustomErr(pctxt,
15581 		    XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
15582 		    WXS_BASIC_CAST type, NULL,
15583 		    "The 'final' of its base type '%s' must not contain 'restriction'",
15584 		    xmlSchemaGetComponentQName(&str, type->baseType));
15585 		FREE_AND_NULL(str)
15586 		return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
15587 	    }
15588 	    /*
15589 	    * 3.3.2.3 The {member type definitions}, in order, must be validly
15590 	    * derived from the corresponding type definitions in the {base
15591 	    * type definition}'s {member type definitions} given the empty set,
15592 	    * as defined in Type Derivation OK (Simple) ($3.14.6).
15593 	    */
15594 	    {
15595 		xmlSchemaTypeLinkPtr baseMember;
15596 
15597 		/*
15598 		* OPTIMIZE: if the type is restricting, it has no local defined
15599 		* member types and inherits the member types of the base type;
15600 		* thus a check for equality can be skipped.
15601 		*/
15602 		/*
15603 		* Even worse: I cannot see a scenario where a restricting
15604 		* union simple type can have other member types as the member
15605 		* types of it's base type. This check seems not necessary with
15606 		* respect to the derivation process in libxml2.
15607 		* But necessary if constructing types with an API.
15608 		*/
15609 		if (type->memberTypes != NULL) {
15610 		    member = type->memberTypes;
15611 		    baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
15612 		    if ((member == NULL) && (baseMember != NULL)) {
15613 			PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15614 			    "different number of member types in base");
15615 		    }
15616 		    while (member != NULL) {
15617 			if (baseMember == NULL) {
15618 			    PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15619 			    "different number of member types in base");
15620 			} else if ((member->type != baseMember->type) &&
15621 			    (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
15622 				member->type, baseMember->type, 0) != 0)) {
15623 			    xmlChar *strBMT = NULL, *strBT = NULL;
15624 
15625 			    xmlSchemaPCustomErrExt(pctxt,
15626 				XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
15627 				WXS_BASIC_CAST type, NULL,
15628 				"The member type %s is not validly "
15629 				"derived from its corresponding member "
15630 				"type %s of the base type %s",
15631 				xmlSchemaGetComponentQName(&str, member->type),
15632 				xmlSchemaGetComponentQName(&strBMT, baseMember->type),
15633 				xmlSchemaGetComponentQName(&strBT, type->baseType));
15634 			    FREE_AND_NULL(str)
15635 			    FREE_AND_NULL(strBMT)
15636 			    FREE_AND_NULL(strBT)
15637 			    return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
15638 			}
15639 			member = member->next;
15640                         if (baseMember != NULL)
15641                             baseMember = baseMember->next;
15642 		    }
15643 		}
15644 	    }
15645 	    /*
15646 	    * 3.3.2.4 Only pattern and enumeration facet components are
15647 	    * allowed among the {facets}.
15648 	    */
15649 	    if (type->facets != NULL) {
15650 		xmlSchemaFacetPtr facet;
15651 		int ok = 1;
15652 
15653 		facet = type->facets;
15654 		do {
15655 		    if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
15656 			(facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
15657 			xmlSchemaPIllegalFacetListUnionErr(pctxt,
15658 				XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
15659 				type, facet);
15660 			ok = 0;
15661 		    }
15662 		    facet = facet->next;
15663 		} while (facet != NULL);
15664 		if (ok == 0)
15665 		    return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
15666 
15667 	    }
15668 	    /*
15669 	    * SPEC (3.3.2.5) (same as 1.3.2)
15670 	    *
15671 	    * NOTE (3.3.2.5) This is currently done in
15672 	    * xmlSchemaDeriveAndValidateFacets()
15673 	    */
15674 	}
15675     }
15676 
15677     return (0);
15678 }
15679 
15680 /**
15681  * xmlSchemaCheckSRCSimpleType:
15682  * @ctxt:  the schema parser context
15683  * @type:  the simple type definition
15684  *
15685  * Checks crc-simple-type constraints.
15686  *
15687  * Returns 0 if the constraints are satisfied,
15688  * if not a positive error code and -1 on internal
15689  * errors.
15690  */
15691 #if 0
15692 static int
15693 xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
15694 			    xmlSchemaTypePtr type)
15695 {
15696     /*
15697     * src-simple-type.1 The corresponding simple type definition, if any,
15698     * must satisfy the conditions set out in Constraints on Simple Type
15699     * Definition Schema Components ($3.14.6).
15700     */
15701     if (WXS_IS_RESTRICTION(type)) {
15702 	/*
15703 	* src-simple-type.2 "If the <restriction> alternative is chosen,
15704 	* either it must have a base [attribute] or a <simpleType> among its
15705 	* [children], but not both."
15706 	* NOTE: This is checked in the parse function of <restriction>.
15707 	*/
15708 	/*
15709 	*
15710 	*/
15711     } else if (WXS_IS_LIST(type)) {
15712 	/* src-simple-type.3 "If the <list> alternative is chosen, either it must have
15713 	* an itemType [attribute] or a <simpleType> among its [children],
15714 	* but not both."
15715 	*
15716 	* NOTE: This is checked in the parse function of <list>.
15717 	*/
15718     } else if (WXS_IS_UNION(type)) {
15719 	/*
15720 	* src-simple-type.4 is checked in xmlSchemaCheckUnionTypeDefCircular().
15721 	*/
15722     }
15723     return (0);
15724 }
15725 #endif
15726 
15727 static int
xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)15728 xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
15729 {
15730    if (ctxt->vctxt == NULL) {
15731 	ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
15732 	if (ctxt->vctxt == NULL) {
15733 	    xmlSchemaPErr(ctxt, NULL,
15734 		XML_SCHEMAP_INTERNAL,
15735 		"Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
15736 		"failed to create a temp. validation context.\n",
15737 		NULL, NULL);
15738 	    return (-1);
15739 	}
15740 	/* TODO: Pass user data. */
15741 	xmlSchemaSetValidErrors(ctxt->vctxt,
15742 	    ctxt->error, ctxt->warning, ctxt->errCtxt);
15743 	xmlSchemaSetValidStructuredErrors(ctxt->vctxt,
15744 	    ctxt->serror, ctxt->errCtxt);
15745     }
15746     return (0);
15747 }
15748 
15749 static int
15750 xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
15751 			     xmlNodePtr node,
15752 			     xmlSchemaTypePtr type,
15753 			     const xmlChar *value,
15754 			     xmlSchemaValPtr *retVal,
15755 			     int fireErrors,
15756 			     int normalize,
15757 			     int isNormalized);
15758 
15759 /**
15760  * xmlSchemaParseCheckCOSValidDefault:
15761  * @pctxt:  the schema parser context
15762  * @type:  the simple type definition
15763  * @value: the default value
15764  * @node: an optional node (the holder of the value)
15765  *
15766  * Schema Component Constraint: Element Default Valid (Immediate)
15767  * (cos-valid-default)
15768  * This will be used by the parser only. For the validator there's
15769  * an other version.
15770  *
15771  * Returns 0 if the constraints are satisfied,
15772  * if not, a positive error code and -1 on internal
15773  * errors.
15774  */
15775 static int
xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,xmlNodePtr node,xmlSchemaTypePtr type,const xmlChar * value,xmlSchemaValPtr * val)15776 xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
15777 				   xmlNodePtr node,
15778 				   xmlSchemaTypePtr type,
15779 				   const xmlChar *value,
15780 				   xmlSchemaValPtr *val)
15781 {
15782     int ret = 0;
15783 
15784     /*
15785     * cos-valid-default:
15786     * Schema Component Constraint: Element Default Valid (Immediate)
15787     * For a string to be a valid default with respect to a type
15788     * definition the appropriate case among the following must be true:
15789     */
15790     if WXS_IS_COMPLEX(type) {
15791 	/*
15792 	* Complex type.
15793 	*
15794 	* SPEC (2.1) "its {content type} must be a simple type definition
15795 	* or mixed."
15796 	* SPEC (2.2.2) "If the {content type} is mixed, then the {content
15797 	* type}'s particle must be `emptiable` as defined by
15798 	* Particle Emptiable ($3.9.6)."
15799 	*/
15800 	if ((! WXS_HAS_SIMPLE_CONTENT(type)) &&
15801 	    ((! WXS_HAS_MIXED_CONTENT(type)) || (! WXS_EMPTIABLE(type)))) {
15802 	    /* NOTE that this covers (2.2.2) as well. */
15803 	    xmlSchemaPCustomErr(pctxt,
15804 		XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
15805 		WXS_BASIC_CAST type, type->node,
15806 		"For a string to be a valid default, the type definition "
15807 		"must be a simple type or a complex type with mixed content "
15808 		"and a particle emptiable", NULL);
15809 	    return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
15810 	}
15811     }
15812     /*
15813     * 1 If the type definition is a simple type definition, then the string
15814     * must be `valid` with respect to that definition as defined by String
15815     * Valid ($3.14.4).
15816     *
15817     * AND
15818     *
15819     * 2.2.1 If the {content type} is a simple type definition, then the
15820     * string must be `valid` with respect to that simple type definition
15821     * as defined by String Valid ($3.14.4).
15822     */
15823     if (WXS_IS_SIMPLE(type))
15824 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15825 	    type, value, val, 1, 1, 0);
15826     else if (WXS_HAS_SIMPLE_CONTENT(type))
15827 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15828 	    type->contentTypeDef, value, val, 1, 1, 0);
15829     else
15830 	return (ret);
15831 
15832     if (ret < 0) {
15833 	PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
15834 	    "calling xmlSchemaVCheckCVCSimpleType()");
15835     }
15836 
15837     return (ret);
15838 }
15839 
15840 /**
15841  * xmlSchemaCheckCTPropsCorrect:
15842  * @ctxt:  the schema parser context
15843  * @type:  the complex type definition
15844  *
15845  *.(4.6) Constraints on Complex Type Definition Schema Components
15846  * Schema Component Constraint:
15847  * Complex Type Definition Properties Correct (ct-props-correct)
15848  * STATUS: (seems) complete
15849  *
15850  * Returns 0 if the constraints are satisfied, a positive
15851  * error code if not and -1 if an internal error occurred.
15852  */
15853 static int
xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)15854 xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
15855 			     xmlSchemaTypePtr type)
15856 {
15857     /*
15858     * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
15859     *
15860     * SPEC (1) "The values of the properties of a complex type definition must
15861     * be as described in the property tableau in The Complex Type Definition
15862     * Schema Component ($3.4.1), modulo the impact of Missing
15863     * Sub-components ($5.3)."
15864     */
15865     if ((type->baseType != NULL) &&
15866 	(WXS_IS_SIMPLE(type->baseType)) &&
15867 	(WXS_IS_EXTENSION(type) == 0)) {
15868 	/*
15869 	* SPEC (2) "If the {base type definition} is a simple type definition,
15870 	* the {derivation method} must be extension."
15871 	*/
15872 	xmlSchemaCustomErr(ACTXT_CAST pctxt,
15873 	    XML_SCHEMAP_SRC_CT_1,
15874 	    NULL, WXS_BASIC_CAST type,
15875 	    "If the base type is a simple type, the derivation method must be "
15876 	    "'extension'", NULL, NULL);
15877 	return (XML_SCHEMAP_SRC_CT_1);
15878     }
15879     /*
15880     * SPEC (3) "Circular definitions are disallowed, except for the `ur-type
15881     * definition`. That is, it must be possible to reach the `ur-type
15882     * definition` by repeatedly following the {base type definition}."
15883     *
15884     * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
15885     */
15886     /*
15887     * NOTE that (4) and (5) need the following:
15888     *   - attribute uses need to be already inherited (apply attr. prohibitions)
15889     *   - attribute group references need to be expanded already
15890     *   - simple types need to be typefixed already
15891     */
15892     if (type->attrUses &&
15893 	(((xmlSchemaItemListPtr) type->attrUses)->nbItems > 1))
15894     {
15895 	xmlSchemaItemListPtr uses = (xmlSchemaItemListPtr) type->attrUses;
15896 	xmlSchemaAttributeUsePtr use, tmp;
15897 	int i, j, hasId = 0;
15898 
15899 	for (i = uses->nbItems -1; i >= 0; i--) {
15900 	    use = uses->items[i];
15901 
15902 	    /*
15903 	    * SPEC ct-props-correct
15904 	    * (4) "Two distinct attribute declarations in the
15905 	    * {attribute uses} must not have identical {name}s and
15906 	    * {target namespace}s."
15907 	    */
15908 	    if (i > 0) {
15909 		for (j = i -1; j >= 0; j--) {
15910 		    tmp = uses->items[j];
15911 		    if ((WXS_ATTRUSE_DECL_NAME(use) ==
15912 			WXS_ATTRUSE_DECL_NAME(tmp)) &&
15913 			(WXS_ATTRUSE_DECL_TNS(use) ==
15914 			WXS_ATTRUSE_DECL_TNS(tmp)))
15915 		    {
15916 			xmlChar *str = NULL;
15917 
15918 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
15919 			    XML_SCHEMAP_AG_PROPS_CORRECT,
15920 			    NULL, WXS_BASIC_CAST type,
15921 			    "Duplicate %s",
15922 			    xmlSchemaGetComponentDesignation(&str, use),
15923 			    NULL);
15924 			FREE_AND_NULL(str);
15925 			/*
15926 			* Remove the duplicate.
15927 			*/
15928 			if (xmlSchemaItemListRemove(uses, i) == -1)
15929 			    goto exit_failure;
15930 			goto next_use;
15931 		    }
15932 		}
15933 	    }
15934 	    /*
15935 	    * SPEC ct-props-correct
15936 	    * (5) "Two distinct attribute declarations in the
15937 	    * {attribute uses} must not have {type definition}s which
15938 	    * are or are derived from ID."
15939 	    */
15940 	    if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
15941 		if (xmlSchemaIsDerivedFromBuiltInType(
15942 		    WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
15943 		{
15944 		    if (hasId) {
15945 			xmlChar *str = NULL;
15946 
15947 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
15948 			    XML_SCHEMAP_AG_PROPS_CORRECT,
15949 			    NULL, WXS_BASIC_CAST type,
15950 			    "There must not exist more than one attribute "
15951 			    "declaration of type 'xs:ID' "
15952 			    "(or derived from 'xs:ID'). The %s violates this "
15953 			    "constraint",
15954 			    xmlSchemaGetComponentDesignation(&str, use),
15955 			    NULL);
15956 			FREE_AND_NULL(str);
15957 			if (xmlSchemaItemListRemove(uses, i) == -1)
15958 			    goto exit_failure;
15959 		    }
15960 
15961 		    hasId = 1;
15962 		}
15963 	    }
15964 next_use: {}
15965 	}
15966     }
15967     return (0);
15968 exit_failure:
15969     return(-1);
15970 }
15971 
15972 static int
xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,xmlSchemaTypePtr typeB)15973 xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
15974 		       xmlSchemaTypePtr typeB)
15975 {
15976     /*
15977     * TODO: This should implement component-identity
15978     * in the future.
15979     */
15980     if ((typeA == NULL) || (typeB == NULL))
15981 	return (0);
15982     return (typeA == typeB);
15983 }
15984 
15985 /**
15986  * xmlSchemaCheckCOSCTDerivedOK:
15987  * @ctxt:  the schema parser context
15988  * @type:  the to-be derived complex type definition
15989  * @baseType:  the base complex type definition
15990  * @set: the given set
15991  *
15992  * Schema Component Constraint:
15993  * Type Derivation OK (Complex) (cos-ct-derived-ok)
15994  *
15995  * STATUS: completed
15996  *
15997  * Returns 0 if the constraints are satisfied, or 1
15998  * if not.
15999  */
16000 static int
xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,xmlSchemaTypePtr type,xmlSchemaTypePtr baseType,int set)16001 xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16002 			     xmlSchemaTypePtr type,
16003 			     xmlSchemaTypePtr baseType,
16004 			     int set)
16005 {
16006     int equal = xmlSchemaAreEqualTypes(type, baseType);
16007     /* TODO: Error codes. */
16008     /*
16009     * SPEC "For a complex type definition (call it D, for derived)
16010     * to be validly derived from a type definition (call this
16011     * B, for base) given a subset of {extension, restriction}
16012     * all of the following must be true:"
16013     */
16014     if (! equal) {
16015 	/*
16016 	* SPEC (1) "If B and D are not the same type definition, then the
16017 	* {derivation method} of D must not be in the subset."
16018 	*/
16019 	if (((set & SUBSET_EXTENSION) && (WXS_IS_EXTENSION(type))) ||
16020 	    ((set & SUBSET_RESTRICTION) && (WXS_IS_RESTRICTION(type))))
16021 	    return (1);
16022     } else {
16023 	/*
16024 	* SPEC (2.1) "B and D must be the same type definition."
16025 	*/
16026 	return (0);
16027     }
16028     /*
16029     * SPEC (2.2) "B must be D's {base type definition}."
16030     */
16031     if (type->baseType == baseType)
16032 	return (0);
16033     /*
16034     * SPEC (2.3.1) "D's {base type definition} must not be the `ur-type
16035     * definition`."
16036     */
16037     if (WXS_IS_ANYTYPE(type->baseType))
16038 	return (1);
16039 
16040     if (WXS_IS_COMPLEX(type->baseType)) {
16041 	/*
16042 	* SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
16043 	* must be validly derived from B given the subset as defined by this
16044 	* constraint."
16045 	*/
16046 	return (xmlSchemaCheckCOSCTDerivedOK(actxt, type->baseType,
16047 	    baseType, set));
16048     } else {
16049 	/*
16050 	* SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
16051 	* must be validly derived from B given the subset as defined in Type
16052 	* Derivation OK (Simple) ($3.14.6).
16053 	*/
16054 	return (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
16055 	    baseType, set));
16056     }
16057 }
16058 
16059 /**
16060  * xmlSchemaCheckCOSDerivedOK:
16061  * @type:  the derived simple type definition
16062  * @baseType:  the base type definition
16063  *
16064  * Calls:
16065  * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
16066  *
16067  * Checks whether @type can be validly derived from @baseType.
16068  *
16069  * Returns 0 on success, an positive error code otherwise.
16070  */
16071 static int
xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt,xmlSchemaTypePtr type,xmlSchemaTypePtr baseType,int set)16072 xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16073 			   xmlSchemaTypePtr type,
16074 			   xmlSchemaTypePtr baseType,
16075 			   int set)
16076 {
16077     if (WXS_IS_SIMPLE(type))
16078 	return (xmlSchemaCheckCOSSTDerivedOK(actxt, type, baseType, set));
16079     else
16080 	return (xmlSchemaCheckCOSCTDerivedOK(actxt, type, baseType, set));
16081 }
16082 
16083 /**
16084  * xmlSchemaCheckCOSCTExtends:
16085  * @ctxt:  the schema parser context
16086  * @type:  the complex type definition
16087  *
16088  * (3.4.6) Constraints on Complex Type Definition Schema Components
16089  * Schema Component Constraint:
16090  * Derivation Valid (Extension) (cos-ct-extends)
16091  *
16092  * STATUS:
16093  *   missing:
16094  *     (1.5)
16095  *     (1.4.3.2.2.2) "Particle Valid (Extension)"
16096  *
16097  * Returns 0 if the constraints are satisfied, a positive
16098  * error code if not and -1 if an internal error occurred.
16099  */
16100 static int
xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)16101 xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
16102 			   xmlSchemaTypePtr type)
16103 {
16104     xmlSchemaTypePtr base = type->baseType;
16105     /*
16106     * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
16107     * temporarily only.
16108     */
16109     /*
16110     * SPEC (1) "If the {base type definition} is a complex type definition,
16111     * then all of the following must be true:"
16112     */
16113     if (WXS_IS_COMPLEX(base)) {
16114 	/*
16115 	* SPEC (1.1) "The {final} of the {base type definition} must not
16116 	* contain extension."
16117 	*/
16118 	if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16119 	    xmlSchemaPCustomErr(ctxt,
16120 		XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16121 		WXS_BASIC_CAST type, NULL,
16122 		"The 'final' of the base type definition "
16123 		"contains 'extension'", NULL);
16124 	    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16125 	}
16126 
16127 	/*
16128 	* ATTENTION: The constrains (1.2) and (1.3) are not applied,
16129 	* since they are automatically satisfied through the
16130 	* inheriting mechanism.
16131 	* Note that even if redefining components, the inheriting mechanism
16132 	* is used.
16133 	*/
16134 #if 0
16135 	/*
16136 	* SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
16137 	* uses}
16138 	* of the complex type definition itself, that is, for every attribute
16139 	* use in the {attribute uses} of the {base type definition}, there
16140 	* must be an attribute use in the {attribute uses} of the complex
16141 	* type definition itself whose {attribute declaration} has the same
16142 	* {name}, {target namespace} and {type definition} as its attribute
16143 	* declaration"
16144 	*/
16145 	if (base->attrUses != NULL) {
16146 	    int i, j, found;
16147 	    xmlSchemaAttributeUsePtr use, buse;
16148 
16149 	    for (i = 0; i < (WXS_LIST_CAST base->attrUses)->nbItems; i ++) {
16150 		buse = (WXS_LIST_CAST base->attrUses)->items[i];
16151 		found = 0;
16152 		if (type->attrUses != NULL) {
16153 		    use = (WXS_LIST_CAST type->attrUses)->items[j];
16154 		    for (j = 0; j < (WXS_LIST_CAST type->attrUses)->nbItems; j ++)
16155 		    {
16156 			if ((WXS_ATTRUSE_DECL_NAME(use) ==
16157 				WXS_ATTRUSE_DECL_NAME(buse)) &&
16158 			    (WXS_ATTRUSE_DECL_TNS(use) ==
16159 				WXS_ATTRUSE_DECL_TNS(buse)) &&
16160 			    (WXS_ATTRUSE_TYPEDEF(use) ==
16161 				WXS_ATTRUSE_TYPEDEF(buse))
16162 			{
16163 			    found = 1;
16164 			    break;
16165 			}
16166 		    }
16167 		}
16168 		if (! found) {
16169 		    xmlChar *str = NULL;
16170 
16171 		    xmlSchemaCustomErr(ACTXT_CAST ctxt,
16172 			XML_SCHEMAP_COS_CT_EXTENDS_1_2,
16173 			NULL, WXS_BASIC_CAST type,
16174 			/*
16175 			* TODO: The report does not indicate that also the
16176 			* type needs to be the same.
16177 			*/
16178 			"This type is missing a matching correspondent "
16179 			"for its {base type}'s %s in its {attribute uses}",
16180 			xmlSchemaGetComponentDesignation(&str,
16181 			    buse->children),
16182 			NULL);
16183 		    FREE_AND_NULL(str)
16184 		}
16185 	    }
16186 	}
16187 	/*
16188 	* SPEC (1.3) "If it has an {attribute wildcard}, the complex type
16189 	* definition must also have one, and the base type definition's
16190 	* {attribute  wildcard}'s {namespace constraint} must be a subset
16191 	* of the complex  type definition's {attribute wildcard}'s {namespace
16192 	* constraint}, as defined by Wildcard Subset ($3.10.6)."
16193 	*/
16194 
16195 	/*
16196 	* MAYBE TODO: Enable if ever needed. But this will be needed only
16197 	* if created the type via a schema construction API.
16198 	*/
16199 	if (base->attributeWildcard != NULL) {
16200 	    if (type->attributeWildcard == NULL) {
16201 		xmlChar *str = NULL;
16202 
16203 		xmlSchemaCustomErr(ACTXT_CAST pctxt,
16204 		    XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16205 		    NULL, type,
16206 		    "The base %s has an attribute wildcard, "
16207 		    "but this type is missing an attribute wildcard",
16208 		    xmlSchemaGetComponentDesignation(&str, base));
16209 		FREE_AND_NULL(str)
16210 
16211 	    } else if (xmlSchemaCheckCOSNSSubset(
16212 		base->attributeWildcard, type->attributeWildcard))
16213 	    {
16214 		xmlChar *str = NULL;
16215 
16216 		xmlSchemaCustomErr(ACTXT_CAST pctxt,
16217 		    XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16218 		    NULL, type,
16219 		    "The attribute wildcard is not a valid "
16220 		    "superset of the one in the base %s",
16221 		    xmlSchemaGetComponentDesignation(&str, base));
16222 		FREE_AND_NULL(str)
16223 	    }
16224 	}
16225 #endif
16226 	/*
16227 	* SPEC (1.4) "One of the following must be true:"
16228 	*/
16229 	if ((type->contentTypeDef != NULL) &&
16230 	    (type->contentTypeDef == base->contentTypeDef)) {
16231 	    /*
16232 	    * SPEC (1.4.1) "The {content type} of the {base type definition}
16233 	    * and the {content type} of the complex type definition itself
16234 	    * must be the same simple type definition"
16235 	    * PASS
16236 	    */
16237 	} else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
16238 	    (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
16239 	    /*
16240 	    * SPEC (1.4.2) "The {content type} of both the {base type
16241 	    * definition} and the complex type definition itself must
16242 	    * be empty."
16243 	    * PASS
16244 	    */
16245 	} else {
16246 	    /*
16247 	    * SPEC (1.4.3) "All of the following must be true:"
16248 	    */
16249 	    if (type->subtypes == NULL) {
16250 		/*
16251 		* SPEC 1.4.3.1 The {content type} of the complex type
16252 		* definition itself must specify a particle.
16253 		*/
16254 		xmlSchemaPCustomErr(ctxt,
16255 		    XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16256 		    WXS_BASIC_CAST type, NULL,
16257 		    "The content type must specify a particle", NULL);
16258 		return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16259 	    }
16260 	    /*
16261 	    * SPEC (1.4.3.2) "One of the following must be true:"
16262 	    */
16263 	    if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16264 		/*
16265 		* SPEC (1.4.3.2.1) "The {content type} of the {base type
16266 		* definition} must be empty.
16267 		* PASS
16268 		*/
16269 	    } else {
16270 		/*
16271 		* SPEC (1.4.3.2.2) "All of the following must be true:"
16272 		*/
16273 		if ((type->contentType != base->contentType) ||
16274 		    ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
16275 		    (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
16276 		    /*
16277 		    * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
16278 		    * or both must be element-only."
16279 		    */
16280 		    xmlSchemaPCustomErr(ctxt,
16281 			XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16282 			WXS_BASIC_CAST type, NULL,
16283 			"The content type of both, the type and its base "
16284 			"type, must either 'mixed' or 'element-only'", NULL);
16285 		    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16286 		}
16287 		/*
16288 		* URGENT TODO SPEC (1.4.3.2.2.2) "The particle of the
16289 		* complex type definition must be a `valid extension`
16290 		* of the {base type definition}'s particle, as defined
16291 		* in Particle Valid (Extension) ($3.9.6)."
16292 		*
16293 		* NOTE that we won't check "Particle Valid (Extension)",
16294 		* since it is ensured by the derivation process in
16295 		* xmlSchemaTypeFixup(). We need to implement this when heading
16296 		* for a construction API
16297 		* TODO: !! This is needed to be checked if redefining a type !!
16298 		*/
16299 	    }
16300 	    /*
16301 	    * URGENT TODO (1.5)
16302 	    */
16303 	}
16304     } else {
16305 	/*
16306 	* SPEC (2) "If the {base type definition} is a simple type definition,
16307 	* then all of the following must be true:"
16308 	*/
16309 	if (type->contentTypeDef != base) {
16310 	    /*
16311 	    * SPEC (2.1) "The {content type} must be the same simple type
16312 	    * definition."
16313 	    */
16314 	    xmlSchemaPCustomErr(ctxt,
16315 		XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16316 		WXS_BASIC_CAST type, NULL,
16317 		"The content type must be the simple base type", NULL);
16318 	    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16319 	}
16320 	if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16321 	    /*
16322 	    * SPEC (2.2) "The {final} of the {base type definition} must not
16323 	    * contain extension"
16324 	    * NOTE that this is the same as (1.1).
16325 	    */
16326 	    xmlSchemaPCustomErr(ctxt,
16327 		XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16328 		WXS_BASIC_CAST type, NULL,
16329 		"The 'final' of the base type definition "
16330 		"contains 'extension'", NULL);
16331 	    return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16332 	}
16333     }
16334     return (0);
16335 }
16336 
16337 /**
16338  * xmlSchemaCheckDerivationOKRestriction:
16339  * @ctxt:  the schema parser context
16340  * @type:  the complex type definition
16341  *
16342  * (3.4.6) Constraints on Complex Type Definition Schema Components
16343  * Schema Component Constraint:
16344  * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
16345  *
16346  * STATUS:
16347  *   missing:
16348  *     (5.4.2) ???
16349  *
16350  * ATTENTION:
16351  * In XML Schema 1.1 this will be:
16352  * Validation Rule: Checking complex type subsumption
16353  *
16354  * Returns 0 if the constraints are satisfied, a positive
16355  * error code if not and -1 if an internal error occurred.
16356  */
16357 static int
xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)16358 xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
16359 				      xmlSchemaTypePtr type)
16360 {
16361     xmlSchemaTypePtr base;
16362 
16363     /*
16364     * TODO: Correct the error code; XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1 is used
16365     * temporarily only.
16366     */
16367     base = type->baseType;
16368     if (! WXS_IS_COMPLEX(base)) {
16369 	xmlSchemaCustomErr(ACTXT_CAST ctxt,
16370 	    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16371 	    type->node, WXS_BASIC_CAST type,
16372 	    "The base type must be a complex type", NULL, NULL);
16373 	return(ctxt->err);
16374     }
16375     if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
16376 	/*
16377 	* SPEC (1) "The {base type definition} must be a complex type
16378 	* definition whose {final} does not contain restriction."
16379 	*/
16380 	xmlSchemaCustomErr(ACTXT_CAST ctxt,
16381 	    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16382 	    type->node, WXS_BASIC_CAST type,
16383 	    "The 'final' of the base type definition "
16384 	    "contains 'restriction'", NULL, NULL);
16385 	return (ctxt->err);
16386     }
16387     /*
16388     * SPEC (2), (3) and (4)
16389     * Those are handled in a separate function, since the
16390     * same constraints are needed for redefinition of
16391     * attribute groups as well.
16392     */
16393     if (xmlSchemaCheckDerivationOKRestriction2to4(ctxt,
16394 	XML_SCHEMA_ACTION_DERIVE,
16395 	WXS_BASIC_CAST type, WXS_BASIC_CAST base,
16396 	type->attrUses, base->attrUses,
16397 	type->attributeWildcard,
16398 	base->attributeWildcard) == -1)
16399     {
16400 	return(-1);
16401     }
16402     /*
16403     * SPEC (5) "One of the following must be true:"
16404     */
16405     if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
16406 	/*
16407 	* SPEC (5.1) "The {base type definition} must be the
16408 	* `ur-type definition`."
16409 	* PASS
16410 	*/
16411     } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16412 	    (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16413 	/*
16414 	* SPEC (5.2.1) "The {content type} of the complex type definition
16415 	* must be a simple type definition"
16416 	*
16417 	* SPEC (5.2.2) "One of the following must be true:"
16418 	*/
16419 	if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16420 	    (base->contentType == XML_SCHEMA_CONTENT_BASIC))
16421 	{
16422 	    int err;
16423 	    /*
16424 	    * SPEC (5.2.2.1) "The {content type} of the {base type
16425 	    * definition} must be a simple type definition from which
16426 	    * the {content type} is validly derived given the empty
16427 	    * set as defined in Type Derivation OK (Simple) ($3.14.6)."
16428 	    *
16429 	    * ATTENTION TODO: This seems not needed if the type implicitly
16430 	    * derived from the base type.
16431 	    *
16432 	    */
16433 	    err = xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST ctxt,
16434 		type->contentTypeDef, base->contentTypeDef, 0);
16435 	    if (err != 0) {
16436 		xmlChar *strA = NULL, *strB = NULL;
16437 
16438 		if (err == -1)
16439 		    return(-1);
16440 		xmlSchemaCustomErr(ACTXT_CAST ctxt,
16441 		    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16442 		    NULL, WXS_BASIC_CAST type,
16443 		    "The {content type} %s is not validly derived from the "
16444 		    "base type's {content type} %s",
16445 		    xmlSchemaGetComponentDesignation(&strA,
16446 			type->contentTypeDef),
16447 		    xmlSchemaGetComponentDesignation(&strB,
16448 			base->contentTypeDef));
16449 		FREE_AND_NULL(strA);
16450 		FREE_AND_NULL(strB);
16451 		return(ctxt->err);
16452 	    }
16453 	} else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16454 	    (xmlSchemaIsParticleEmptiable(
16455 		(xmlSchemaParticlePtr) base->subtypes))) {
16456 	    /*
16457 	    * SPEC (5.2.2.2) "The {base type definition} must be mixed
16458 	    * and have a particle which is `emptiable` as defined in
16459 	    * Particle Emptiable ($3.9.6)."
16460 	    * PASS
16461 	    */
16462 	} else {
16463 	    xmlSchemaPCustomErr(ctxt,
16464 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16465 		WXS_BASIC_CAST type, NULL,
16466 		"The content type of the base type must be either "
16467 		"a simple type or 'mixed' and an emptiable particle", NULL);
16468 	    return (ctxt->err);
16469 	}
16470     } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16471 	/*
16472 	* SPEC (5.3.1) "The {content type} of the complex type itself must
16473 	* be empty"
16474 	*/
16475 	if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16476 	    /*
16477 	    * SPEC (5.3.2.1) "The {content type} of the {base type
16478 	    * definition} must also be empty."
16479 	    * PASS
16480 	    */
16481 	} else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16482 	    (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
16483 	    xmlSchemaIsParticleEmptiable(
16484 		(xmlSchemaParticlePtr) base->subtypes)) {
16485 	    /*
16486 	    * SPEC (5.3.2.2) "The {content type} of the {base type
16487 	    * definition} must be elementOnly or mixed and have a particle
16488 	    * which is `emptiable` as defined in Particle Emptiable ($3.9.6)."
16489 	    * PASS
16490 	    */
16491 	} else {
16492 	    xmlSchemaPCustomErr(ctxt,
16493 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16494 		WXS_BASIC_CAST type, NULL,
16495 		"The content type of the base type must be either "
16496 		"empty or 'mixed' (or 'elements-only') and an emptiable "
16497 		"particle", NULL);
16498 	    return (ctxt->err);
16499 	}
16500     } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16501 	WXS_HAS_MIXED_CONTENT(type)) {
16502 	/*
16503 	* SPEC (5.4.1.1) "The {content type} of the complex type definition
16504 	* itself must be element-only"
16505 	*/
16506 	if (WXS_HAS_MIXED_CONTENT(type) && (! WXS_HAS_MIXED_CONTENT(base))) {
16507 	    /*
16508 	    * SPEC (5.4.1.2) "The {content type} of the complex type
16509 	    * definition itself and of the {base type definition} must be
16510 	    * mixed"
16511 	    */
16512 	    xmlSchemaPCustomErr(ctxt,
16513 		XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16514 		WXS_BASIC_CAST type, NULL,
16515 		"If the content type is 'mixed', then the content type of the "
16516 		"base type must also be 'mixed'", NULL);
16517 	    return (ctxt->err);
16518 	}
16519 	/*
16520 	* SPEC (5.4.2) "The particle of the complex type definition itself
16521 	* must be a `valid restriction` of the particle of the {content
16522 	* type} of the {base type definition} as defined in Particle Valid
16523 	* (Restriction) ($3.9.6).
16524 	*
16525 	* URGENT TODO: (5.4.2)
16526 	*/
16527     } else {
16528 	xmlSchemaPCustomErr(ctxt,
16529 	    XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16530 	    WXS_BASIC_CAST type, NULL,
16531 	    "The type is not a valid restriction of its base type", NULL);
16532 	return (ctxt->err);
16533     }
16534     return (0);
16535 }
16536 
16537 /**
16538  * xmlSchemaCheckCTComponent:
16539  * @ctxt:  the schema parser context
16540  * @type:  the complex type definition
16541  *
16542  * (3.4.6) Constraints on Complex Type Definition Schema Components
16543  *
16544  * Returns 0 if the constraints are satisfied, a positive
16545  * error code if not and -1 if an internal error occurred.
16546  */
16547 static int
xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)16548 xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
16549 			  xmlSchemaTypePtr type)
16550 {
16551     int ret;
16552     /*
16553     * Complex Type Definition Properties Correct
16554     */
16555     ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
16556     if (ret != 0)
16557 	return (ret);
16558     if (WXS_IS_EXTENSION(type))
16559 	ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
16560     else
16561 	ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
16562     return (ret);
16563 }
16564 
16565 /**
16566  * xmlSchemaCheckSRCCT:
16567  * @ctxt:  the schema parser context
16568  * @type:  the complex type definition
16569  *
16570  * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
16571  * Schema Representation Constraint:
16572  * Complex Type Definition Representation OK (src-ct)
16573  *
16574  * Returns 0 if the constraints are satisfied, a positive
16575  * error code if not and -1 if an internal error occurred.
16576  */
16577 static int
xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,xmlSchemaTypePtr type)16578 xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
16579 		    xmlSchemaTypePtr type)
16580 {
16581     xmlSchemaTypePtr base;
16582     int ret = 0;
16583 
16584     /*
16585     * TODO: Adjust the error codes here, as I used
16586     * XML_SCHEMAP_SRC_CT_1 only yet.
16587     */
16588     base = type->baseType;
16589     if (! WXS_HAS_SIMPLE_CONTENT(type)) {
16590 	/*
16591 	* 1 If the <complexContent> alternative is chosen, the type definition
16592 	* `resolved` to by the `actual value` of the base [attribute]
16593 	* must be a complex type definition;
16594 	*/
16595 	if (! WXS_IS_COMPLEX(base)) {
16596 	    xmlChar *str = NULL;
16597 	    xmlSchemaPCustomErr(ctxt,
16598 		XML_SCHEMAP_SRC_CT_1,
16599 		WXS_BASIC_CAST type, type->node,
16600 		"If using <complexContent>, the base type is expected to be "
16601 		"a complex type. The base type '%s' is a simple type",
16602 		xmlSchemaFormatQName(&str, base->targetNamespace,
16603 		base->name));
16604 	    FREE_AND_NULL(str)
16605 	    return (XML_SCHEMAP_SRC_CT_1);
16606 	}
16607     } else {
16608 	/*
16609 	* SPEC
16610 	* 2 If the <simpleContent> alternative is chosen, all of the
16611 	* following must be true:
16612 	* 2.1 The type definition `resolved` to by the `actual value` of the
16613 	* base [attribute] must be one of the following:
16614 	*/
16615 	if (WXS_IS_SIMPLE(base)) {
16616 	    if (WXS_IS_EXTENSION(type) == 0) {
16617 		xmlChar *str = NULL;
16618 		/*
16619 		* 2.1.3 only if the <extension> alternative is also
16620 		* chosen, a simple type definition.
16621 		*/
16622 		/* TODO: Change error code to ..._SRC_CT_2_1_3. */
16623 		xmlSchemaPCustomErr(ctxt,
16624 		    XML_SCHEMAP_SRC_CT_1,
16625 		    WXS_BASIC_CAST type, NULL,
16626 		    "If using <simpleContent> and <restriction>, the base "
16627 		    "type must be a complex type. The base type '%s' is "
16628 		    "a simple type",
16629 		    xmlSchemaFormatQName(&str, base->targetNamespace,
16630 			base->name));
16631 		FREE_AND_NULL(str)
16632 		return (XML_SCHEMAP_SRC_CT_1);
16633 	    }
16634 	} else {
16635 	    /* Base type is a complex type. */
16636 	    if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16637 		(base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16638 		/*
16639 		* 2.1.1 a complex type definition whose {content type} is a
16640 		* simple type definition;
16641 		* PASS
16642 		*/
16643 		if (base->contentTypeDef == NULL) {
16644 		    xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
16645 			WXS_BASIC_CAST type, NULL,
16646 			"Internal error: xmlSchemaCheckSRCCT, "
16647 			"'%s', base type has no content type",
16648 			type->name);
16649 		    return (-1);
16650 		}
16651 	    } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16652 		(WXS_IS_RESTRICTION(type))) {
16653 
16654 		/*
16655 		* 2.1.2 only if the <restriction> alternative is also
16656 		* chosen, a complex type definition whose {content type}
16657 		* is mixed and a particle emptiable.
16658 		*/
16659 		if (! xmlSchemaIsParticleEmptiable(
16660 		    (xmlSchemaParticlePtr) base->subtypes)) {
16661 		    ret = XML_SCHEMAP_SRC_CT_1;
16662 		} else
16663 		    /*
16664 		    * Attention: at this point the <simpleType> child is in
16665 		    * ->contentTypeDef (put there during parsing).
16666 		    */
16667 		    if (type->contentTypeDef == NULL) {
16668 		    xmlChar *str = NULL;
16669 		    /*
16670 		    * 2.2 If clause 2.1.2 above is satisfied, then there
16671 		    * must be a <simpleType> among the [children] of
16672 		    * <restriction>.
16673 		    */
16674 		    /* TODO: Change error code to ..._SRC_CT_2_2. */
16675 		    xmlSchemaPCustomErr(ctxt,
16676 			XML_SCHEMAP_SRC_CT_1,
16677 			WXS_BASIC_CAST type, NULL,
16678 			"A <simpleType> is expected among the children "
16679 			"of <restriction>, if <simpleContent> is used and "
16680 			"the base type '%s' is a complex type",
16681 			xmlSchemaFormatQName(&str, base->targetNamespace,
16682 			base->name));
16683 		    FREE_AND_NULL(str)
16684 		    return (XML_SCHEMAP_SRC_CT_1);
16685 		}
16686 	    } else {
16687 		ret = XML_SCHEMAP_SRC_CT_1;
16688 	    }
16689 	}
16690 	if (ret > 0) {
16691 	    xmlChar *str = NULL;
16692 	    if (WXS_IS_RESTRICTION(type)) {
16693 		xmlSchemaPCustomErr(ctxt,
16694 		    XML_SCHEMAP_SRC_CT_1,
16695 		    WXS_BASIC_CAST type, NULL,
16696 		    "If <simpleContent> and <restriction> is used, the "
16697 		    "base type must be a simple type or a complex type with "
16698 		    "mixed content and particle emptiable. The base type "
16699 		    "'%s' is none of those",
16700 		    xmlSchemaFormatQName(&str, base->targetNamespace,
16701 		    base->name));
16702 	    } else {
16703 		xmlSchemaPCustomErr(ctxt,
16704 		    XML_SCHEMAP_SRC_CT_1,
16705 		    WXS_BASIC_CAST type, NULL,
16706 		    "If <simpleContent> and <extension> is used, the "
16707 		    "base type must be a simple type. The base type '%s' "
16708 		    "is a complex type",
16709 		    xmlSchemaFormatQName(&str, base->targetNamespace,
16710 		    base->name));
16711 	    }
16712 	    FREE_AND_NULL(str)
16713 	}
16714     }
16715     /*
16716     * SPEC (3) "The corresponding complex type definition component must
16717     * satisfy the conditions set out in Constraints on Complex Type
16718     * Definition Schema Components ($3.4.6);"
16719     * NOTE (3) will be done in xmlSchemaTypeFixup().
16720     */
16721     /*
16722     * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
16723     * above for {attribute wildcard} is satisfied, the intensional
16724     * intersection must be expressible, as defined in Attribute Wildcard
16725     * Intersection ($3.10.6).
16726     * NOTE (4) is done in xmlSchemaFixupTypeAttributeUses().
16727     */
16728     return (ret);
16729 }
16730 
16731 #ifdef ENABLE_PARTICLE_RESTRICTION
16732 /**
16733  * xmlSchemaCheckParticleRangeOK:
16734  * @ctxt:  the schema parser context
16735  * @type:  the complex type definition
16736  *
16737  * (3.9.6) Constraints on Particle Schema Components
16738  * Schema Component Constraint:
16739  * Occurrence Range OK (range-ok)
16740  *
16741  * STATUS: complete
16742  *
16743  * Returns 0 if the constraints are satisfied, a positive
16744  * error code if not and -1 if an internal error occurred.
16745  */
16746 static int
xmlSchemaCheckParticleRangeOK(int rmin,int rmax,int bmin,int bmax)16747 xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
16748 			      int bmin, int bmax)
16749 {
16750     if (rmin < bmin)
16751 	return (1);
16752     if ((bmax != UNBOUNDED) &&
16753 	(rmax > bmax))
16754 	return (1);
16755     return (0);
16756 }
16757 
16758 /**
16759  * xmlSchemaCheckRCaseNameAndTypeOK:
16760  * @ctxt:  the schema parser context
16761  * @r: the restricting element declaration particle
16762  * @b: the base element declaration particle
16763  *
16764  * (3.9.6) Constraints on Particle Schema Components
16765  * Schema Component Constraint:
16766  * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
16767  * (rcase-NameAndTypeOK)
16768  *
16769  * STATUS:
16770  *   MISSING (3.2.3)
16771  *   CLARIFY: (3.2.2)
16772  *
16773  * Returns 0 if the constraints are satisfied, a positive
16774  * error code if not and -1 if an internal error occurred.
16775  */
16776 static int
xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)16777 xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
16778 				 xmlSchemaParticlePtr r,
16779 				 xmlSchemaParticlePtr b)
16780 {
16781     xmlSchemaElementPtr elemR, elemB;
16782 
16783     /* TODO: Error codes (rcase-NameAndTypeOK). */
16784     elemR = (xmlSchemaElementPtr) r->children;
16785     elemB = (xmlSchemaElementPtr) b->children;
16786     /*
16787     * SPEC (1) "The declarations' {name}s and {target namespace}s are
16788     * the same."
16789     */
16790     if ((elemR != elemB) &&
16791 	((! xmlStrEqual(elemR->name, elemB->name)) ||
16792 	(! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
16793 	return (1);
16794     /*
16795     * SPEC (2) "R's occurrence range is a valid restriction of B's
16796     * occurrence range as defined by Occurrence Range OK ($3.9.6)."
16797     */
16798     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16799 	    b->minOccurs, b->maxOccurs) != 0)
16800 	return (1);
16801     /*
16802     * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
16803     * {scope} are global."
16804     */
16805     if (elemR == elemB)
16806 	return (0);
16807     /*
16808     * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
16809     */
16810     if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
16811 	(elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
16812 	 return (1);
16813     /*
16814     * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
16815     * or is not fixed, or R's declaration's {value constraint} is fixed
16816     * with the same value."
16817     */
16818     if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
16819 	((elemR->value == NULL) ||
16820 	 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
16821 	 /* TODO: Equality of the initial value or normalized or canonical? */
16822 	 (! xmlStrEqual(elemR->value, elemB->value))))
16823 	 return (1);
16824     /*
16825     * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
16826     * definitions} is a subset of B's declaration's {identity-constraint
16827     * definitions}, if any."
16828     */
16829     if (elemB->idcs != NULL) {
16830 	/* TODO */
16831     }
16832     /*
16833     * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
16834     * superset of B's declaration's {disallowed substitutions}."
16835     */
16836     if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
16837 	 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
16838 	((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
16839 	 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
16840 	((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
16841 	 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
16842 	 return (1);
16843     /*
16844     * SPEC (3.2.5) "R's {type definition} is validly derived given
16845     * {extension, list, union} from B's {type definition}"
16846     *
16847     * BADSPEC TODO: What's the point of adding "list" and "union" to the
16848     * set, if the corresponding constraints handle "restriction" and
16849     * "extension" only?
16850     *
16851     */
16852     {
16853 	int set = 0;
16854 
16855 	set |= SUBSET_EXTENSION;
16856 	set |= SUBSET_LIST;
16857 	set |= SUBSET_UNION;
16858 	if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST ctxt, elemR->subtypes,
16859 	    elemB->subtypes, set) != 0)
16860 	    return (1);
16861     }
16862     return (0);
16863 }
16864 
16865 /**
16866  * xmlSchemaCheckRCaseNSCompat:
16867  * @ctxt:  the schema parser context
16868  * @r: the restricting element declaration particle
16869  * @b: the base wildcard particle
16870  *
16871  * (3.9.6) Constraints on Particle Schema Components
16872  * Schema Component Constraint:
16873  * Particle Derivation OK (Elt:Any -- NSCompat)
16874  * (rcase-NSCompat)
16875  *
16876  * STATUS: complete
16877  *
16878  * Returns 0 if the constraints are satisfied, a positive
16879  * error code if not and -1 if an internal error occurred.
16880  */
16881 static int
xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)16882 xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
16883 			    xmlSchemaParticlePtr r,
16884 			    xmlSchemaParticlePtr b)
16885 {
16886     /* TODO:Error codes (rcase-NSCompat). */
16887     /*
16888     * SPEC "For an element declaration particle to be a `valid restriction`
16889     * of a wildcard particle all of the following must be true:"
16890     *
16891     * SPEC (1) "The element declaration's {target namespace} is `valid`
16892     * with respect to the wildcard's {namespace constraint} as defined by
16893     * Wildcard allows Namespace Name ($3.10.4)."
16894     */
16895     if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
16896 	((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
16897 	return (1);
16898     /*
16899     * SPEC (2) "R's occurrence range is a valid restriction of B's
16900     * occurrence range as defined by Occurrence Range OK ($3.9.6)."
16901     */
16902     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16903 	    b->minOccurs, b->maxOccurs) != 0)
16904 	return (1);
16905 
16906     return (0);
16907 }
16908 
16909 /**
16910  * xmlSchemaCheckRCaseRecurseAsIfGroup:
16911  * @ctxt:  the schema parser context
16912  * @r: the restricting element declaration particle
16913  * @b: the base model group particle
16914  *
16915  * (3.9.6) Constraints on Particle Schema Components
16916  * Schema Component Constraint:
16917  * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
16918  * (rcase-RecurseAsIfGroup)
16919  *
16920  * STATUS: TODO
16921  *
16922  * Returns 0 if the constraints are satisfied, a positive
16923  * error code if not and -1 if an internal error occurred.
16924  */
16925 static int
xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)16926 xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
16927 				    xmlSchemaParticlePtr r,
16928 				    xmlSchemaParticlePtr b)
16929 {
16930     /* TODO: Error codes (rcase-RecurseAsIfGroup). */
16931     TODO
16932     return (0);
16933 }
16934 
16935 /**
16936  * xmlSchemaCheckRCaseNSSubset:
16937  * @ctxt:  the schema parser context
16938  * @r: the restricting wildcard particle
16939  * @b: the base wildcard particle
16940  *
16941  * (3.9.6) Constraints on Particle Schema Components
16942  * Schema Component Constraint:
16943  * Particle Derivation OK (Any:Any -- NSSubset)
16944  * (rcase-NSSubset)
16945  *
16946  * STATUS: complete
16947  *
16948  * Returns 0 if the constraints are satisfied, a positive
16949  * error code if not and -1 if an internal error occurred.
16950  */
16951 static int
xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b,int isAnyTypeBase)16952 xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
16953 				    xmlSchemaParticlePtr r,
16954 				    xmlSchemaParticlePtr b,
16955 				    int isAnyTypeBase)
16956 {
16957     /* TODO: Error codes (rcase-NSSubset). */
16958     /*
16959     * SPEC (1) "R's occurrence range is a valid restriction of B's
16960     * occurrence range as defined by Occurrence Range OK ($3.9.6)."
16961     */
16962     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16963 	    b->minOccurs, b->maxOccurs))
16964 	return (1);
16965     /*
16966     * SPEC (2) "R's {namespace constraint} must be an intensional subset
16967     * of B's {namespace constraint} as defined by Wildcard Subset ($3.10.6)."
16968     */
16969     if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
16970 	(xmlSchemaWildcardPtr) b->children))
16971 	return (1);
16972     /*
16973     * SPEC (3) "Unless B is the content model wildcard of the `ur-type
16974     * definition`, R's {process contents} must be identical to or stronger
16975     * than B's {process contents}, where strict is stronger than lax is
16976     * stronger than skip."
16977     */
16978     if (! isAnyTypeBase) {
16979 	if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
16980 	    ((xmlSchemaWildcardPtr) b->children)->processContents)
16981 	    return (1);
16982     }
16983 
16984     return (0);
16985 }
16986 
16987 /**
16988  * xmlSchemaCheckCOSParticleRestrict:
16989  * @ctxt:  the schema parser context
16990  * @type:  the complex type definition
16991  *
16992  * (3.9.6) Constraints on Particle Schema Components
16993  * Schema Component Constraint:
16994  * Particle Valid (Restriction) (cos-particle-restrict)
16995  *
16996  * STATUS: TODO
16997  *
16998  * Returns 0 if the constraints are satisfied, a positive
16999  * error code if not and -1 if an internal error occurred.
17000  */
17001 static int
xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)17002 xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
17003 				  xmlSchemaParticlePtr r,
17004 				  xmlSchemaParticlePtr b)
17005 {
17006     int ret = 0;
17007 
17008     /*part = WXS_TYPE_PARTICLE(type);
17009     basePart = WXS_TYPE_PARTICLE(base);
17010     */
17011 
17012     TODO
17013 
17014     /*
17015     * SPEC (1) "They are the same particle."
17016     */
17017     if (r == b)
17018 	return (0);
17019 
17020 
17021     return (0);
17022 }
17023 
17024 #if 0
17025 /**
17026  * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
17027  * @ctxt:  the schema parser context
17028  * @r: the model group particle
17029  * @b: the base wildcard particle
17030  *
17031  * (3.9.6) Constraints on Particle Schema Components
17032  * Schema Component Constraint:
17033  * Particle Derivation OK (All/Choice/Sequence:Any --
17034  *                         NSRecurseCheckCardinality)
17035  * (rcase-NSRecurseCheckCardinality)
17036  *
17037  * STATUS: TODO: subst-groups
17038  *
17039  * Returns 0 if the constraints are satisfied, a positive
17040  * error code if not and -1 if an internal error occurred.
17041  */
17042 static int
17043 xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
17044 					     xmlSchemaParticlePtr r,
17045 					     xmlSchemaParticlePtr b)
17046 {
17047     xmlSchemaParticlePtr part;
17048     /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
17049     if ((r->children == NULL) || (r->children->children == NULL))
17050 	return (-1);
17051     /*
17052     * SPEC "For a group particle to be a `valid restriction` of a
17053     * wildcard particle..."
17054     *
17055     * SPEC (1) "Every member of the {particles} of the group is a `valid
17056     * restriction` of the wildcard as defined by
17057     * Particle Valid (Restriction) ($3.9.6)."
17058     */
17059     part = (xmlSchemaParticlePtr) r->children->children;
17060     do {
17061 	if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
17062 	    return (1);
17063 	part = (xmlSchemaParticlePtr) part->next;
17064     } while (part != NULL);
17065     /*
17066     * SPEC (2) "The effective total range of the group [...] is a
17067     * valid restriction of B's occurrence range as defined by
17068     * Occurrence Range OK ($3.9.6)."
17069     */
17070     if (xmlSchemaCheckParticleRangeOK(
17071 	    xmlSchemaGetParticleTotalRangeMin(r),
17072 	    xmlSchemaGetParticleTotalRangeMax(r),
17073 	    b->minOccurs, b->maxOccurs) != 0)
17074 	return (1);
17075     return (0);
17076 }
17077 #endif
17078 
17079 /**
17080  * xmlSchemaCheckRCaseRecurse:
17081  * @ctxt:  the schema parser context
17082  * @r: the <all> or <sequence> model group particle
17083  * @b: the base <all> or <sequence> model group particle
17084  *
17085  * (3.9.6) Constraints on Particle Schema Components
17086  * Schema Component Constraint:
17087  * Particle Derivation OK (All:All,Sequence:Sequence --
17088                            Recurse)
17089  * (rcase-Recurse)
17090  *
17091  * STATUS:  ?
17092  * TODO: subst-groups
17093  *
17094  * Returns 0 if the constraints are satisfied, a positive
17095  * error code if not and -1 if an internal error occurred.
17096  */
17097 static int
xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,xmlSchemaParticlePtr r,xmlSchemaParticlePtr b)17098 xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
17099 			   xmlSchemaParticlePtr r,
17100 			   xmlSchemaParticlePtr b)
17101 {
17102     /* xmlSchemaParticlePtr part; */
17103     /* TODO: Error codes (rcase-Recurse). */
17104     if ((r->children == NULL) || (b->children == NULL) ||
17105 	(r->children->type != b->children->type))
17106 	return (-1);
17107     /*
17108     * SPEC "For an all or sequence group particle to be a `valid
17109     * restriction` of another group particle with the same {compositor}..."
17110     *
17111     * SPEC (1) "R's occurrence range is a valid restriction of B's
17112     * occurrence range as defined by Occurrence Range OK ($3.9.6)."
17113     */
17114     if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17115 	    b->minOccurs, b->maxOccurs))
17116 	return (1);
17117 
17118 
17119     return (0);
17120 }
17121 
17122 #endif
17123 
17124 #define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
17125     xmlSchemaPCustomErrExt(pctxt,      \
17126 	XML_SCHEMAP_INVALID_FACET_VALUE, \
17127 	WXS_BASIC_CAST fac1, fac1->node, \
17128 	"It is an error for both '%s' and '%s' to be specified on the "\
17129 	"same type definition", \
17130 	BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
17131 	BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
17132 
17133 #define FACET_RESTR_ERR(fac1, msg) \
17134     xmlSchemaPCustomErr(pctxt,      \
17135 	XML_SCHEMAP_INVALID_FACET_VALUE, \
17136 	WXS_BASIC_CAST fac1, fac1->node, \
17137 	msg, NULL);
17138 
17139 #define FACET_RESTR_FIXED_ERR(fac) \
17140     xmlSchemaPCustomErr(pctxt, \
17141 	XML_SCHEMAP_INVALID_FACET_VALUE, \
17142 	WXS_BASIC_CAST fac, fac->node, \
17143 	"The base type's facet is 'fixed', thus the value must not " \
17144 	"differ", NULL);
17145 
17146 static void
xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,xmlSchemaFacetPtr facet1,xmlSchemaFacetPtr facet2,int lessGreater,int orEqual,int ofBase)17147 xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
17148 			xmlSchemaFacetPtr facet1,
17149 			xmlSchemaFacetPtr facet2,
17150 			int lessGreater,
17151 			int orEqual,
17152 			int ofBase)
17153 {
17154     xmlChar *msg = NULL;
17155 
17156     msg = xmlStrdup(BAD_CAST "'");
17157     msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
17158     msg = xmlStrcat(msg, BAD_CAST "' has to be");
17159     if (lessGreater == 0)
17160 	msg = xmlStrcat(msg, BAD_CAST " equal to");
17161     if (lessGreater == 1)
17162 	msg = xmlStrcat(msg, BAD_CAST " greater than");
17163     else
17164 	msg = xmlStrcat(msg, BAD_CAST " less than");
17165 
17166     if (orEqual)
17167 	msg = xmlStrcat(msg, BAD_CAST " or equal to");
17168     msg = xmlStrcat(msg, BAD_CAST " '");
17169     msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
17170     if (ofBase)
17171 	msg = xmlStrcat(msg, BAD_CAST "' of the base type");
17172     else
17173 	msg = xmlStrcat(msg, BAD_CAST "'");
17174 
17175     xmlSchemaPCustomErr(pctxt,
17176 	XML_SCHEMAP_INVALID_FACET_VALUE,
17177 	WXS_BASIC_CAST facet1, NULL,
17178 	(const char *) msg, NULL);
17179 
17180     if (msg != NULL)
17181 	xmlFree(msg);
17182 }
17183 
17184 /*
17185 * xmlSchemaDeriveAndValidateFacets:
17186 *
17187 * Schema Component Constraint: Simple Type Restriction (Facets)
17188 * (st-restrict-facets)
17189 */
17190 static int
xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)17191 xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
17192 				 xmlSchemaTypePtr type)
17193 {
17194     xmlSchemaTypePtr base = type->baseType;
17195     xmlSchemaFacetLinkPtr link, cur, last = NULL;
17196     xmlSchemaFacetPtr facet, bfacet,
17197 	flength = NULL, ftotdig = NULL, ffracdig = NULL,
17198 	fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
17199 	fmininc = NULL, fmaxinc = NULL,
17200 	fminexc = NULL, fmaxexc = NULL,
17201 	bflength = NULL, bftotdig = NULL, bffracdig = NULL,
17202 	bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
17203 	bfmininc = NULL, bfmaxinc = NULL,
17204 	bfminexc = NULL, bfmaxexc = NULL;
17205     int res; /* err = 0, fixedErr; */
17206 
17207     /*
17208     * SPEC st-restrict-facets 1:
17209     * "The {variety} of R is the same as that of B."
17210     */
17211     /*
17212     * SPEC st-restrict-facets 2:
17213     * "If {variety} is atomic, the {primitive type definition}
17214     * of R is the same as that of B."
17215     *
17216     * NOTE: we leave 1 & 2 out for now, since this will be
17217     * satisfied by the derivation process.
17218     * CONSTRUCTION TODO: Maybe needed if using a construction API.
17219     */
17220     /*
17221     * SPEC st-restrict-facets 3:
17222     * "The {facets} of R are the union of S and the {facets}
17223     * of B, eliminating duplicates. To eliminate duplicates,
17224     * when a facet of the same kind occurs in both S and the
17225     * {facets} of B, the one in the {facets} of B is not
17226     * included, with the exception of enumeration and pattern
17227     * facets, for which multiple occurrences with distinct values
17228     * are allowed."
17229     */
17230 
17231     if ((type->facetSet == NULL) && (base->facetSet == NULL))
17232 	return (0);
17233 
17234     last = type->facetSet;
17235     if (last != NULL)
17236 	while (last->next != NULL)
17237 	    last = last->next;
17238 
17239     for (cur = type->facetSet; cur != NULL; cur = cur->next) {
17240 	facet = cur->facet;
17241 	switch (facet->type) {
17242 	    case XML_SCHEMA_FACET_LENGTH:
17243 		flength = facet; break;
17244 	    case XML_SCHEMA_FACET_MINLENGTH:
17245 		fminlen = facet; break;
17246 	    case XML_SCHEMA_FACET_MININCLUSIVE:
17247 		fmininc = facet; break;
17248 	    case XML_SCHEMA_FACET_MINEXCLUSIVE:
17249 		fminexc = facet; break;
17250 	    case XML_SCHEMA_FACET_MAXLENGTH:
17251 		fmaxlen = facet; break;
17252 	    case XML_SCHEMA_FACET_MAXINCLUSIVE:
17253 		fmaxinc = facet; break;
17254 	    case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17255 		fmaxexc = facet; break;
17256 	    case XML_SCHEMA_FACET_TOTALDIGITS:
17257 		ftotdig = facet; break;
17258 	    case XML_SCHEMA_FACET_FRACTIONDIGITS:
17259 		ffracdig = facet; break;
17260 	    default:
17261 		break;
17262 	}
17263     }
17264     for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17265 	facet = cur->facet;
17266 	switch (facet->type) {
17267 	    case XML_SCHEMA_FACET_LENGTH:
17268 		bflength = facet; break;
17269 	    case XML_SCHEMA_FACET_MINLENGTH:
17270 		bfminlen = facet; break;
17271 	    case XML_SCHEMA_FACET_MININCLUSIVE:
17272 		bfmininc = facet; break;
17273 	    case XML_SCHEMA_FACET_MINEXCLUSIVE:
17274 		bfminexc = facet; break;
17275 	    case XML_SCHEMA_FACET_MAXLENGTH:
17276 		bfmaxlen = facet; break;
17277 	    case XML_SCHEMA_FACET_MAXINCLUSIVE:
17278 		bfmaxinc = facet; break;
17279 	    case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17280 		bfmaxexc = facet; break;
17281 	    case XML_SCHEMA_FACET_TOTALDIGITS:
17282 		bftotdig = facet; break;
17283 	    case XML_SCHEMA_FACET_FRACTIONDIGITS:
17284 		bffracdig = facet; break;
17285 	    default:
17286 		break;
17287 	}
17288     }
17289     /*
17290     * length and minLength or maxLength (2.2) + (3.2)
17291     */
17292     if (flength && (fminlen || fmaxlen)) {
17293 	FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
17294 	    "either of 'minLength' or 'maxLength' to be specified on "
17295 	    "the same type definition")
17296     }
17297     /*
17298     * Mutual exclusions in the same derivation step.
17299     */
17300     if ((fmaxinc) && (fmaxexc)) {
17301 	/*
17302 	* SCC "maxInclusive and maxExclusive"
17303 	*/
17304 	FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
17305     }
17306     if ((fmininc) && (fminexc)) {
17307 	/*
17308 	* SCC "minInclusive and minExclusive"
17309 	*/
17310 	FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
17311     }
17312 
17313     if (flength && bflength) {
17314 	/*
17315 	* SCC "length valid restriction"
17316 	* The values have to be equal.
17317 	*/
17318 	res = xmlSchemaCompareValues(flength->val, bflength->val);
17319 	if (res == -2)
17320 	    goto internal_error;
17321 	if (res != 0)
17322 	    xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
17323 	if ((res != 0) && (bflength->fixed)) {
17324 	    FACET_RESTR_FIXED_ERR(flength)
17325 	}
17326 
17327     }
17328     if (fminlen && bfminlen) {
17329 	/*
17330 	* SCC "minLength valid restriction"
17331 	* minLength >= BASE minLength
17332 	*/
17333 	res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
17334 	if (res == -2)
17335 	    goto internal_error;
17336 	if (res == -1)
17337 	    xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
17338 	if ((res != 0) && (bfminlen->fixed)) {
17339 	    FACET_RESTR_FIXED_ERR(fminlen)
17340 	}
17341     }
17342     if (fmaxlen && bfmaxlen) {
17343 	/*
17344 	* SCC "maxLength valid restriction"
17345 	* maxLength <= BASE minLength
17346 	*/
17347 	res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
17348 	if (res == -2)
17349 	    goto internal_error;
17350 	if (res == 1)
17351 	    xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
17352 	if ((res != 0) && (bfmaxlen->fixed)) {
17353 	    FACET_RESTR_FIXED_ERR(fmaxlen)
17354 	}
17355     }
17356     /*
17357     * SCC "length and minLength or maxLength"
17358     */
17359     if (! flength)
17360 	flength = bflength;
17361     if (flength) {
17362 	if (! fminlen)
17363 	    fminlen = bfminlen;
17364 	if (fminlen) {
17365 	    /* (1.1) length >= minLength */
17366 	    res = xmlSchemaCompareValues(flength->val, fminlen->val);
17367 	    if (res == -2)
17368 		goto internal_error;
17369 	    if (res == -1)
17370 		xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
17371 	}
17372 	if (! fmaxlen)
17373 	    fmaxlen = bfmaxlen;
17374 	if (fmaxlen) {
17375 	    /* (2.1) length <= maxLength */
17376 	    res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
17377 	    if (res == -2)
17378 		goto internal_error;
17379 	    if (res == 1)
17380 		xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
17381 	}
17382     }
17383     if (fmaxinc) {
17384 	/*
17385 	* "maxInclusive"
17386 	*/
17387 	if (fmininc) {
17388 	    /* SCC "maxInclusive >= minInclusive" */
17389 	    res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
17390 	    if (res == -2)
17391 		goto internal_error;
17392 	    if (res == -1) {
17393 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
17394 	    }
17395 	}
17396 	/*
17397 	* SCC "maxInclusive valid restriction"
17398 	*/
17399 	if (bfmaxinc) {
17400 	    /* maxInclusive <= BASE maxInclusive */
17401 	    res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
17402 	    if (res == -2)
17403 		goto internal_error;
17404 	    if (res == 1)
17405 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
17406 	    if ((res != 0) && (bfmaxinc->fixed)) {
17407 		FACET_RESTR_FIXED_ERR(fmaxinc)
17408 	    }
17409 	}
17410 	if (bfmaxexc) {
17411 	    /* maxInclusive < BASE maxExclusive */
17412 	    res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
17413 	    if (res == -2)
17414 		goto internal_error;
17415 	    if (res != -1) {
17416 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
17417 	    }
17418 	}
17419 	if (bfmininc) {
17420 	    /* maxInclusive >= BASE minInclusive */
17421 	    res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
17422 	    if (res == -2)
17423 		goto internal_error;
17424 	    if (res == -1) {
17425 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
17426 	    }
17427 	}
17428 	if (bfminexc) {
17429 	    /* maxInclusive > BASE minExclusive */
17430 	    res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
17431 	    if (res == -2)
17432 		goto internal_error;
17433 	    if (res != 1) {
17434 		xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
17435 	    }
17436 	}
17437     }
17438     if (fmaxexc) {
17439 	/*
17440 	* "maxExclusive >= minExclusive"
17441 	*/
17442 	if (fminexc) {
17443 	    res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
17444 	    if (res == -2)
17445 		goto internal_error;
17446 	    if (res == -1) {
17447 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
17448 	    }
17449 	}
17450 	/*
17451 	* "maxExclusive valid restriction"
17452 	*/
17453 	if (bfmaxexc) {
17454 	    /* maxExclusive <= BASE maxExclusive */
17455 	    res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
17456 	    if (res == -2)
17457 		goto internal_error;
17458 	    if (res == 1) {
17459 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
17460 	    }
17461 	    if ((res != 0) && (bfmaxexc->fixed)) {
17462 		FACET_RESTR_FIXED_ERR(fmaxexc)
17463 	    }
17464 	}
17465 	if (bfmaxinc) {
17466 	    /* maxExclusive <= BASE maxInclusive */
17467 	    res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
17468 	    if (res == -2)
17469 		goto internal_error;
17470 	    if (res == 1) {
17471 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
17472 	    }
17473 	}
17474 	if (bfmininc) {
17475 	    /* maxExclusive > BASE minInclusive */
17476 	    res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
17477 	    if (res == -2)
17478 		goto internal_error;
17479 	    if (res != 1) {
17480 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
17481 	    }
17482 	}
17483 	if (bfminexc) {
17484 	    /* maxExclusive > BASE minExclusive */
17485 	    res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
17486 	    if (res == -2)
17487 		goto internal_error;
17488 	    if (res != 1) {
17489 		xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
17490 	    }
17491 	}
17492     }
17493     if (fminexc) {
17494 	/*
17495 	* "minExclusive < maxInclusive"
17496 	*/
17497 	if (fmaxinc) {
17498 	    res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
17499 	    if (res == -2)
17500 		goto internal_error;
17501 	    if (res != -1) {
17502 		xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
17503 	    }
17504 	}
17505 	/*
17506 	* "minExclusive valid restriction"
17507 	*/
17508 	if (bfminexc) {
17509 	    /* minExclusive >= BASE minExclusive */
17510 	    res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
17511 	    if (res == -2)
17512 		goto internal_error;
17513 	    if (res == -1) {
17514 		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
17515 	    }
17516 	    if ((res != 0) && (bfminexc->fixed)) {
17517 		FACET_RESTR_FIXED_ERR(fminexc)
17518 	    }
17519 	}
17520 	if (bfmaxinc) {
17521 	    /* minExclusive <= BASE maxInclusive */
17522 	    res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
17523 	    if (res == -2)
17524 		goto internal_error;
17525 	    if (res == 1) {
17526 		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
17527 	    }
17528 	}
17529 	if (bfmininc) {
17530 	    /* minExclusive >= BASE minInclusive */
17531 	    res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
17532 	    if (res == -2)
17533 		goto internal_error;
17534 	    if (res == -1) {
17535 		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
17536 	    }
17537 	}
17538 	if (bfmaxexc) {
17539 	    /* minExclusive < BASE maxExclusive */
17540 	    res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
17541 	    if (res == -2)
17542 		goto internal_error;
17543 	    if (res != -1) {
17544 		xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
17545 	    }
17546 	}
17547     }
17548     if (fmininc) {
17549 	/*
17550 	* "minInclusive < maxExclusive"
17551 	*/
17552 	if (fmaxexc) {
17553 	    res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
17554 	    if (res == -2)
17555 		goto internal_error;
17556 	    if (res != -1) {
17557 		xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
17558 	    }
17559 	}
17560 	/*
17561 	* "minExclusive valid restriction"
17562 	*/
17563 	if (bfmininc) {
17564 	    /* minInclusive >= BASE minInclusive */
17565 	    res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
17566 	    if (res == -2)
17567 		goto internal_error;
17568 	    if (res == -1) {
17569 		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
17570 	    }
17571 	    if ((res != 0) && (bfmininc->fixed)) {
17572 		FACET_RESTR_FIXED_ERR(fmininc)
17573 	    }
17574 	}
17575 	if (bfmaxinc) {
17576 	    /* minInclusive <= BASE maxInclusive */
17577 	    res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
17578 	    if (res == -2)
17579 		goto internal_error;
17580 	    if (res == 1) {
17581 		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
17582 	    }
17583 	}
17584 	if (bfminexc) {
17585 	    /* minInclusive > BASE minExclusive */
17586 	    res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
17587 	    if (res == -2)
17588 		goto internal_error;
17589 	    if (res != 1)
17590 		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
17591 	}
17592 	if (bfmaxexc) {
17593 	    /* minInclusive < BASE maxExclusive */
17594 	    res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
17595 	    if (res == -2)
17596 		goto internal_error;
17597 	    if (res != -1)
17598 		xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
17599 	}
17600     }
17601     if (ftotdig && bftotdig) {
17602 	/*
17603 	* SCC " totalDigits valid restriction"
17604 	* totalDigits <= BASE totalDigits
17605 	*/
17606 	res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
17607 	if (res == -2)
17608 	    goto internal_error;
17609 	if (res == 1)
17610 	    xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
17611 	    -1, 1, 1);
17612 	if ((res != 0) && (bftotdig->fixed)) {
17613 	    FACET_RESTR_FIXED_ERR(ftotdig)
17614 	}
17615     }
17616     if (ffracdig && bffracdig) {
17617 	/*
17618 	* SCC  "fractionDigits valid restriction"
17619 	* fractionDigits <= BASE fractionDigits
17620 	*/
17621 	res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
17622 	if (res == -2)
17623 	    goto internal_error;
17624 	if (res == 1)
17625 	    xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
17626 	    -1, 1, 1);
17627 	if ((res != 0) && (bffracdig->fixed)) {
17628 	    FACET_RESTR_FIXED_ERR(ffracdig)
17629 	}
17630     }
17631     /*
17632     * SCC "fractionDigits less than or equal to totalDigits"
17633     */
17634     if (! ftotdig)
17635 	ftotdig = bftotdig;
17636     if (! ffracdig)
17637 	ffracdig = bffracdig;
17638     if (ftotdig && ffracdig) {
17639 	res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
17640 	if (res == -2)
17641 	    goto internal_error;
17642 	if (res == 1)
17643 	    xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
17644 		-1, 1, 0);
17645     }
17646     /*
17647     * *Enumerations* won' be added here, since only the first set
17648     * of enumerations in the ancestor-or-self axis is used
17649     * for validation, plus we need to use the base type of those
17650     * enumerations for whitespace.
17651     *
17652     * *Patterns*: won't be add here, since they are ORed at
17653     * type level and ANDed at ancestor level. This will
17654     * happen during validation by walking the base axis
17655     * of the type.
17656     */
17657     for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17658 	bfacet = cur->facet;
17659 	/*
17660 	* Special handling of enumerations and patterns.
17661 	* TODO: hmm, they should not appear in the set, so remove this.
17662 	*/
17663 	if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
17664 	    (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
17665 	    continue;
17666 	/*
17667 	* Search for a duplicate facet in the current type.
17668 	*/
17669 	link = type->facetSet;
17670 	/* err = 0; */
17671 	/* fixedErr = 0; */
17672 	while (link != NULL) {
17673 	    facet = link->facet;
17674 	    if (facet->type == bfacet->type) {
17675 		switch (facet->type) {
17676 		    case XML_SCHEMA_FACET_WHITESPACE:
17677 			/*
17678 			* The whitespace must be stronger.
17679 			*/
17680 			if (facet->whitespace < bfacet->whitespace) {
17681 			    FACET_RESTR_ERR(facet,
17682 				"The 'whitespace' value has to be equal to "
17683 				"or stronger than the 'whitespace' value of "
17684 				"the base type")
17685 			}
17686 			if ((bfacet->fixed) &&
17687 			    (facet->whitespace != bfacet->whitespace)) {
17688 			    FACET_RESTR_FIXED_ERR(facet)
17689 			}
17690 			break;
17691 		    default:
17692 			break;
17693 		}
17694 		/* Duplicate found. */
17695 		break;
17696 	    }
17697 	    link = link->next;
17698 	}
17699 	/*
17700 	* If no duplicate was found: add the base types's facet
17701 	* to the set.
17702 	*/
17703 	if (link == NULL) {
17704 	    link = (xmlSchemaFacetLinkPtr)
17705 		xmlMalloc(sizeof(xmlSchemaFacetLink));
17706 	    if (link == NULL) {
17707 		xmlSchemaPErrMemory(pctxt);
17708 		return (-1);
17709 	    }
17710 	    link->facet = cur->facet;
17711 	    link->next = NULL;
17712 	    if (last == NULL)
17713 		type->facetSet = link;
17714 	    else
17715 		last->next = link;
17716 	    last = link;
17717 	}
17718 
17719     }
17720 
17721     return (0);
17722 internal_error:
17723     PERROR_INT("xmlSchemaDeriveAndValidateFacets",
17724 	"an error occurred");
17725     return (-1);
17726 }
17727 
17728 static int
xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)17729 xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
17730 					     xmlSchemaTypePtr type)
17731 {
17732     xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
17733     /*
17734     * The actual value is then formed by replacing any union type
17735     * definition in the `explicit members` with the members of their
17736     * {member type definitions}, in order.
17737     *
17738     * TODO: There's a bug entry at
17739     * "http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0287.html"
17740     * which indicates that we'll keep the union types the future.
17741     */
17742     link = type->memberTypes;
17743     while (link != NULL) {
17744 
17745 	if (WXS_IS_TYPE_NOT_FIXED(link->type))
17746 	    xmlSchemaTypeFixup(link->type, ACTXT_CAST pctxt);
17747 
17748 	if (WXS_IS_UNION(link->type)) {
17749 	    subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
17750 	    if (subLink != NULL) {
17751 		link->type = subLink->type;
17752 		if (subLink->next != NULL) {
17753 		    lastLink = link->next;
17754 		    subLink = subLink->next;
17755 		    prevLink = link;
17756 		    while (subLink != NULL) {
17757 			newLink = (xmlSchemaTypeLinkPtr)
17758 			    xmlMalloc(sizeof(xmlSchemaTypeLink));
17759 			if (newLink == NULL) {
17760 			    xmlSchemaPErrMemory(pctxt);
17761 			    return (-1);
17762 			}
17763 			newLink->type = subLink->type;
17764 			prevLink->next = newLink;
17765 			prevLink = newLink;
17766 			newLink->next = lastLink;
17767 
17768 			subLink = subLink->next;
17769 		    }
17770 		}
17771 	    }
17772 	}
17773 	link = link->next;
17774     }
17775     return (0);
17776 }
17777 
17778 static void
xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)17779 xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
17780 {
17781     int has = 0, needVal = 0, normVal = 0;
17782 
17783     has	= (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
17784     if (has) {
17785 	needVal = (type->baseType->flags &
17786 	    XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
17787 	normVal = (type->baseType->flags &
17788 	    XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
17789     }
17790     if (type->facets != NULL) {
17791 	xmlSchemaFacetPtr fac;
17792 
17793 	for (fac = type->facets; fac != NULL; fac = fac->next) {
17794 	    switch (fac->type) {
17795 		case XML_SCHEMA_FACET_WHITESPACE:
17796 		    break;
17797 		case XML_SCHEMA_FACET_PATTERN:
17798 		    normVal = 1;
17799 		    has = 1;
17800 		    break;
17801 		case XML_SCHEMA_FACET_ENUMERATION:
17802 		    needVal = 1;
17803 		    normVal = 1;
17804 		    has = 1;
17805 		    break;
17806 		default:
17807 		    has = 1;
17808 		    break;
17809 	    }
17810 	}
17811     }
17812     if (normVal)
17813 	type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
17814     if (needVal)
17815 	type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17816     if (has)
17817 	type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
17818 
17819     if (has && (! needVal) && WXS_IS_ATOMIC(type)) {
17820 	xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
17821 	/*
17822 	* OPTIMIZE VAL TODO: Some facets need a computed value.
17823 	*/
17824 	if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
17825 	    (prim->builtInType != XML_SCHEMAS_STRING)) {
17826 	    type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17827 	}
17828     }
17829 }
17830 
17831 static int
xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)17832 xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
17833 {
17834 
17835 
17836     /*
17837     * Evaluate the whitespace-facet value.
17838     */
17839     if (WXS_IS_LIST(type)) {
17840 	type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17841 	return (0);
17842     } else if (WXS_IS_UNION(type))
17843 	return (0);
17844 
17845     if (type->facetSet != NULL) {
17846 	xmlSchemaFacetLinkPtr lin;
17847 
17848 	for (lin = type->facetSet; lin != NULL; lin = lin->next) {
17849 	    if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
17850 		switch (lin->facet->whitespace) {
17851 		case XML_SCHEMAS_FACET_PRESERVE:
17852 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17853 		    break;
17854 		case XML_SCHEMAS_FACET_REPLACE:
17855 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17856 		    break;
17857 		case XML_SCHEMAS_FACET_COLLAPSE:
17858 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17859 		    break;
17860 		default:
17861 		    return (-1);
17862 		}
17863 		return (0);
17864 	    }
17865 	}
17866     }
17867     /*
17868     * For all `atomic` datatypes other than string (and types `derived`
17869     * by `restriction` from it) the value of whiteSpace is fixed to
17870     * collapse
17871     */
17872     {
17873 	xmlSchemaTypePtr anc;
17874 
17875 	for (anc = type->baseType; anc != NULL &&
17876 		anc->builtInType != XML_SCHEMAS_ANYTYPE;
17877 		anc = anc->baseType) {
17878 
17879 	    if (anc->type == XML_SCHEMA_TYPE_BASIC) {
17880 		if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
17881 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17882 
17883 		} else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
17884 		    (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
17885 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17886 
17887 		} else
17888 		    type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17889 		break;
17890 	    }
17891 	}
17892     }
17893     return (0);
17894 }
17895 
17896 static int
xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)17897 xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,
17898 			  xmlSchemaTypePtr type)
17899 {
17900     if (type->type != XML_SCHEMA_TYPE_SIMPLE)
17901 	return(0);
17902     if (! WXS_IS_TYPE_NOT_FIXED_1(type))
17903 	return(0);
17904     type->flags |= XML_SCHEMAS_TYPE_FIXUP_1;
17905 
17906     if (WXS_IS_LIST(type)) {
17907 	/*
17908 	* Corresponds to <simpleType><list>...
17909 	*/
17910 	if (type->subtypes == NULL) {
17911 	    /*
17912 	    * This one is really needed, so get out.
17913 	    */
17914 	    PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17915 		"list type has no item-type assigned");
17916 	    return(-1);
17917 	}
17918     } else if (WXS_IS_UNION(type)) {
17919 	/*
17920 	* Corresponds to <simpleType><union>...
17921 	*/
17922 	if (type->memberTypes == NULL) {
17923 	    /*
17924 	    * This one is really needed, so get out.
17925 	    */
17926 	    PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17927 		"union type has no member-types assigned");
17928 	    return(-1);
17929 	}
17930     } else {
17931 	/*
17932 	* Corresponds to <simpleType><restriction>...
17933 	*/
17934 	if (type->baseType == NULL) {
17935 	    PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17936 		"type has no base-type assigned");
17937 	    return(-1);
17938 	}
17939 	if (WXS_IS_TYPE_NOT_FIXED_1(type->baseType))
17940 	    if (xmlSchemaFixupSimpleTypeStageOne(pctxt, type->baseType) == -1)
17941 		return(-1);
17942 	/*
17943 	* Variety
17944 	* If the <restriction> alternative is chosen, then the
17945 	* {variety} of the {base type definition}.
17946 	*/
17947 	if (WXS_IS_ATOMIC(type->baseType))
17948 	    type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
17949 	else if (WXS_IS_LIST(type->baseType)) {
17950 	    type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
17951 	    /*
17952 	    * Inherit the itemType.
17953 	    */
17954 	    type->subtypes = type->baseType->subtypes;
17955 	} else if (WXS_IS_UNION(type->baseType)) {
17956 	    type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
17957 	    /*
17958 	    * NOTE that we won't assign the memberTypes of the base,
17959 	    * since this will make trouble when freeing them; we will
17960 	    * use a lookup function to access them instead.
17961 	    */
17962 	}
17963     }
17964     return(0);
17965 }
17966 
17967 /*
17968 * 3.14.6 Constraints on Simple Type Definition Schema Components
17969 */
17970 static int
xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)17971 xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,
17972 				 xmlSchemaTypePtr type)
17973 {
17974     int res, olderrs = pctxt->nberrors;
17975 
17976     if (type->type != XML_SCHEMA_TYPE_SIMPLE)
17977 	return(-1);
17978 
17979     if (! WXS_IS_TYPE_NOT_FIXED(type))
17980 	return(0);
17981 
17982     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
17983     type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
17984 
17985     if (type->baseType == NULL) {
17986 	PERROR_INT("xmlSchemaFixupSimpleTypeStageTwo",
17987 	    "missing baseType");
17988 	goto exit_failure;
17989     }
17990     if (WXS_IS_TYPE_NOT_FIXED(type->baseType))
17991 	xmlSchemaTypeFixup(type->baseType, ACTXT_CAST pctxt);
17992     /*
17993     * If a member type of a union is a union itself, we need to substitute
17994     * that member type for its member types.
17995     * NOTE that this might change in WXS 1.1; i.e. we will keep the union
17996     * types in WXS 1.1.
17997     */
17998     if ((type->memberTypes != NULL) &&
17999 	(xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1))
18000 	return(-1);
18001     /*
18002     * SPEC src-simple-type 1
18003     * "The corresponding simple type definition, if any, must satisfy
18004     * the conditions set out in Constraints on Simple Type Definition
18005     * Schema Components ($3.14.6)."
18006     */
18007     /*
18008     * Schema Component Constraint: Simple Type Definition Properties Correct
18009     * (st-props-correct)
18010     */
18011     res = xmlSchemaCheckSTPropsCorrect(pctxt, type);
18012     HFAILURE HERROR
18013     /*
18014     * Schema Component Constraint: Derivation Valid (Restriction, Simple)
18015     * (cos-st-restricts)
18016     */
18017     res = xmlSchemaCheckCOSSTRestricts(pctxt, type);
18018     HFAILURE HERROR
18019     /*
18020     * TODO: Removed the error report, since it got annoying to get an
18021     * extra error report, if anything failed until now.
18022     * Enable this if needed.
18023     *
18024     * xmlSchemaPErr(ctxt, type->node,
18025     *    XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
18026     *    "Simple type '%s' does not satisfy the constraints "
18027     *    "on simple type definitions.\n",
18028     *    type->name, NULL);
18029     */
18030     /*
18031     * Schema Component Constraint: Simple Type Restriction (Facets)
18032     * (st-restrict-facets)
18033     */
18034     res = xmlSchemaCheckFacetValues(type, pctxt);
18035     HFAILURE HERROR
18036     if ((type->facetSet != NULL) ||
18037 	(type->baseType->facetSet != NULL)) {
18038 	res = xmlSchemaDeriveAndValidateFacets(pctxt, type);
18039 	HFAILURE HERROR
18040     }
18041     /*
18042     * Whitespace value.
18043     */
18044     res = xmlSchemaTypeFixupWhitespace(type);
18045     HFAILURE HERROR
18046     xmlSchemaTypeFixupOptimFacets(type);
18047 
18048 exit_error:
18049     if (olderrs != pctxt->nberrors)
18050 	return(pctxt->err);
18051     return(0);
18052 
18053 exit_failure:
18054     return(-1);
18055 }
18056 
18057 static int
xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,xmlSchemaTypePtr type)18058 xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,
18059 			  xmlSchemaTypePtr type)
18060 {
18061     int res = 0, olderrs = pctxt->nberrors;
18062     xmlSchemaTypePtr baseType = type->baseType;
18063 
18064     if (! WXS_IS_TYPE_NOT_FIXED(type))
18065 	return(0);
18066     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18067     if (baseType == NULL) {
18068 	PERROR_INT("xmlSchemaFixupComplexType",
18069 	    "missing baseType");
18070 	goto exit_failure;
18071     }
18072     /*
18073     * Fixup the base type.
18074     */
18075     if (WXS_IS_TYPE_NOT_FIXED(baseType))
18076 	xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt);
18077     if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
18078 	/*
18079 	* Skip fixup if the base type is invalid.
18080 	* TODO: Generate a warning!
18081 	*/
18082 	return(0);
18083     }
18084     /*
18085     * This basically checks if the base type can be derived.
18086     */
18087     res = xmlSchemaCheckSRCCT(pctxt, type);
18088     HFAILURE HERROR
18089     /*
18090     * Fixup the content type.
18091     */
18092     if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
18093 	/*
18094 	* Corresponds to <complexType><simpleContent>...
18095 	*/
18096 	if ((WXS_IS_COMPLEX(baseType)) &&
18097 	    (baseType->contentTypeDef != NULL) &&
18098 	    (WXS_IS_RESTRICTION(type))) {
18099 	    xmlSchemaTypePtr contentBase, content;
18100 #ifdef ENABLE_NAMED_LOCALS
18101 	    char buf[30];
18102 	    const xmlChar *tmpname;
18103 #endif
18104 	    /*
18105 	    * SPEC (1) If <restriction> + base type is <complexType>,
18106 	    * "whose own {content type} is a simple type..."
18107 	    */
18108 	    if (type->contentTypeDef != NULL) {
18109 		/*
18110 		* SPEC (1.1) "the simple type definition corresponding to the
18111 		* <simpleType> among the [children] of <restriction> if there
18112 		* is one;"
18113 		* Note that this "<simpleType> among the [children]" was put
18114 		* into ->contentTypeDef during parsing.
18115 		*/
18116 		contentBase = type->contentTypeDef;
18117 		type->contentTypeDef = NULL;
18118 	    } else {
18119 		/*
18120 		* (1.2) "...otherwise (<restriction> has no <simpleType>
18121 		* among its [children]), the simple type definition which
18122 		* is the {content type} of the ... base type."
18123 		*/
18124 		contentBase = baseType->contentTypeDef;
18125 	    }
18126 	    /*
18127 	    * SPEC
18128 	    * "... a simple type definition which restricts the simple
18129 	    * type definition identified in clause 1.1 or clause 1.2
18130 	    * with a set of facet components"
18131 	    *
18132 	    * Create the anonymous simple type, which will be the content
18133 	    * type of the complex type.
18134 	    */
18135 #ifdef ENABLE_NAMED_LOCALS
18136 	    snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
18137 	    tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
18138 	    content = xmlSchemaAddType(pctxt, pctxt->schema,
18139 		XML_SCHEMA_TYPE_SIMPLE, tmpname, type->targetNamespace,
18140 		type->node, 0);
18141 #else
18142 	    content = xmlSchemaAddType(pctxt, pctxt->schema,
18143 		XML_SCHEMA_TYPE_SIMPLE, NULL, type->targetNamespace,
18144 		type->node, 0);
18145 #endif
18146 	    if (content == NULL)
18147 		goto exit_failure;
18148 	    /*
18149 	    * We will use the same node as for the <complexType>
18150 	    * to have it somehow anchored in the schema doc.
18151 	    */
18152 	    content->type = XML_SCHEMA_TYPE_SIMPLE;
18153 	    content->baseType = contentBase;
18154 	    /*
18155 	    * Move the facets, previously anchored on the
18156 	    * complexType during parsing.
18157 	    */
18158 	    content->facets = type->facets;
18159 	    type->facets = NULL;
18160 	    content->facetSet = type->facetSet;
18161 	    type->facetSet = NULL;
18162 
18163 	    type->contentTypeDef = content;
18164 	    if (WXS_IS_TYPE_NOT_FIXED(contentBase))
18165 		xmlSchemaTypeFixup(contentBase, ACTXT_CAST pctxt);
18166 	    /*
18167 	    * Fixup the newly created type. We don't need to check
18168 	    * for circularity here.
18169 	    */
18170 	    res = xmlSchemaFixupSimpleTypeStageOne(pctxt, content);
18171 	    HFAILURE HERROR
18172 	    res = xmlSchemaFixupSimpleTypeStageTwo(pctxt, content);
18173 	    HFAILURE HERROR
18174 
18175 	} else if ((WXS_IS_COMPLEX(baseType)) &&
18176 	    (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
18177 	    (WXS_IS_RESTRICTION(type))) {
18178 	    /*
18179 	    * SPEC (2) If <restriction> + base is a mixed <complexType> with
18180 	    * an emptiable particle, then a simple type definition which
18181 	    * restricts the <restriction>'s <simpleType> child.
18182 	    */
18183 	    if ((type->contentTypeDef == NULL) ||
18184 		(type->contentTypeDef->baseType == NULL)) {
18185 		/*
18186 		* TODO: Check if this ever happens.
18187 		*/
18188 		xmlSchemaPCustomErr(pctxt,
18189 		    XML_SCHEMAP_INTERNAL,
18190 		    WXS_BASIC_CAST type, NULL,
18191 		    "Internal error: xmlSchemaTypeFixup, "
18192 		    "complex type '%s': the <simpleContent><restriction> "
18193 		    "is missing a <simpleType> child, but was not caught "
18194 		    "by xmlSchemaCheckSRCCT()", type->name);
18195 		goto exit_failure;
18196 	    }
18197 	} else if ((WXS_IS_COMPLEX(baseType)) && WXS_IS_EXTENSION(type)) {
18198 	    /*
18199 	    * SPEC (3) If <extension> + base is <complexType> with
18200 	    * <simpleType> content, "...then the {content type} of that
18201 	    * complex type definition"
18202 	    */
18203 	    if (baseType->contentTypeDef == NULL) {
18204 		/*
18205 		* TODO: Check if this ever happens. xmlSchemaCheckSRCCT
18206 		* should have caught this already.
18207 		*/
18208 		xmlSchemaPCustomErr(pctxt,
18209 		    XML_SCHEMAP_INTERNAL,
18210 		    WXS_BASIC_CAST type, NULL,
18211 		    "Internal error: xmlSchemaTypeFixup, "
18212 		    "complex type '%s': the <extension>ed base type is "
18213 		    "a complex type with no simple content type",
18214 		    type->name);
18215 		goto exit_failure;
18216 	    }
18217 	    type->contentTypeDef = baseType->contentTypeDef;
18218 	} else if ((WXS_IS_SIMPLE(baseType)) && WXS_IS_EXTENSION(type)) {
18219 	    /*
18220 	    * SPEC (4) <extension> + base is <simpleType>
18221 	    * "... then that simple type definition"
18222 	    */
18223 	    type->contentTypeDef = baseType;
18224 	} else {
18225 	    /*
18226 	    * TODO: Check if this ever happens.
18227 	    */
18228 	    xmlSchemaPCustomErr(pctxt,
18229 		XML_SCHEMAP_INTERNAL,
18230 		WXS_BASIC_CAST type, NULL,
18231 		"Internal error: xmlSchemaTypeFixup, "
18232 		"complex type '%s' with <simpleContent>: unhandled "
18233 		"derivation case", type->name);
18234 	    goto exit_failure;
18235 	}
18236     } else {
18237 	int dummySequence = 0;
18238 	xmlSchemaParticlePtr particle =
18239 	    (xmlSchemaParticlePtr) type->subtypes;
18240 	/*
18241 	* Corresponds to <complexType><complexContent>...
18242 	*
18243 	* NOTE that the effective mixed was already set during parsing of
18244 	* <complexType> and <complexContent>; its flag value is
18245 	* XML_SCHEMAS_TYPE_MIXED.
18246 	*
18247 	* Compute the "effective content":
18248 	* (2.1.1) + (2.1.2) + (2.1.3)
18249 	*/
18250 	if ((particle == NULL) ||
18251 	    ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
18252 	    ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
18253 	    (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
18254 	    ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
18255 	    (particle->minOccurs == 0))) &&
18256 	    ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
18257 	    if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
18258 		/*
18259 		* SPEC (2.1.4) "If the `effective mixed` is true, then
18260 		* a particle whose properties are as follows:..."
18261 		*
18262 		* Empty sequence model group with
18263 		* minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
18264 		* NOTE that we sill assign it the <complexType> node to
18265 		* somehow anchor it in the doc.
18266 		*/
18267 		if ((particle == NULL) ||
18268 		    (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
18269 		    /*
18270 		    * Create the particle.
18271 		    */
18272 		    particle = xmlSchemaAddParticle(pctxt,
18273 			type->node, 1, 1);
18274 		    if (particle == NULL)
18275 			goto exit_failure;
18276 		    /*
18277 		    * Create the model group.
18278 		    */ /* URGENT TODO: avoid adding to pending items. */
18279 		    particle->children = (xmlSchemaTreeItemPtr)
18280 			xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18281 			XML_SCHEMA_TYPE_SEQUENCE, type->node);
18282 		    if (particle->children == NULL)
18283 			goto exit_failure;
18284 
18285 		    type->subtypes = (xmlSchemaTypePtr) particle;
18286 		}
18287 		dummySequence = 1;
18288 		type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18289 	    } else {
18290 		/*
18291 		* SPEC (2.1.5) "otherwise empty"
18292 		*/
18293 		type->contentType = XML_SCHEMA_CONTENT_EMPTY;
18294 	    }
18295 	} else {
18296 	    /*
18297 	    * SPEC (2.2) "otherwise the particle corresponding to the
18298 	    * <all>, <choice>, <group> or <sequence> among the
18299 	    * [children]."
18300 	    */
18301 	    type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18302 	}
18303 	/*
18304 	* Compute the "content type".
18305 	*/
18306 	if (WXS_IS_RESTRICTION(type)) {
18307 	    /*
18308 	    * SPEC (3.1) "If <restriction>..."
18309 	    * (3.1.1) + (3.1.2) */
18310 	    if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
18311 		if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18312 		    type->contentType = XML_SCHEMA_CONTENT_MIXED;
18313 	    }
18314 	} else {
18315 	    /*
18316 	    * SPEC (3.2) "If <extension>..."
18317 	    */
18318 	    if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18319 		/*
18320 		* SPEC (3.2.1)
18321 		* "If the `effective content` is empty, then the
18322 		*  {content type} of the [...] base ..."
18323 		*/
18324 		type->contentType = baseType->contentType;
18325 		type->subtypes = baseType->subtypes;
18326 		/*
18327 		* Fixes bug #347316:
18328 		* This is the case when the base type has a simple
18329 		* type definition as content.
18330 		*/
18331 		type->contentTypeDef = baseType->contentTypeDef;
18332 		/*
18333 		* NOTE that the effective mixed is ignored here.
18334 		*/
18335 	    } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18336 		/*
18337 		* SPEC (3.2.2)
18338 		*/
18339 		if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18340 		    type->contentType = XML_SCHEMA_CONTENT_MIXED;
18341 	    } else {
18342 		/*
18343 		* SPEC (3.2.3)
18344 		*/
18345 		if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18346 		    type->contentType = XML_SCHEMA_CONTENT_MIXED;
18347 		    /*
18348 		    * "A model group whose {compositor} is sequence and whose
18349 		    * {particles} are..."
18350 		    */
18351 		if ((WXS_TYPE_PARTICLE(type) != NULL) &&
18352 		    (WXS_TYPE_PARTICLE_TERM(type) != NULL) &&
18353 		    ((WXS_TYPE_PARTICLE_TERM(type))->type ==
18354 			XML_SCHEMA_TYPE_ALL))
18355 		{
18356 		    /*
18357 		    * SPEC cos-all-limited (1)
18358 		    */
18359 		    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18360 			/* TODO: error code */
18361 			XML_SCHEMAP_COS_ALL_LIMITED,
18362 			WXS_ITEM_NODE(type), NULL,
18363 			"The type has an 'all' model group in its "
18364 			"{content type} and thus cannot be derived from "
18365 			"a non-empty type, since this would produce a "
18366 			"'sequence' model group containing the 'all' "
18367 			"model group; 'all' model groups are not "
18368 			"allowed to appear inside other model groups",
18369 			NULL, NULL);
18370 
18371 		} else if ((WXS_TYPE_PARTICLE(baseType) != NULL) &&
18372 		    (WXS_TYPE_PARTICLE_TERM(baseType) != NULL) &&
18373 		    ((WXS_TYPE_PARTICLE_TERM(baseType))->type ==
18374 			XML_SCHEMA_TYPE_ALL))
18375 		{
18376 		    /*
18377 		    * SPEC cos-all-limited (1)
18378 		    */
18379 		    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18380 			/* TODO: error code */
18381 			XML_SCHEMAP_COS_ALL_LIMITED,
18382 			WXS_ITEM_NODE(type), NULL,
18383 			"A type cannot be derived by extension from a type "
18384 			"which has an 'all' model group in its "
18385 			"{content type}, since this would produce a "
18386 			"'sequence' model group containing the 'all' "
18387 			"model group; 'all' model groups are not "
18388 			"allowed to appear inside other model groups",
18389 			NULL, NULL);
18390 
18391 		} else if ((!dummySequence) && (baseType->subtypes != NULL)) {
18392 		    xmlSchemaTreeItemPtr effectiveContent =
18393 			(xmlSchemaTreeItemPtr) type->subtypes;
18394 		    /*
18395 		    * Create the particle.
18396 		    */
18397 		    particle = xmlSchemaAddParticle(pctxt,
18398 			type->node, 1, 1);
18399 		    if (particle == NULL)
18400 			goto exit_failure;
18401 		    /*
18402 		    * Create the "sequence" model group.
18403 		    */
18404 		    particle->children = (xmlSchemaTreeItemPtr)
18405 			xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18406 			XML_SCHEMA_TYPE_SEQUENCE, type->node);
18407 		    if (particle->children == NULL)
18408 			goto exit_failure;
18409 		    WXS_TYPE_CONTENTTYPE(type) = (xmlSchemaTypePtr) particle;
18410 		    /*
18411 		    * SPEC "the particle of the {content type} of
18412 		    * the ... base ..."
18413 		    * Create a duplicate of the base type's particle
18414 		    * and assign its "term" to it.
18415 		    */
18416 		    particle->children->children =
18417 			(xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
18418 			type->node,
18419 			((xmlSchemaParticlePtr) baseType->subtypes)->minOccurs,
18420 			((xmlSchemaParticlePtr) baseType->subtypes)->maxOccurs);
18421 		    if (particle->children->children == NULL)
18422 			goto exit_failure;
18423 		    particle = (xmlSchemaParticlePtr)
18424 			particle->children->children;
18425 		    particle->children =
18426 			((xmlSchemaParticlePtr) baseType->subtypes)->children;
18427 		    /*
18428 		    * SPEC "followed by the `effective content`."
18429 		    */
18430 		    particle->next = effectiveContent;
18431 		    /*
18432 		    * This all will result in:
18433 		    * new-particle
18434 		    *   --> new-sequence(
18435 		    *         new-particle
18436 		    *           --> base-model,
18437 		    *         this-particle
18438 		    *	        --> this-model
18439 		    *	    )
18440 		    */
18441 		} else {
18442 		    /*
18443 		    * This is the case when there is already an empty
18444 		    * <sequence> with minOccurs==maxOccurs==1.
18445 		    * Just add the base types's content type.
18446 		    * NOTE that, although we miss to add an intermediate
18447 		    * <sequence>, this should produce no difference to
18448 		    * neither the regex compilation of the content model,
18449 		    * nor to the complex type constraints.
18450 		    */
18451 		    particle->children->children =
18452 			(xmlSchemaTreeItemPtr) baseType->subtypes;
18453 		}
18454 	    }
18455 	}
18456     }
18457     /*
18458     * Now fixup attribute uses:
18459     *   - expand attr. group references
18460     *     - intersect attribute wildcards
18461     *   - inherit attribute uses of the base type
18462     *   - inherit or union attr. wildcards if extending
18463     *   - apply attr. use prohibitions if restricting
18464     */
18465     res = xmlSchemaFixupTypeAttributeUses(pctxt, type);
18466     HFAILURE HERROR
18467     /*
18468     * Apply the complex type component constraints; this will not
18469     * check attributes, since this is done in
18470     * xmlSchemaFixupTypeAttributeUses().
18471     */
18472     res = xmlSchemaCheckCTComponent(pctxt, type);
18473     HFAILURE HERROR
18474 
18475     if (olderrs != pctxt->nberrors)
18476 	return(pctxt->err);
18477     else
18478 	return(0);
18479 
18480 exit_error:
18481     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18482     return(pctxt->err);
18483 
18484 exit_failure:
18485     type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18486     return(-1);
18487 }
18488 
18489 
18490 /**
18491  * xmlSchemaTypeFixup:
18492  * @typeDecl:  the schema type definition
18493  * @ctxt:  the schema parser context
18494  *
18495  * Fixes the content model of the type.
18496  * URGENT TODO: We need an int result!
18497  */
18498 static int
xmlSchemaTypeFixup(xmlSchemaTypePtr type,xmlSchemaAbstractCtxtPtr actxt)18499 xmlSchemaTypeFixup(xmlSchemaTypePtr type,
18500                    xmlSchemaAbstractCtxtPtr actxt)
18501 {
18502     if (type == NULL)
18503         return(0);
18504     if (actxt->type != XML_SCHEMA_CTXT_PARSER) {
18505 	AERROR_INT("xmlSchemaTypeFixup",
18506 	    "this function needs a parser context");
18507 	return(-1);
18508     }
18509     if (! WXS_IS_TYPE_NOT_FIXED(type))
18510 	return(0);
18511     if (type->type == XML_SCHEMA_TYPE_COMPLEX)
18512 	return(xmlSchemaFixupComplexType(PCTXT_CAST actxt, type));
18513     else if (type->type == XML_SCHEMA_TYPE_SIMPLE)
18514 	return(xmlSchemaFixupSimpleTypeStageTwo(PCTXT_CAST actxt, type));
18515     return(0);
18516 }
18517 
18518 /**
18519  * xmlSchemaCheckFacet:
18520  * @facet:  the facet
18521  * @typeDecl:  the schema type definition
18522  * @pctxt:  the schema parser context or NULL
18523  * @name: the optional name of the type
18524  *
18525  * Checks and computes the values of facets.
18526  *
18527  * Returns 0 if valid, a positive error code if not valid and
18528  *         -1 in case of an internal or API error.
18529  */
18530 int
xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,xmlSchemaTypePtr typeDecl,xmlSchemaParserCtxtPtr pctxt,const xmlChar * name ATTRIBUTE_UNUSED)18531 xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
18532                     xmlSchemaTypePtr typeDecl,
18533                     xmlSchemaParserCtxtPtr pctxt,
18534 		    const xmlChar * name ATTRIBUTE_UNUSED)
18535 {
18536     int ret = 0, ctxtGiven;
18537 
18538     if ((facet == NULL) || (typeDecl == NULL))
18539         return(-1);
18540     /*
18541     * TODO: will the parser context be given if used from
18542     * the relaxNG module?
18543     */
18544     if (pctxt == NULL)
18545 	ctxtGiven = 0;
18546     else
18547 	ctxtGiven = 1;
18548 
18549     switch (facet->type) {
18550         case XML_SCHEMA_FACET_MININCLUSIVE:
18551         case XML_SCHEMA_FACET_MINEXCLUSIVE:
18552         case XML_SCHEMA_FACET_MAXINCLUSIVE:
18553         case XML_SCHEMA_FACET_MAXEXCLUSIVE:
18554 	case XML_SCHEMA_FACET_ENUMERATION: {
18555                 /*
18556                  * Okay we need to validate the value
18557                  * at that point.
18558                  */
18559 		xmlSchemaTypePtr base;
18560 
18561 		/* 4.3.5.5 Constraints on enumeration Schema Components
18562 		* Schema Component Constraint: enumeration valid restriction
18563 		* It is an `error` if any member of {value} is not in the
18564 		* `value space` of {base type definition}.
18565 		*
18566 		* minInclusive, maxInclusive, minExclusive, maxExclusive:
18567 		* The value `must` be in the
18568 		* `value space` of the `base type`.
18569 		*/
18570 		/*
18571 		* This function is intended to deliver a compiled value
18572 		* on the facet. In this implementation of XML Schemata the
18573 		* type holding a facet, won't be a built-in type.
18574 		* Thus to ensure that other API
18575 		* calls (relaxng) do work, if the given type is a built-in
18576 		* type, we will assume that the given built-in type *is
18577 		* already* the base type.
18578 		*/
18579 		if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
18580 		    base = typeDecl->baseType;
18581 		    if (base == NULL) {
18582 			PERROR_INT("xmlSchemaCheckFacet",
18583 			    "a type user derived type has no base type");
18584 			return (-1);
18585 		    }
18586 		} else
18587 		    base = typeDecl;
18588 
18589 		if (! ctxtGiven) {
18590 		    /*
18591 		    * A context is needed if called from RelaxNG.
18592 		    */
18593 		    pctxt = xmlSchemaNewParserCtxt("*");
18594 		    if (pctxt == NULL)
18595 			return (-1);
18596 		}
18597 		/*
18598 		* NOTE: This call does not check the content nodes,
18599 		* since they are not available:
18600 		* facet->node is just the node holding the facet
18601 		* definition, *not* the attribute holding the *value*
18602 		* of the facet.
18603 		*/
18604 		ret = xmlSchemaVCheckCVCSimpleType(
18605 		    ACTXT_CAST pctxt, facet->node, base,
18606 		    facet->value, &(facet->val), 1, 1, 0);
18607                 if (ret != 0) {
18608 		    if (ret < 0) {
18609 			/* No error message for RelaxNG. */
18610 			if (ctxtGiven) {
18611 			    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18612 				XML_SCHEMAP_INTERNAL, facet->node, NULL,
18613 				"Internal error: xmlSchemaCheckFacet, "
18614 				"failed to validate the value '%s' of the "
18615 				"facet '%s' against the base type",
18616 				facet->value, xmlSchemaFacetTypeToString(facet->type));
18617 			}
18618 			goto internal_error;
18619 		    }
18620 		    ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18621 		    /* No error message for RelaxNG. */
18622 		    if (ctxtGiven) {
18623 			xmlChar *str = NULL;
18624 
18625 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
18626 			    ret, facet->node, WXS_BASIC_CAST facet,
18627 			    "The value '%s' of the facet does not validate "
18628 			    "against the base type '%s'",
18629 			    facet->value,
18630 			    xmlSchemaFormatQName(&str,
18631 				base->targetNamespace, base->name));
18632 			FREE_AND_NULL(str);
18633 		    }
18634 		    goto exit;
18635                 } else if (facet->val == NULL) {
18636 		    if (ctxtGiven) {
18637 			PERROR_INT("xmlSchemaCheckFacet",
18638 			    "value was not computed");
18639 		    }
18640 		    /* TODO */
18641 		}
18642                 break;
18643             }
18644         case XML_SCHEMA_FACET_PATTERN:
18645             facet->regexp = xmlRegexpCompile(facet->value);
18646             if (facet->regexp == NULL) {
18647 		ret = XML_SCHEMAP_REGEXP_INVALID;
18648 		/* No error message for RelaxNG. */
18649 		if (ctxtGiven) {
18650 		    xmlSchemaCustomErr(ACTXT_CAST pctxt,
18651 			ret, facet->node, WXS_BASIC_CAST typeDecl,
18652 			"The value '%s' of the facet 'pattern' is not a "
18653 			"valid regular expression",
18654 			facet->value, NULL);
18655 		}
18656             }
18657             break;
18658         case XML_SCHEMA_FACET_TOTALDIGITS:
18659         case XML_SCHEMA_FACET_FRACTIONDIGITS:
18660         case XML_SCHEMA_FACET_LENGTH:
18661         case XML_SCHEMA_FACET_MAXLENGTH:
18662         case XML_SCHEMA_FACET_MINLENGTH:
18663 
18664 	    if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
18665 		ret = xmlSchemaValidatePredefinedType(
18666 		    xmlSchemaGetBuiltInType(XML_SCHEMAS_PINTEGER),
18667 		    facet->value, &(facet->val));
18668 	    } else {
18669 		ret = xmlSchemaValidatePredefinedType(
18670 		    xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
18671 		    facet->value, &(facet->val));
18672 	    }
18673 	    if (ret != 0) {
18674 		if (ret < 0) {
18675 		    /* No error message for RelaxNG. */
18676 		    if (ctxtGiven) {
18677 			PERROR_INT("xmlSchemaCheckFacet",
18678 			    "validating facet value");
18679 		    }
18680 		    goto internal_error;
18681 		}
18682 		ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18683 		/* No error message for RelaxNG. */
18684 		if (ctxtGiven) {
18685 		    /* error code */
18686 		    xmlSchemaCustomErr4(ACTXT_CAST pctxt,
18687 			ret, facet->node, WXS_BASIC_CAST typeDecl,
18688 			"The value '%s' of the facet '%s' is not a valid '%s'",
18689 			facet->value,
18690 			xmlSchemaFacetTypeToString(facet->type),
18691 			(facet->type != XML_SCHEMA_FACET_TOTALDIGITS) ?
18692 			    BAD_CAST "nonNegativeInteger" :
18693 			    BAD_CAST "positiveInteger",
18694 			NULL);
18695 		}
18696 	    }
18697 	    break;
18698 
18699         case XML_SCHEMA_FACET_WHITESPACE:{
18700                 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
18701                     facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
18702                 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
18703                     facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
18704                 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
18705                     facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
18706                 } else {
18707 		    ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18708                     /* No error message for RelaxNG. */
18709 		    if (ctxtGiven) {
18710 			/* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
18711 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
18712 			    ret, facet->node, WXS_BASIC_CAST typeDecl,
18713 			    "The value '%s' of the facet 'whitespace' is not "
18714 			    "valid", facet->value, NULL);
18715                     }
18716                 }
18717             }
18718         default:
18719             break;
18720     }
18721 exit:
18722     if ((! ctxtGiven) && (pctxt != NULL))
18723 	xmlSchemaFreeParserCtxt(pctxt);
18724     return (ret);
18725 internal_error:
18726     if ((! ctxtGiven) && (pctxt != NULL))
18727 	xmlSchemaFreeParserCtxt(pctxt);
18728     return (-1);
18729 }
18730 
18731 /**
18732  * xmlSchemaCheckFacetValues:
18733  * @typeDecl:  the schema type definition
18734  * @ctxt:  the schema parser context
18735  *
18736  * Checks the default values types, especially for facets
18737  */
18738 static int
xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,xmlSchemaParserCtxtPtr pctxt)18739 xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
18740 			  xmlSchemaParserCtxtPtr pctxt)
18741 {
18742     int res, olderrs = pctxt->nberrors;
18743     const xmlChar *name = typeDecl->name;
18744     /*
18745     * NOTE: It is intended to use the facets list, instead
18746     * of facetSet.
18747     */
18748     if (typeDecl->facets != NULL) {
18749 	xmlSchemaFacetPtr facet = typeDecl->facets;
18750 
18751 	/*
18752 	* Temporarily assign the "schema" to the validation context
18753 	* of the parser context. This is needed for NOTATION validation.
18754 	*/
18755 	if (pctxt->vctxt == NULL) {
18756 	    if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1)
18757 		return(-1);
18758 	}
18759 	pctxt->vctxt->schema = pctxt->schema;
18760 	while (facet != NULL) {
18761 	    res = xmlSchemaCheckFacet(facet, typeDecl, pctxt, name);
18762 	    HFAILURE
18763 	    facet = facet->next;
18764 	}
18765 	pctxt->vctxt->schema = NULL;
18766     }
18767     if (olderrs != pctxt->nberrors)
18768 	return(pctxt->err);
18769     return(0);
18770 exit_failure:
18771     return(-1);
18772 }
18773 
18774 /**
18775  * xmlSchemaGetCircModelGrDefRef:
18776  * @ctxtMGroup: the searched model group
18777  * @selfMGroup: the second searched model group
18778  * @particle: the first particle
18779  *
18780  * This one is intended to be used by
18781  * xmlSchemaCheckGroupDefCircular only.
18782  *
18783  * Returns the particle with the circular model group definition reference,
18784  * otherwise NULL.
18785  */
18786 static xmlSchemaTreeItemPtr
xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,xmlSchemaTreeItemPtr particle)18787 xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
18788 			      xmlSchemaTreeItemPtr particle)
18789 {
18790     xmlSchemaTreeItemPtr circ = NULL;
18791     xmlSchemaTreeItemPtr term;
18792     xmlSchemaModelGroupDefPtr gdef;
18793 
18794     for (; particle != NULL; particle = particle->next) {
18795 	term = particle->children;
18796 	if (term == NULL)
18797 	    continue;
18798 	switch (term->type) {
18799 	    case XML_SCHEMA_TYPE_GROUP:
18800 		gdef = (xmlSchemaModelGroupDefPtr) term;
18801 		if (gdef == groupDef)
18802 		    return (particle);
18803 		/*
18804 		* Mark this model group definition to avoid infinite
18805 		* recursion on circular references not yet examined.
18806 		*/
18807 		if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
18808 		    continue;
18809 		if (gdef->children != NULL) {
18810 		    gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18811 		    circ = xmlSchemaGetCircModelGrDefRef(groupDef,
18812 			gdef->children->children);
18813 		    gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18814 		    if (circ != NULL)
18815 			return (circ);
18816 		}
18817 		break;
18818 	    case XML_SCHEMA_TYPE_SEQUENCE:
18819 	    case XML_SCHEMA_TYPE_CHOICE:
18820 	    case XML_SCHEMA_TYPE_ALL:
18821 		circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
18822 		if (circ != NULL)
18823 		    return (circ);
18824 		break;
18825 	    default:
18826 		break;
18827 	}
18828     }
18829     return (NULL);
18830 }
18831 
18832 /**
18833  * xmlSchemaCheckGroupDefCircular:
18834  * @item:  the model group definition
18835  * @ctxt:  the parser context
18836  * @name:  the name
18837  *
18838  * Checks for circular references to model group definitions.
18839  */
18840 static void
xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,xmlSchemaParserCtxtPtr ctxt)18841 xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
18842 			       xmlSchemaParserCtxtPtr ctxt)
18843 {
18844     /*
18845     * Schema Component Constraint: Model Group Correct
18846     * 2 Circular groups are disallowed. That is, within the {particles}
18847     * of a group there must not be at any depth a particle whose {term}
18848     * is the group itself.
18849     */
18850     if ((item == NULL) ||
18851 	(item->type != XML_SCHEMA_TYPE_GROUP) ||
18852 	(item->children == NULL))
18853 	return;
18854     {
18855 	xmlSchemaTreeItemPtr circ;
18856 
18857 	circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
18858 	if (circ != NULL) {
18859 	    xmlChar *str = NULL;
18860 	    /*
18861 	    * TODO: The error report is not adequate: this constraint
18862 	    * is defined for model groups but not definitions, but since
18863 	    * there cannot be any circular model groups without a model group
18864 	    * definition (if not using a construction API), we check those
18865 	    * definitions only.
18866 	    */
18867 	    xmlSchemaPCustomErr(ctxt,
18868 		XML_SCHEMAP_MG_PROPS_CORRECT_2,
18869 		NULL, WXS_ITEM_NODE(circ),
18870 		"Circular reference to the model group definition '%s' "
18871 		"defined", xmlSchemaFormatQName(&str,
18872 		    item->targetNamespace, item->name));
18873 	    FREE_AND_NULL(str)
18874 	    /*
18875 	    * NOTE: We will cut the reference to avoid further
18876 	    * confusion of the processor. This is a fatal error.
18877 	    */
18878 	    circ->children = NULL;
18879 	}
18880     }
18881 }
18882 
18883 /**
18884  * xmlSchemaModelGroupToModelGroupDefFixup:
18885  * @ctxt:  the parser context
18886  * @mg:  the model group
18887  *
18888  * Assigns the model group of model group definitions to the "term"
18889  * of the referencing particle.
18890  * In xmlSchemaResolveModelGroupParticleReferences the model group
18891  * definitions were assigned to the "term", since needed for the
18892  * circularity check.
18893  *
18894  * Schema Component Constraint:
18895  *     All Group Limited (cos-all-limited) (1.2)
18896  */
18897 static void
xmlSchemaModelGroupToModelGroupDefFixup(xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,xmlSchemaModelGroupPtr mg)18898 xmlSchemaModelGroupToModelGroupDefFixup(
18899     xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
18900     xmlSchemaModelGroupPtr mg)
18901 {
18902     xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
18903 
18904     while (particle != NULL) {
18905 	if ((WXS_PARTICLE_TERM(particle) == NULL) ||
18906 	    ((WXS_PARTICLE_TERM(particle))->type !=
18907 		XML_SCHEMA_TYPE_GROUP))
18908 	{
18909 	    particle = WXS_PTC_CAST particle->next;
18910 	    continue;
18911 	}
18912 	if (WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle)) == NULL) {
18913 	    /*
18914 	    * TODO: Remove the particle.
18915 	    */
18916 	    WXS_PARTICLE_TERM(particle) = NULL;
18917 	    particle = WXS_PTC_CAST particle->next;
18918 	    continue;
18919 	}
18920 	/*
18921 	* Assign the model group to the {term} of the particle.
18922 	*/
18923 	WXS_PARTICLE_TERM(particle) =
18924 	    WXS_TREE_CAST WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle));
18925 
18926 	particle = WXS_PTC_CAST particle->next;
18927     }
18928 }
18929 
18930 /**
18931  * xmlSchemaCheckAttrGroupCircularRecur:
18932  * @ctxtGr: the searched attribute group
18933  * @attr: the current attribute list to be processed
18934  *
18935  * This one is intended to be used by
18936  * xmlSchemaCheckAttrGroupCircular only.
18937  *
18938  * Returns the circular attribute group reference, otherwise NULL.
18939  */
18940 static xmlSchemaQNameRefPtr
xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,xmlSchemaItemListPtr list)18941 xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,
18942 				     xmlSchemaItemListPtr list)
18943 {
18944     xmlSchemaAttributeGroupPtr gr;
18945     xmlSchemaQNameRefPtr ref, circ;
18946     int i;
18947     /*
18948     * We will search for an attribute group reference which
18949     * references the context attribute group.
18950     */
18951     for (i = 0; i < list->nbItems; i++) {
18952 	ref = list->items[i];
18953 	if ((ref->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
18954 	    (ref->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
18955 	    (ref->item != NULL))
18956 	{
18957 	    gr = WXS_ATTR_GROUP_CAST ref->item;
18958 	    if (gr == ctxtGr)
18959 		return(ref);
18960 	    if (gr->flags & XML_SCHEMAS_ATTRGROUP_MARKED)
18961 		continue;
18962 	    /*
18963 	    * Mark as visited to avoid infinite recursion on
18964 	    * circular references not yet examined.
18965 	    */
18966 	    if ((gr->attrUses) &&
18967 		(gr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS))
18968 	    {
18969 		gr->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
18970 		circ = xmlSchemaCheckAttrGroupCircularRecur(ctxtGr,
18971 		    (xmlSchemaItemListPtr) gr->attrUses);
18972 		gr->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
18973 		if (circ != NULL)
18974 		    return (circ);
18975 	    }
18976 
18977 	}
18978     }
18979     return (NULL);
18980 }
18981 
18982 /**
18983  * xmlSchemaCheckAttrGroupCircular:
18984  * attrGr:  the attribute group definition
18985  * @ctxt:  the parser context
18986  * @name:  the name
18987  *
18988  * Checks for circular references of attribute groups.
18989  */
18990 static int
xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,xmlSchemaParserCtxtPtr ctxt)18991 xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
18992 				xmlSchemaParserCtxtPtr ctxt)
18993 {
18994     /*
18995     * Schema Representation Constraint:
18996     * Attribute Group Definition Representation OK
18997     * 3 Circular group reference is disallowed outside <redefine>.
18998     * That is, unless this element information item's parent is
18999     * <redefine>, then among the [children], if any, there must
19000     * not be an <attributeGroup> with ref [attribute] which resolves
19001     * to the component corresponding to this <attributeGroup>. Indirect
19002     * circularity is also ruled out. That is, when QName resolution
19003     * (Schema Document) ($3.15.3) is applied to a `QName` arising from
19004     * any <attributeGroup>s with a ref [attribute] among the [children],
19005     * it must not be the case that a `QName` is encountered at any depth
19006     * which resolves to the component corresponding to this <attributeGroup>.
19007     */
19008     if (attrGr->attrUses == NULL)
19009 	return(0);
19010     else if ((attrGr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS) == 0)
19011 	return(0);
19012     else {
19013 	xmlSchemaQNameRefPtr circ;
19014 
19015 	circ = xmlSchemaCheckAttrGroupCircularRecur(attrGr,
19016 	    (xmlSchemaItemListPtr) attrGr->attrUses);
19017 	if (circ != NULL) {
19018 	    xmlChar *str = NULL;
19019 	    /*
19020 	    * TODO: Report the referenced attr group as QName.
19021 	    */
19022 	    xmlSchemaPCustomErr(ctxt,
19023 		XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
19024 		NULL, WXS_ITEM_NODE(WXS_BASIC_CAST circ),
19025 		"Circular reference to the attribute group '%s' "
19026 		"defined", xmlSchemaGetComponentQName(&str, attrGr));
19027 	    FREE_AND_NULL(str);
19028 	    /*
19029 	    * NOTE: We will cut the reference to avoid further
19030 	    * confusion of the processor.
19031 	    * BADSPEC TODO: The spec should define how to process in this case.
19032 	    */
19033 	    circ->item = NULL;
19034 	    return(ctxt->err);
19035 	}
19036     }
19037     return(0);
19038 }
19039 
19040 static int
19041 xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19042 				  xmlSchemaAttributeGroupPtr attrGr);
19043 
19044 /**
19045  * xmlSchemaExpandAttributeGroupRefs:
19046  * @pctxt: the parser context
19047  * @node: the node of the component holding the attribute uses
19048  * @completeWild: the intersected wildcard to be returned
19049  * @list: the attribute uses
19050  *
19051  * Substitutes contained attribute group references
19052  * for their attribute uses. Wildcards are intersected.
19053  * Attribute use prohibitions are removed from the list
19054  * and returned via the @prohibs list.
19055  * Pointlessness of attr. prohibs, if a matching attr. decl
19056  * is existent a well, are checked.
19057  */
19058 static int
xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBasicItemPtr item,xmlSchemaWildcardPtr * completeWild,xmlSchemaItemListPtr list,xmlSchemaItemListPtr prohibs)19059 xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
19060 				  xmlSchemaBasicItemPtr item,
19061 				  xmlSchemaWildcardPtr *completeWild,
19062 				  xmlSchemaItemListPtr list,
19063 				  xmlSchemaItemListPtr prohibs)
19064 {
19065     xmlSchemaAttributeGroupPtr gr;
19066     xmlSchemaAttributeUsePtr use;
19067     xmlSchemaItemListPtr sublist;
19068     int i, j;
19069     int created = (*completeWild == NULL) ? 0 : 1;
19070 
19071     if (prohibs)
19072 	prohibs->nbItems = 0;
19073 
19074     for (i = 0; i < list->nbItems; i++) {
19075 	use = list->items[i];
19076 
19077 	if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
19078 	    if (prohibs == NULL) {
19079 		PERROR_INT("xmlSchemaExpandAttributeGroupRefs",
19080 		    "unexpected attr prohibition found");
19081 		return(-1);
19082 	    }
19083 	    /*
19084 	    * Remove from attribute uses.
19085 	    */
19086 	    if (xmlSchemaItemListRemove(list, i) == -1)
19087 		return(-1);
19088 	    i--;
19089 	    /*
19090 	    * Note that duplicate prohibitions were already
19091 	    * handled at parsing time.
19092 	    */
19093 	    /*
19094 	    * Add to list of prohibitions.
19095 	    */
19096 	    xmlSchemaItemListAddSize(prohibs, 2, use);
19097 	    continue;
19098 	}
19099 	if ((use->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19100 	    ((WXS_QNAME_CAST use)->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP))
19101 	{
19102 	    if ((WXS_QNAME_CAST use)->item == NULL)
19103 		return(-1);
19104 	    gr = WXS_ATTR_GROUP_CAST (WXS_QNAME_CAST use)->item;
19105 	    /*
19106 	    * Expand the referenced attr. group.
19107 	    * TODO: remove this, this is done in a previous step, so
19108 	    * already done here.
19109 	    */
19110 	    if ((gr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
19111 		if (xmlSchemaAttributeGroupExpandRefs(pctxt, gr) == -1)
19112 		    return(-1);
19113 	    }
19114 	    /*
19115 	    * Build the 'complete' wildcard; i.e. intersect multiple
19116 	    * wildcards.
19117 	    */
19118 	    if (gr->attributeWildcard != NULL) {
19119 		if (*completeWild == NULL) {
19120 		    *completeWild = gr->attributeWildcard;
19121 		} else {
19122 		    if (! created) {
19123 			xmlSchemaWildcardPtr tmpWild;
19124 
19125 			 /*
19126 			* Copy the first encountered wildcard as context,
19127 			* except for the annotation.
19128 			*
19129 			* Although the complete wildcard might not correspond
19130 			* to any node in the schema, we will anchor it on
19131 			* the node of the owner component.
19132 			*/
19133 			tmpWild =  xmlSchemaAddWildcard(pctxt, pctxt->schema,
19134 			    XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
19135 			    WXS_ITEM_NODE(item));
19136 			if (tmpWild == NULL)
19137 			    return(-1);
19138 			if (xmlSchemaCloneWildcardNsConstraints(pctxt,
19139 			    tmpWild, *completeWild) == -1)
19140 			    return (-1);
19141 			tmpWild->processContents = (*completeWild)->processContents;
19142 			*completeWild = tmpWild;
19143 			created = 1;
19144 		    }
19145 
19146 		    if (xmlSchemaIntersectWildcards(pctxt, *completeWild,
19147 			gr->attributeWildcard) == -1)
19148 			return(-1);
19149 		}
19150 	    }
19151 	    /*
19152 	    * Just remove the reference if the referenced group does not
19153 	    * contain any attribute uses.
19154 	    */
19155 	    sublist = ((xmlSchemaItemListPtr) gr->attrUses);
19156 	    if ((sublist == NULL) || sublist->nbItems == 0) {
19157 		if (xmlSchemaItemListRemove(list, i) == -1)
19158 		    return(-1);
19159 		i--;
19160 		continue;
19161 	    }
19162 	    /*
19163 	    * Add the attribute uses.
19164 	    */
19165 	    list->items[i] = sublist->items[0];
19166 	    if (sublist->nbItems != 1) {
19167 		for (j = 1; j < sublist->nbItems; j++) {
19168 		    i++;
19169 		    if (xmlSchemaItemListInsert(list,
19170 			    sublist->items[j], i) == -1)
19171 			return(-1);
19172 		}
19173 	    }
19174 	}
19175 
19176     }
19177     /*
19178     * Handle pointless prohibitions of declared attributes.
19179     */
19180     if (prohibs && (prohibs->nbItems != 0) && (list->nbItems != 0)) {
19181 	xmlSchemaAttributeUseProhibPtr prohib;
19182 
19183 	for (i = prohibs->nbItems -1; i >= 0; i--) {
19184 	    prohib = prohibs->items[i];
19185 	    for (j = 0; j < list->nbItems; j++) {
19186 		use = list->items[j];
19187 
19188 		if ((prohib->name == WXS_ATTRUSE_DECL_NAME(use)) &&
19189 		    (prohib->targetNamespace == WXS_ATTRUSE_DECL_TNS(use)))
19190 		{
19191 		    xmlChar *str = NULL;
19192 
19193 		    xmlSchemaCustomWarning(ACTXT_CAST pctxt,
19194 			XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
19195 			prohib->node, NULL,
19196 			"Skipping pointless attribute use prohibition "
19197 			"'%s', since a corresponding attribute use "
19198 			"exists already in the type definition",
19199 			xmlSchemaFormatQName(&str,
19200 			    prohib->targetNamespace, prohib->name),
19201 			NULL, NULL);
19202 		    FREE_AND_NULL(str);
19203 		    /*
19204 		    * Remove the prohibition.
19205 		    */
19206 		    if (xmlSchemaItemListRemove(prohibs, i) == -1)
19207 			return(-1);
19208 		    break;
19209 		}
19210 	    }
19211 	}
19212     }
19213     return(0);
19214 }
19215 
19216 /**
19217  * xmlSchemaAttributeGroupExpandRefs:
19218  * @pctxt:  the parser context
19219  * @attrGr:  the attribute group definition
19220  *
19221  * Computation of:
19222  * {attribute uses} property
19223  * {attribute wildcard} property
19224  *
19225  * Substitutes contained attribute group references
19226  * for their attribute uses. Wildcards are intersected.
19227  */
19228 static int
xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,xmlSchemaAttributeGroupPtr attrGr)19229 xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19230 				  xmlSchemaAttributeGroupPtr attrGr)
19231 {
19232     if ((attrGr->attrUses == NULL) ||
19233 	(attrGr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED))
19234 	return(0);
19235 
19236     attrGr->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
19237     if (xmlSchemaExpandAttributeGroupRefs(pctxt, WXS_BASIC_CAST attrGr,
19238 	&(attrGr->attributeWildcard), attrGr->attrUses, NULL) == -1)
19239 	return(-1);
19240     return(0);
19241 }
19242 
19243 /**
19244  * xmlSchemaAttributeGroupExpandRefs:
19245  * @pctxt:  the parser context
19246  * @attrGr:  the attribute group definition
19247  *
19248  * Substitutes contained attribute group references
19249  * for their attribute uses. Wildcards are intersected.
19250  *
19251  * Schema Component Constraint:
19252  *    Attribute Group Definition Properties Correct (ag-props-correct)
19253  */
19254 static int
xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,xmlSchemaAttributeGroupPtr attrGr)19255 xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19256 				  xmlSchemaAttributeGroupPtr attrGr)
19257 {
19258     /*
19259     * SPEC ag-props-correct
19260     * (1) "The values of the properties of an attribute group definition
19261     * must be as described in the property tableau in The Attribute
19262     * Group Definition Schema Component ($3.6.1), modulo the impact of
19263     * Missing Sub-components ($5.3);"
19264     */
19265 
19266     if ((attrGr->attrUses != NULL) &&
19267 	(WXS_LIST_CAST attrGr->attrUses)->nbItems > 1)
19268     {
19269 	xmlSchemaItemListPtr uses = WXS_LIST_CAST attrGr->attrUses;
19270 	xmlSchemaAttributeUsePtr use, tmp;
19271 	int i, j, hasId = 0;
19272 
19273 	for (i = uses->nbItems -1; i >= 0; i--) {
19274 	    use = uses->items[i];
19275 	    /*
19276 	    * SPEC ag-props-correct
19277 	    * (2) "Two distinct members of the {attribute uses} must not have
19278 	    * {attribute declaration}s both of whose {name}s match and whose
19279 	    * {target namespace}s are identical."
19280 	    */
19281 	    if (i > 0) {
19282 		for (j = i -1; j >= 0; j--) {
19283 		    tmp = uses->items[j];
19284 		    if ((WXS_ATTRUSE_DECL_NAME(use) ==
19285 			WXS_ATTRUSE_DECL_NAME(tmp)) &&
19286 			(WXS_ATTRUSE_DECL_TNS(use) ==
19287 			WXS_ATTRUSE_DECL_TNS(tmp)))
19288 		    {
19289 			xmlChar *str = NULL;
19290 
19291 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
19292 			    XML_SCHEMAP_AG_PROPS_CORRECT,
19293 			    attrGr->node, WXS_BASIC_CAST attrGr,
19294 			    "Duplicate %s",
19295 			    xmlSchemaGetComponentDesignation(&str, use),
19296 			    NULL);
19297 			FREE_AND_NULL(str);
19298 			/*
19299 			* Remove the duplicate.
19300 			*/
19301 			if (xmlSchemaItemListRemove(uses, i) == -1)
19302 			    return(-1);
19303 			goto next_use;
19304 		    }
19305 		}
19306 	    }
19307 	    /*
19308 	    * SPEC ag-props-correct
19309 	    * (3) "Two distinct members of the {attribute uses} must not have
19310 	    * {attribute declaration}s both of whose {type definition}s are or
19311 	    * are derived from ID."
19312 	    * TODO: Does 'derived' include member-types of unions?
19313 	    */
19314 	    if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
19315 		if (xmlSchemaIsDerivedFromBuiltInType(
19316 		    WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
19317 		{
19318 		    if (hasId) {
19319 			xmlChar *str = NULL;
19320 
19321 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
19322 			    XML_SCHEMAP_AG_PROPS_CORRECT,
19323 			    attrGr->node, WXS_BASIC_CAST attrGr,
19324 			    "There must not exist more than one attribute "
19325 			    "declaration of type 'xs:ID' "
19326 			    "(or derived from 'xs:ID'). The %s violates this "
19327 			    "constraint",
19328 			    xmlSchemaGetComponentDesignation(&str, use),
19329 			    NULL);
19330 			FREE_AND_NULL(str);
19331 			if (xmlSchemaItemListRemove(uses, i) == -1)
19332 			    return(-1);
19333 		    }
19334 		    hasId = 1;
19335 		}
19336 	    }
19337 next_use: {}
19338 	}
19339     }
19340     return(0);
19341 }
19342 
19343 /**
19344  * xmlSchemaResolveAttrGroupReferences:
19345  * @attrgrpDecl:  the schema attribute definition
19346  * @ctxt:  the schema parser context
19347  * @name:  the attribute name
19348  *
19349  * Resolves references to attribute group definitions.
19350  */
19351 static int
xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,xmlSchemaParserCtxtPtr ctxt)19352 xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,
19353 				    xmlSchemaParserCtxtPtr ctxt)
19354 {
19355     xmlSchemaAttributeGroupPtr group;
19356 
19357     if (ref->item != NULL)
19358         return(0);
19359     group = xmlSchemaGetAttributeGroup(ctxt->schema,
19360 	ref->name,
19361 	ref->targetNamespace);
19362     if (group == NULL) {
19363 	xmlSchemaPResCompAttrErr(ctxt,
19364 	    XML_SCHEMAP_SRC_RESOLVE,
19365 	    NULL, ref->node,
19366 	    "ref", ref->name, ref->targetNamespace,
19367 	    ref->itemType, NULL);
19368 	return(ctxt->err);
19369     }
19370     ref->item = WXS_BASIC_CAST group;
19371     return(0);
19372 }
19373 
19374 /**
19375  * xmlSchemaCheckAttrPropsCorrect:
19376  * @item:  an schema attribute declaration/use
19377  * @ctxt:  a schema parser context
19378  * @name:  the name of the attribute
19379  *
19380  *
19381  * Schema Component Constraint:
19382  *    Attribute Declaration Properties Correct (a-props-correct)
19383  *
19384  * Validates the value constraints of an attribute declaration/use.
19385  * NOTE that this needs the simple type definitions to be already
19386  *   built and checked.
19387  */
19388 static int
xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,xmlSchemaAttributePtr attr)19389 xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19390 			       xmlSchemaAttributePtr attr)
19391 {
19392 
19393     /*
19394     * SPEC a-props-correct (1)
19395     * "The values of the properties of an attribute declaration must
19396     * be as described in the property tableau in The Attribute
19397     * Declaration Schema Component ($3.2.1), modulo the impact of
19398     * Missing Sub-components ($5.3)."
19399     */
19400 
19401     if (WXS_ATTR_TYPEDEF(attr) == NULL)
19402 	return(0);
19403 
19404     if (attr->defValue != NULL) {
19405 	int ret;
19406 
19407 	/*
19408 	* SPEC a-props-correct (3)
19409 	* "If the {type definition} is or is derived from ID then there
19410 	* must not be a {value constraint}."
19411 	*/
19412 	if (xmlSchemaIsDerivedFromBuiltInType(
19413 	    WXS_ATTR_TYPEDEF(attr), XML_SCHEMAS_ID))
19414 	{
19415 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
19416 		XML_SCHEMAP_A_PROPS_CORRECT_3,
19417 		NULL, WXS_BASIC_CAST attr,
19418 		"Value constraints are not allowed if the type definition "
19419 		"is or is derived from xs:ID",
19420 		NULL, NULL);
19421 	    return(pctxt->err);
19422 	}
19423 	/*
19424 	* SPEC a-props-correct (2)
19425 	* "if there is a {value constraint}, the canonical lexical
19426 	* representation of its value must be `valid` with respect
19427 	* to the {type definition} as defined in String Valid ($3.14.4)."
19428 	* TODO: Don't care about the *canonical* stuff here, this requirement
19429 	* will be removed in WXS 1.1 anyway.
19430 	*/
19431 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt,
19432 	    attr->node, WXS_ATTR_TYPEDEF(attr),
19433 	    attr->defValue, &(attr->defVal),
19434 	    1, 1, 0);
19435 	if (ret != 0) {
19436 	    if (ret < 0) {
19437 		PERROR_INT("xmlSchemaCheckAttrPropsCorrect",
19438 		    "calling xmlSchemaVCheckCVCSimpleType()");
19439 		return(-1);
19440 	    }
19441 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
19442 		XML_SCHEMAP_A_PROPS_CORRECT_2,
19443 		NULL, WXS_BASIC_CAST attr,
19444 		"The value of the value constraint is not valid",
19445 		NULL, NULL);
19446 	    return(pctxt->err);
19447 	}
19448     }
19449 
19450     return(0);
19451 }
19452 
19453 static xmlSchemaElementPtr
xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,xmlSchemaElementPtr ancestor)19454 xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
19455 				 xmlSchemaElementPtr ancestor)
19456 {
19457     xmlSchemaElementPtr ret;
19458 
19459     if (WXS_SUBST_HEAD(ancestor) == NULL)
19460 	return (NULL);
19461     if (WXS_SUBST_HEAD(ancestor) == elemDecl)
19462 	return (ancestor);
19463 
19464     if (WXS_SUBST_HEAD(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
19465 	return (NULL);
19466     WXS_SUBST_HEAD(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
19467     ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
19468 	WXS_SUBST_HEAD(ancestor));
19469     WXS_SUBST_HEAD(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
19470 
19471     return (ret);
19472 }
19473 
19474 /**
19475  * xmlSchemaCheckElemPropsCorrect:
19476  * @ctxt:  a schema parser context
19477  * @decl: the element declaration
19478  * @name:  the name of the attribute
19479  *
19480  * Schema Component Constraint:
19481  * Element Declaration Properties Correct (e-props-correct)
19482  *
19483  * STATUS:
19484  *   missing: (6)
19485  */
19486 static int
xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,xmlSchemaElementPtr elemDecl)19487 xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19488 			       xmlSchemaElementPtr elemDecl)
19489 {
19490     int ret = 0;
19491     xmlSchemaTypePtr typeDef = WXS_ELEM_TYPEDEF(elemDecl);
19492     /*
19493     * SPEC (1) "The values of the properties of an element declaration
19494     * must be as described in the property tableau in The Element
19495     * Declaration Schema Component ($3.3.1), modulo the impact of Missing
19496     * Sub-components ($5.3)."
19497     */
19498     if (WXS_SUBST_HEAD(elemDecl) != NULL) {
19499 	xmlSchemaElementPtr head = WXS_SUBST_HEAD(elemDecl), circ;
19500 
19501 	xmlSchemaCheckElementDeclComponent(head, pctxt);
19502 	/*
19503 	* SPEC (3) "If there is a non-`absent` {substitution group
19504 	* affiliation}, then {scope} must be global."
19505 	*/
19506 	if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
19507 	    xmlSchemaPCustomErr(pctxt,
19508 		XML_SCHEMAP_E_PROPS_CORRECT_3,
19509 		WXS_BASIC_CAST elemDecl, NULL,
19510 		"Only global element declarations can have a "
19511 		"substitution group affiliation", NULL);
19512 	    ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
19513 	}
19514 	/*
19515 	* TODO: SPEC (6) "Circular substitution groups are disallowed.
19516 	* That is, it must not be possible to return to an element declaration
19517 	* by repeatedly following the {substitution group affiliation}
19518 	* property."
19519 	*/
19520 	if (head == elemDecl)
19521 	    circ = head;
19522 	else if (WXS_SUBST_HEAD(head) != NULL)
19523 	    circ = xmlSchemaCheckSubstGroupCircular(head, head);
19524 	else
19525 	    circ = NULL;
19526 	if (circ != NULL) {
19527 	    xmlChar *strA = NULL, *strB = NULL;
19528 
19529 	    xmlSchemaPCustomErrExt(pctxt,
19530 		XML_SCHEMAP_E_PROPS_CORRECT_6,
19531 		WXS_BASIC_CAST circ, NULL,
19532 		"The element declaration '%s' defines a circular "
19533 		"substitution group to element declaration '%s'",
19534 		xmlSchemaGetComponentQName(&strA, circ),
19535 		xmlSchemaGetComponentQName(&strB, head),
19536 		NULL);
19537 	    FREE_AND_NULL(strA)
19538 	    FREE_AND_NULL(strB)
19539 	    ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
19540 	}
19541 	/*
19542 	* SPEC (4) "If there is a {substitution group affiliation},
19543 	* the {type definition}
19544 	* of the element declaration must be validly derived from the {type
19545 	* definition} of the {substitution group affiliation}, given the value
19546 	* of the {substitution group exclusions} of the {substitution group
19547 	* affiliation}, as defined in Type Derivation OK (Complex) ($3.4.6)
19548 	* (if the {type definition} is complex) or as defined in
19549 	* Type Derivation OK (Simple) ($3.14.6) (if the {type definition} is
19550 	* simple)."
19551 	*
19552 	* NOTE: {substitution group exclusions} means the values of the
19553 	* attribute "final".
19554 	*/
19555 
19556 	if (typeDef != WXS_ELEM_TYPEDEF(WXS_SUBST_HEAD(elemDecl))) {
19557 	    int set = 0;
19558 
19559 	    if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
19560 		set |= SUBSET_EXTENSION;
19561 	    if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
19562 		set |= SUBSET_RESTRICTION;
19563 
19564 	    if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST pctxt, typeDef,
19565 		WXS_ELEM_TYPEDEF(head), set) != 0) {
19566 		xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
19567 
19568 		ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
19569 		xmlSchemaPCustomErrExt(pctxt,
19570 		    XML_SCHEMAP_E_PROPS_CORRECT_4,
19571 		    WXS_BASIC_CAST elemDecl, NULL,
19572 		    "The type definition '%s' was "
19573 		    "either rejected by the substitution group "
19574 		    "affiliation '%s', or not validly derived from its type "
19575 		    "definition '%s'",
19576 		    xmlSchemaGetComponentQName(&strA, typeDef),
19577 		    xmlSchemaGetComponentQName(&strB, head),
19578 		    xmlSchemaGetComponentQName(&strC, WXS_ELEM_TYPEDEF(head)));
19579 		FREE_AND_NULL(strA)
19580 		FREE_AND_NULL(strB)
19581 		FREE_AND_NULL(strC)
19582 	    }
19583 	}
19584     }
19585     /*
19586     * SPEC (5) "If the {type definition} or {type definition}'s
19587     * {content type}
19588     * is or is derived from ID then there must not be a {value constraint}.
19589     * Note: The use of ID as a type definition for elements goes beyond
19590     * XML 1.0, and should be avoided if backwards compatibility is desired"
19591     */
19592     if ((elemDecl->value != NULL) &&
19593 	((WXS_IS_SIMPLE(typeDef) &&
19594 	  xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
19595 	 (WXS_IS_COMPLEX(typeDef) &&
19596 	  WXS_HAS_SIMPLE_CONTENT(typeDef) &&
19597 	  xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
19598 	    XML_SCHEMAS_ID)))) {
19599 
19600 	ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
19601 	xmlSchemaPCustomErr(pctxt,
19602 	    XML_SCHEMAP_E_PROPS_CORRECT_5,
19603 	    WXS_BASIC_CAST elemDecl, NULL,
19604 	    "The type definition (or type definition's content type) is or "
19605 	    "is derived from ID; value constraints are not allowed in "
19606 	    "conjunction with such a type definition", NULL);
19607     } else if (elemDecl->value != NULL) {
19608 	int vcret;
19609 	xmlNodePtr node = NULL;
19610 
19611 	/*
19612 	* SPEC (2) "If there is a {value constraint}, the canonical lexical
19613 	* representation of its value must be `valid` with respect to the
19614 	* {type definition} as defined in Element Default Valid (Immediate)
19615 	* ($3.3.6)."
19616 	*/
19617 	if (typeDef == NULL) {
19618 	    xmlSchemaPErr(pctxt, elemDecl->node,
19619 		XML_SCHEMAP_INTERNAL,
19620 		"Internal error: xmlSchemaCheckElemPropsCorrect, "
19621 		"type is missing... skipping validation of "
19622 		"the value constraint", NULL, NULL);
19623 	    return (-1);
19624 	}
19625 	if (elemDecl->node != NULL) {
19626 	    if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
19627 		node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19628 		    BAD_CAST "fixed");
19629 	    else
19630 		node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19631 		    BAD_CAST "default");
19632 	}
19633 	vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
19634 	    typeDef, elemDecl->value, &(elemDecl->defVal));
19635 	if (vcret != 0) {
19636 	    if (vcret < 0) {
19637 		PERROR_INT("xmlSchemaElemCheckValConstr",
19638 		    "failed to validate the value constraint of an "
19639 		    "element declaration");
19640 		return (-1);
19641 	    }
19642 	    return (vcret);
19643 	}
19644     }
19645 
19646     return (ret);
19647 }
19648 
19649 /**
19650  * xmlSchemaCheckElemSubstGroup:
19651  * @ctxt:  a schema parser context
19652  * @decl: the element declaration
19653  * @name:  the name of the attribute
19654  *
19655  * Schema Component Constraint:
19656  * Substitution Group (cos-equiv-class)
19657  *
19658  * In Libxml2 the subst. groups will be precomputed, in terms of that
19659  * a list will be built for each subst. group head, holding all direct
19660  * referents to this head.
19661  * NOTE that this function needs:
19662  *   1. circular subst. groups to be checked beforehand
19663  *   2. the declaration's type to be derived from the head's type
19664  *
19665  * STATUS:
19666  *
19667  */
19668 static void
xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,xmlSchemaElementPtr elemDecl)19669 xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
19670 			     xmlSchemaElementPtr elemDecl)
19671 {
19672     if ((WXS_SUBST_HEAD(elemDecl) == NULL) ||
19673 	/* SPEC (1) "Its {abstract} is false." */
19674 	(elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
19675 	return;
19676     {
19677 	xmlSchemaElementPtr head;
19678 	xmlSchemaTypePtr headType, type;
19679 	int set, methSet;
19680 	/*
19681 	* SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
19682 	* {disallowed substitutions} as the blocking constraint, as defined in
19683 	* Substitution Group OK (Transitive) ($3.3.6)."
19684 	*/
19685 	for (head = WXS_SUBST_HEAD(elemDecl); head != NULL;
19686 	    head = WXS_SUBST_HEAD(head)) {
19687 	    set = 0;
19688 	    methSet = 0;
19689 	    /*
19690 	    * The blocking constraints.
19691 	    */
19692 	    if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
19693 		continue;
19694 	    headType = head->subtypes;
19695 	    type = elemDecl->subtypes;
19696 	    if (headType == type)
19697 		goto add_member;
19698 	    if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
19699 		set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19700 	    if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
19701 		set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19702 	    /*
19703 	    * SPEC: Substitution Group OK (Transitive) (2.3)
19704 	    * "The set of all {derivation method}s involved in the
19705 	    * derivation of D's {type definition} from C's {type definition}
19706 	    * does not intersect with the union of the blocking constraint,
19707 	    * C's {prohibited substitutions} (if C is complex, otherwise the
19708 	    * empty set) and the {prohibited substitutions} (respectively the
19709 	    * empty set) of any intermediate {type definition}s in the
19710 	    * derivation of D's {type definition} from C's {type definition}."
19711 	    */
19712 	    /*
19713 	    * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
19714 	    * subst.head axis, the methSet does not need to be computed for
19715 	    * the full depth over and over.
19716 	    */
19717 	    /*
19718 	    * The set of all {derivation method}s involved in the derivation
19719 	    */
19720 	    while ((type != NULL) && (type != headType) &&
19721                    (type != type->baseType)) {
19722 		if ((WXS_IS_EXTENSION(type)) &&
19723 		    ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19724 		    methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19725 
19726 		if (WXS_IS_RESTRICTION(type) &&
19727 		    ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19728 		    methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19729 
19730 		type = type->baseType;
19731 	    }
19732 	    /*
19733 	    * The {prohibited substitutions} of all intermediate types +
19734 	    * the head's type.
19735 	    */
19736 	    type = elemDecl->subtypes->baseType;
19737 	    while (type != NULL) {
19738 		if (WXS_IS_COMPLEX(type)) {
19739 		    if ((type->flags &
19740 			    XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19741 			((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
19742 		    set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19743 		    if ((type->flags &
19744 			    XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19745 			((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19746 		    set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19747 		} else
19748 		    break;
19749 		if (type == headType)
19750 		    break;
19751 		type = type->baseType;
19752 	    }
19753 	    if ((set != 0) &&
19754 		(((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19755 		(methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
19756 		((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19757 		(methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
19758 		continue;
19759 	    }
19760 add_member:
19761 	    xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
19762 	    if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
19763 		head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
19764 	}
19765     }
19766 }
19767 
19768 #ifdef WXS_ELEM_DECL_CONS_ENABLED /* enable when finished */
19769 /**
19770  * xmlSchemaCheckElementDeclComponent
19771  * @pctxt: the schema parser context
19772  * @ctxtComponent: the context component (an element declaration)
19773  * @ctxtParticle: the first particle of the context component
19774  * @searchParticle: the element declaration particle to be analysed
19775  *
19776  * Schema Component Constraint: Element Declarations Consistent
19777  */
19778 static int
xmlSchemaCheckElementDeclConsistent(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBasicItemPtr ctxtComponent,xmlSchemaParticlePtr ctxtParticle,xmlSchemaParticlePtr searchParticle,xmlSchemaParticlePtr curParticle,int search)19779 xmlSchemaCheckElementDeclConsistent(xmlSchemaParserCtxtPtr pctxt,
19780 				    xmlSchemaBasicItemPtr ctxtComponent,
19781 				    xmlSchemaParticlePtr ctxtParticle,
19782 				    xmlSchemaParticlePtr searchParticle,
19783 				    xmlSchemaParticlePtr curParticle,
19784 				    int search)
19785 {
19786     return(0);
19787 
19788     int ret = 0;
19789     xmlSchemaParticlePtr cur = curParticle;
19790     if (curParticle == NULL) {
19791 	return(0);
19792     }
19793     if (WXS_PARTICLE_TERM(curParticle) == NULL) {
19794 	/*
19795 	* Just return in this case. A missing "term" of the particle
19796 	* might arise due to an invalid "term" component.
19797 	*/
19798 	return(0);
19799     }
19800     while (cur != NULL) {
19801 	switch (WXS_PARTICLE_TERM(cur)->type) {
19802 	    case XML_SCHEMA_TYPE_ANY:
19803 		break;
19804 	    case XML_SCHEMA_TYPE_ELEMENT:
19805 		if (search == 0) {
19806 		    ret = xmlSchemaCheckElementDeclConsistent(pctxt,
19807 			ctxtComponent, ctxtParticle, cur, ctxtParticle, 1);
19808 		    if (ret != 0)
19809 			return(ret);
19810 		} else {
19811 		    xmlSchemaElementPtr elem =
19812 			WXS_ELEM_CAST(WXS_PARTICLE_TERM(cur));
19813 		    /*
19814 		    * SPEC Element Declarations Consistent:
19815 		    * "If the {particles} contains, either directly,
19816 		    * indirectly (that is, within the {particles} of a
19817 		    * contained model group, recursively) or `implicitly`
19818 		    * two or more element declaration particles with
19819 		    * the same {name} and {target namespace}, then
19820 		    * all their type definitions must be the same
19821 		    * top-level definition [...]"
19822 		    */
19823 		    if (xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->name,
19824 			    WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->name) &&
19825 			xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
19826 			    WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->targetNamespace))
19827 		    {
19828 			xmlChar *strA = NULL, *strB = NULL;
19829 
19830 			xmlSchemaCustomErr(ACTXT_CAST pctxt,
19831 			    /* TODO: error code */
19832 			    XML_SCHEMAP_COS_NONAMBIG,
19833 			    WXS_ITEM_NODE(cur), NULL,
19834 			    "In the content model of %s, there are multiple "
19835 			    "element declarations for '%s' with different "
19836 			    "type definitions",
19837 			    xmlSchemaGetComponentDesignation(&strA,
19838 				ctxtComponent),
19839 			    xmlSchemaFormatQName(&strB,
19840 				WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
19841 				WXS_PARTICLE_TERM_AS_ELEM(cur)->name));
19842 			FREE_AND_NULL(strA);
19843 			FREE_AND_NULL(strB);
19844 			return(XML_SCHEMAP_COS_NONAMBIG);
19845 		    }
19846 		}
19847 		break;
19848 	    case XML_SCHEMA_TYPE_SEQUENCE: {
19849 		break;
19850 		}
19851 	    case XML_SCHEMA_TYPE_CHOICE:{
19852 		/*
19853 		xmlSchemaTreeItemPtr sub;
19854 
19855 		sub = WXS_PARTICLE_TERM(particle)->children;  (xmlSchemaParticlePtr)
19856 		while (sub != NULL) {
19857 		    ret = xmlSchemaCheckElementDeclConsistent(pctxt, ctxtComponent,
19858 			ctxtParticle, ctxtElem);
19859 		    if (ret != 0)
19860 			return(ret);
19861 		    sub = sub->next;
19862 		}
19863 		*/
19864 		break;
19865 		}
19866 	    case XML_SCHEMA_TYPE_ALL:
19867 		break;
19868 	    case XML_SCHEMA_TYPE_GROUP:
19869 		break;
19870 	    default:
19871 		xmlSchemaInternalErr2(ACTXT_CAST pctxt,
19872 		    "xmlSchemaCheckElementDeclConsistent",
19873 		    "found unexpected term of type '%s' in content model",
19874 		    WXS_ITEM_TYPE_NAME(WXS_PARTICLE_TERM(cur)), NULL);
19875 		return(-1);
19876 	}
19877 	cur = (xmlSchemaParticlePtr) cur->next;
19878     }
19879 
19880 exit:
19881     return(ret);
19882 }
19883 #endif
19884 
19885 /**
19886  * xmlSchemaCheckElementDeclComponent
19887  * @item:  an schema element declaration/particle
19888  * @ctxt:  a schema parser context
19889  * @name:  the name of the attribute
19890  *
19891  * Validates the value constraints of an element declaration.
19892  * Adds substitution group members.
19893  */
19894 static void
xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,xmlSchemaParserCtxtPtr ctxt)19895 xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
19896 				   xmlSchemaParserCtxtPtr ctxt)
19897 {
19898     if (elemDecl == NULL)
19899 	return;
19900     if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
19901 	return;
19902     elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
19903     if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0) {
19904 	/*
19905 	* Adds substitution group members.
19906 	*/
19907 	xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
19908     }
19909 }
19910 
19911 /**
19912  * xmlSchemaResolveModelGroupParticleReferences:
19913  * @particle:  a particle component
19914  * @ctxt:  a parser context
19915  *
19916  * Resolves references of a model group's {particles} to
19917  * model group definitions and to element declarations.
19918  */
19919 static void
xmlSchemaResolveModelGroupParticleReferences(xmlSchemaParserCtxtPtr ctxt,xmlSchemaModelGroupPtr mg)19920 xmlSchemaResolveModelGroupParticleReferences(
19921     xmlSchemaParserCtxtPtr ctxt,
19922     xmlSchemaModelGroupPtr mg)
19923 {
19924     xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
19925     xmlSchemaQNameRefPtr ref;
19926     xmlSchemaBasicItemPtr refItem;
19927 
19928     /*
19929     * URGENT TODO: Test this.
19930     */
19931     while (particle != NULL) {
19932 	if ((WXS_PARTICLE_TERM(particle) == NULL) ||
19933 	    ((WXS_PARTICLE_TERM(particle))->type !=
19934 		XML_SCHEMA_EXTRA_QNAMEREF))
19935 	{
19936 	    goto next_particle;
19937 	}
19938 	ref = WXS_QNAME_CAST WXS_PARTICLE_TERM(particle);
19939 	/*
19940 	* Resolve the reference.
19941 	* NULL the {term} by default.
19942 	*/
19943 	particle->children = NULL;
19944 
19945 	refItem = xmlSchemaGetNamedComponent(ctxt->schema,
19946 	    ref->itemType, ref->name, ref->targetNamespace);
19947 	if (refItem == NULL) {
19948 	    xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
19949 		NULL, WXS_ITEM_NODE(particle), "ref", ref->name,
19950 		ref->targetNamespace, ref->itemType, NULL);
19951 	    /* TODO: remove the particle. */
19952 	    goto next_particle;
19953 	}
19954 	if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
19955 	    if (WXS_MODELGROUPDEF_MODEL(refItem) == NULL)
19956 		/* TODO: remove the particle. */
19957 		goto next_particle;
19958 	    /*
19959 	    * NOTE that we will assign the model group definition
19960 	    * itself to the "term" of the particle. This will ease
19961 	    * the check for circular model group definitions. After
19962 	    * that the "term" will be assigned the model group of the
19963 	    * model group definition.
19964 	    */
19965 	    if ((WXS_MODELGROUPDEF_MODEL(refItem))->type ==
19966 		    XML_SCHEMA_TYPE_ALL) {
19967 		/*
19968 		* SPEC cos-all-limited (1)
19969 		* SPEC cos-all-limited (1.2)
19970 		* "It appears only as the value of one or both of the
19971 		* following properties:"
19972 		* (1.1) "the {model group} property of a model group
19973 		*        definition."
19974 		* (1.2) "the {term} property of a particle [... of] the "
19975 		* {content type} of a complex type definition."
19976 		*/
19977 		xmlSchemaCustomErr(ACTXT_CAST ctxt,
19978 		    /* TODO: error code */
19979 		    XML_SCHEMAP_COS_ALL_LIMITED,
19980 		    WXS_ITEM_NODE(particle), NULL,
19981 		    "A model group definition is referenced, but "
19982 		    "it contains an 'all' model group, which "
19983 		    "cannot be contained by model groups",
19984 		    NULL, NULL);
19985 		/* TODO: remove the particle. */
19986 		goto next_particle;
19987 	    }
19988 	    particle->children = (xmlSchemaTreeItemPtr) refItem;
19989 	} else {
19990 	    /*
19991 	    * TODO: Are referenced element declarations the only
19992 	    * other components we expect here?
19993 	    */
19994 	    particle->children = (xmlSchemaTreeItemPtr) refItem;
19995 	}
19996 next_particle:
19997 	particle = WXS_PTC_CAST particle->next;
19998     }
19999 }
20000 
20001 static int
xmlSchemaAreValuesEqual(xmlSchemaValPtr x,xmlSchemaValPtr y)20002 xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
20003 		       xmlSchemaValPtr y)
20004 {
20005     xmlSchemaTypePtr tx, ty, ptx, pty;
20006     int ret;
20007 
20008     while (x != NULL) {
20009 	/* Same types. */
20010 	tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
20011 	ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
20012 	ptx = xmlSchemaGetPrimitiveType(tx);
20013 	pty = xmlSchemaGetPrimitiveType(ty);
20014 	/*
20015 	* (1) if a datatype T' is `derived` by `restriction` from an
20016 	* atomic datatype T then the `value space` of T' is a subset of
20017 	* the `value space` of T. */
20018 	/*
20019 	* (2) if datatypes T' and T'' are `derived` by `restriction`
20020 	* from a common atomic ancestor T then the `value space`s of T'
20021 	* and T'' may overlap.
20022 	*/
20023 	if (ptx != pty)
20024 	    return(0);
20025 	/*
20026 	* We assume computed values to be normalized, so do a fast
20027 	* string comparison for string based types.
20028 	*/
20029 	if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
20030 	    WXS_IS_ANY_SIMPLE_TYPE(ptx)) {
20031 	    if (! xmlStrEqual(
20032 		xmlSchemaValueGetAsString(x),
20033 		xmlSchemaValueGetAsString(y)))
20034 		return (0);
20035 	} else {
20036 	    ret = xmlSchemaCompareValuesWhtsp(
20037 		x, XML_SCHEMA_WHITESPACE_PRESERVE,
20038 		y, XML_SCHEMA_WHITESPACE_PRESERVE);
20039 	    if (ret == -2)
20040 		return(-1);
20041 	    if (ret != 0)
20042 		return(0);
20043 	}
20044 	/*
20045 	* Lists.
20046 	*/
20047 	x = xmlSchemaValueGetNext(x);
20048 	if (x != NULL) {
20049 	    y = xmlSchemaValueGetNext(y);
20050 	    if (y == NULL)
20051 		return (0);
20052 	} else if (xmlSchemaValueGetNext(y) != NULL)
20053 	    return (0);
20054 	else
20055 	    return (1);
20056     }
20057     return (0);
20058 }
20059 
20060 /**
20061  * xmlSchemaResolveAttrUseReferences:
20062  * @item:  an attribute use
20063  * @ctxt:  a parser context
20064  *
20065  * Resolves the referenced attribute declaration.
20066  */
20067 static int
xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,xmlSchemaParserCtxtPtr ctxt)20068 xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,
20069 				  xmlSchemaParserCtxtPtr ctxt)
20070 {
20071     if ((ctxt == NULL) || (ause == NULL))
20072 	return(-1);
20073     if ((ause->attrDecl == NULL) ||
20074 	(ause->attrDecl->type != XML_SCHEMA_EXTRA_QNAMEREF))
20075 	return(0);
20076 
20077     {
20078 	xmlSchemaQNameRefPtr ref = WXS_QNAME_CAST ause->attrDecl;
20079 
20080 	/*
20081 	* TODO: Evaluate, what errors could occur if the declaration is not
20082 	* found.
20083 	*/
20084 	ause->attrDecl = xmlSchemaGetAttributeDecl(ctxt->schema,
20085 	    ref->name, ref->targetNamespace);
20086         if (ause->attrDecl == NULL) {
20087 	    xmlSchemaPResCompAttrErr(ctxt,
20088 		XML_SCHEMAP_SRC_RESOLVE,
20089 		WXS_BASIC_CAST ause, ause->node,
20090 		"ref", ref->name, ref->targetNamespace,
20091 		XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20092             return(ctxt->err);;
20093         }
20094     }
20095     return(0);
20096 }
20097 
20098 /**
20099  * xmlSchemaCheckAttrUsePropsCorrect:
20100  * @ctxt:  a parser context
20101  * @use:  an attribute use
20102  *
20103  * Schema Component Constraint:
20104  * Attribute Use Correct (au-props-correct)
20105  *
20106  */
20107 static int
xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,xmlSchemaAttributeUsePtr use)20108 xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,
20109 			     xmlSchemaAttributeUsePtr use)
20110 {
20111     if ((ctxt == NULL) || (use == NULL))
20112 	return(-1);
20113     if ((use->defValue == NULL) || (WXS_ATTRUSE_DECL(use) == NULL) ||
20114 	((WXS_ATTRUSE_DECL(use))->type != XML_SCHEMA_TYPE_ATTRIBUTE))
20115 	return(0);
20116 
20117     /*
20118     * SPEC au-props-correct (1)
20119     * "The values of the properties of an attribute use must be as
20120     * described in the property tableau in The Attribute Use Schema
20121     * Component ($3.5.1), modulo the impact of Missing
20122     * Sub-components ($5.3)."
20123     */
20124 
20125     if (((WXS_ATTRUSE_DECL(use))->defValue != NULL) &&
20126 	((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMAS_ATTR_FIXED) &&
20127         ((use->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20128     {
20129 	xmlSchemaPCustomErr(ctxt,
20130 	    XML_SCHEMAP_AU_PROPS_CORRECT_2,
20131 	    WXS_BASIC_CAST use, NULL,
20132 	    "The attribute declaration has a 'fixed' value constraint "
20133 	    ", thus the attribute use must also have a 'fixed' value "
20134 	    "constraint",
20135 	    NULL);
20136 	return(ctxt->err);
20137     }
20138     /*
20139     * Compute and check the value constraint's value.
20140     */
20141     if ((use->defVal != NULL) && (WXS_ATTRUSE_TYPEDEF(use) != NULL)) {
20142 	int ret;
20143 	/*
20144 	* TODO: The spec seems to be missing a check of the
20145 	* value constraint of the attribute use. We will do it here.
20146 	*/
20147 	/*
20148 	* SPEC a-props-correct (3)
20149 	*/
20150 	if (xmlSchemaIsDerivedFromBuiltInType(
20151 	    WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
20152 	{
20153 	    xmlSchemaCustomErr(ACTXT_CAST ctxt,
20154 		XML_SCHEMAP_AU_PROPS_CORRECT,
20155 		NULL, WXS_BASIC_CAST use,
20156 		"Value constraints are not allowed if the type definition "
20157 		"is or is derived from xs:ID",
20158 		NULL, NULL);
20159 	    return(ctxt->err);
20160 	}
20161 
20162 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST ctxt,
20163 	    use->node, WXS_ATTRUSE_TYPEDEF(use),
20164 	    use->defValue, &(use->defVal),
20165 	    1, 1, 0);
20166 	if (ret != 0) {
20167 	    if (ret < 0) {
20168 		PERROR_INT2("xmlSchemaCheckAttrUsePropsCorrect",
20169 		    "calling xmlSchemaVCheckCVCSimpleType()");
20170 		return(-1);
20171 	    }
20172 	    xmlSchemaCustomErr(ACTXT_CAST ctxt,
20173 		XML_SCHEMAP_AU_PROPS_CORRECT,
20174 		NULL, WXS_BASIC_CAST use,
20175 		"The value of the value constraint is not valid",
20176 		NULL, NULL);
20177 	    return(ctxt->err);
20178 	}
20179     }
20180     /*
20181     * SPEC au-props-correct (2)
20182     * "If the {attribute declaration} has a fixed
20183     * {value constraint}, then if the attribute use itself has a
20184     * {value constraint}, it must also be fixed and its value must match
20185     * that of the {attribute declaration}'s {value constraint}."
20186     */
20187     if (((WXS_ATTRUSE_DECL(use))->defVal != NULL) &&
20188 	(((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20189     {
20190 	if (! xmlSchemaAreValuesEqual(use->defVal,
20191 		(WXS_ATTRUSE_DECL(use))->defVal))
20192 	{
20193 	    xmlSchemaPCustomErr(ctxt,
20194 		XML_SCHEMAP_AU_PROPS_CORRECT_2,
20195 		WXS_BASIC_CAST use, NULL,
20196 		"The 'fixed' value constraint of the attribute use "
20197 		"must match the attribute declaration's value "
20198 		"constraint '%s'",
20199 		(WXS_ATTRUSE_DECL(use))->defValue);
20200 	}
20201 	return(ctxt->err);
20202     }
20203     return(0);
20204 }
20205 
20206 
20207 
20208 
20209 /**
20210  * xmlSchemaResolveAttrTypeReferences:
20211  * @item:  an attribute declaration
20212  * @ctxt:  a parser context
20213  *
20214  * Resolves the referenced type definition component.
20215  */
20216 static int
xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,xmlSchemaParserCtxtPtr ctxt)20217 xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,
20218 				   xmlSchemaParserCtxtPtr ctxt)
20219 {
20220     /*
20221     * The simple type definition corresponding to the <simpleType> element
20222     * information item in the [children], if present, otherwise the simple
20223     * type definition `resolved` to by the `actual value` of the type
20224     * [attribute], if present, otherwise the `simple ur-type definition`.
20225     */
20226     if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
20227 	return(0);
20228     item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
20229     if (item->subtypes != NULL)
20230         return(0);
20231     if (item->typeName != NULL) {
20232         xmlSchemaTypePtr type;
20233 
20234 	type = xmlSchemaGetType(ctxt->schema, item->typeName,
20235 	    item->typeNs);
20236 	if ((type == NULL) || (! WXS_IS_SIMPLE(type))) {
20237 	    xmlSchemaPResCompAttrErr(ctxt,
20238 		XML_SCHEMAP_SRC_RESOLVE,
20239 		WXS_BASIC_CAST item, item->node,
20240 		"type", item->typeName, item->typeNs,
20241 		XML_SCHEMA_TYPE_SIMPLE, NULL);
20242 	    return(ctxt->err);
20243 	} else
20244 	    item->subtypes = type;
20245 
20246     } else {
20247 	/*
20248 	* The type defaults to the xs:anySimpleType.
20249 	*/
20250 	item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
20251     }
20252     return(0);
20253 }
20254 
20255 /**
20256  * xmlSchemaResolveIDCKeyReferences:
20257  * @idc:  the identity-constraint definition
20258  * @ctxt:  the schema parser context
20259  * @name:  the attribute name
20260  *
20261  * Resolve keyRef references to key/unique IDCs.
20262  * Schema Component Constraint:
20263  *   Identity-constraint Definition Properties Correct (c-props-correct)
20264  */
20265 static int
xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,xmlSchemaParserCtxtPtr pctxt)20266 xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,
20267 			  xmlSchemaParserCtxtPtr pctxt)
20268 {
20269     if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
20270         return(0);
20271     if (idc->ref->name != NULL) {
20272 	idc->ref->item = (xmlSchemaBasicItemPtr)
20273 	    xmlSchemaGetIDC(pctxt->schema, idc->ref->name,
20274 		idc->ref->targetNamespace);
20275         if (idc->ref->item == NULL) {
20276 	    /*
20277 	    * TODO: It is actually not an error to fail to resolve
20278 	    * at this stage. BUT we need to be that strict!
20279 	    */
20280 	    xmlSchemaPResCompAttrErr(pctxt,
20281 		XML_SCHEMAP_SRC_RESOLVE,
20282 		WXS_BASIC_CAST idc, idc->node,
20283 		"refer", idc->ref->name,
20284 		idc->ref->targetNamespace,
20285 		XML_SCHEMA_TYPE_IDC_KEY, NULL);
20286             return(pctxt->err);
20287 	} else if (idc->ref->item->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20288 	    /*
20289 	    * SPEC c-props-correct (1)
20290 	    */
20291 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20292 		XML_SCHEMAP_C_PROPS_CORRECT,
20293 		NULL, WXS_BASIC_CAST idc,
20294 		"The keyref references a keyref",
20295 		NULL, NULL);
20296 	    idc->ref->item = NULL;
20297 	    return(pctxt->err);
20298 	} else {
20299 	    if (idc->nbFields !=
20300 		((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
20301 		xmlChar *str = NULL;
20302 		xmlSchemaIDCPtr refer;
20303 
20304 		refer = (xmlSchemaIDCPtr) idc->ref->item;
20305 		/*
20306 		* SPEC c-props-correct(2)
20307 		* "If the {identity-constraint category} is keyref,
20308 		* the cardinality of the {fields} must equal that of
20309 		* the {fields} of the {referenced key}.
20310 		*/
20311 		xmlSchemaCustomErr(ACTXT_CAST pctxt,
20312 		    XML_SCHEMAP_C_PROPS_CORRECT,
20313 		    NULL, WXS_BASIC_CAST idc,
20314 		    "The cardinality of the keyref differs from the "
20315 		    "cardinality of the referenced key/unique '%s'",
20316 		    xmlSchemaFormatQName(&str, refer->targetNamespace,
20317 			refer->name),
20318 		    NULL);
20319 		FREE_AND_NULL(str)
20320 		return(pctxt->err);
20321 	    }
20322 	}
20323     }
20324     return(0);
20325 }
20326 
20327 static int
xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,xmlSchemaParserCtxtPtr pctxt)20328 xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,
20329 				       xmlSchemaParserCtxtPtr pctxt)
20330 {
20331     if (xmlSchemaGetAttributeDecl(pctxt->schema, prohib->name,
20332 	prohib->targetNamespace) == NULL) {
20333 
20334 	xmlSchemaPResCompAttrErr(pctxt,
20335 	    XML_SCHEMAP_SRC_RESOLVE,
20336 	    NULL, prohib->node,
20337 	    "ref", prohib->name, prohib->targetNamespace,
20338 	    XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20339 	return(XML_SCHEMAP_SRC_RESOLVE);
20340     }
20341     return(0);
20342 }
20343 
20344 #define WXS_REDEFINED_TYPE(c) \
20345 (((xmlSchemaTypePtr) item)->flags & XML_SCHEMAS_TYPE_REDEFINED)
20346 
20347 #define WXS_REDEFINED_MODEL_GROUP_DEF(c) \
20348 (((xmlSchemaModelGroupDefPtr) item)->flags & XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20349 
20350 #define WXS_REDEFINED_ATTR_GROUP(c) \
20351 (((xmlSchemaAttributeGroupPtr) item)->flags & XML_SCHEMAS_ATTRGROUP_REDEFINED)
20352 
20353 static int
xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)20354 xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)
20355 {
20356     int err = 0;
20357     xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20358     xmlSchemaBasicItemPtr prev, item;
20359     int wasRedefined;
20360 
20361     if (redef == NULL)
20362 	return(0);
20363 
20364     do {
20365 	item = redef->item;
20366 	/*
20367 	* First try to locate the redefined component in the
20368 	* schema graph starting with the redefined schema.
20369 	* NOTE: According to this schema bug entry:
20370 	*   http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005OctDec/0019.html
20371 	*   it's not clear if the referenced component needs to originate
20372 	*   from the <redefine>d schema _document_ or the schema; the latter
20373 	*   would include all imported and included sub-schemas of the
20374 	*   <redefine>d schema. Currently the latter approach is used.
20375 	*   SUPPLEMENT: It seems that the WG moves towards the latter
20376 	*   approach, so we are doing it right.
20377 	*
20378 	*/
20379 	prev = xmlSchemaFindRedefCompInGraph(
20380 	    redef->targetBucket, item->type,
20381 	    redef->refName, redef->refTargetNs);
20382 	if (prev == NULL) {
20383 	    xmlChar *str = NULL;
20384 	    xmlNodePtr node;
20385 
20386 	    /*
20387 	    * SPEC src-redefine:
20388 	    * (6.2.1) "The `actual value` of its own name attribute plus
20389 	    * target namespace must successfully `resolve` to a model
20390 	    * group definition in I."
20391 	    * (7.2.1) "The `actual value` of its own name attribute plus
20392 	    * target namespace must successfully `resolve` to an attribute
20393 	    * group definition in I."
20394 
20395 	    *
20396 	    * Note that, if we are redefining with the use of references
20397 	    * to components, the spec assumes the src-resolve to be used;
20398 	    * but this won't assure that we search only *inside* the
20399 	    * redefined schema.
20400 	    */
20401 	    if (redef->reference)
20402 		node = WXS_ITEM_NODE(redef->reference);
20403 	    else
20404 		node = WXS_ITEM_NODE(item);
20405 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20406 		/*
20407 		* TODO: error code.
20408 		* Probably XML_SCHEMAP_SRC_RESOLVE, if this is using the
20409 		* reference kind.
20410 		*/
20411 		XML_SCHEMAP_SRC_REDEFINE, node, NULL,
20412 		"The %s '%s' to be redefined could not be found in "
20413 		"the redefined schema",
20414 		WXS_ITEM_TYPE_NAME(item),
20415 		xmlSchemaFormatQName(&str, redef->refTargetNs,
20416 		    redef->refName));
20417 	    FREE_AND_NULL(str);
20418 	    err = pctxt->err;
20419 	    redef = redef->next;
20420 	    continue;
20421 	}
20422 	/*
20423 	* TODO: Obtaining and setting the redefinition state is really
20424 	* clumsy.
20425 	*/
20426 	wasRedefined = 0;
20427 	switch (item->type) {
20428 	    case XML_SCHEMA_TYPE_COMPLEX:
20429 	    case XML_SCHEMA_TYPE_SIMPLE:
20430 		if ((WXS_TYPE_CAST prev)->flags &
20431 		    XML_SCHEMAS_TYPE_REDEFINED)
20432 		{
20433 		    wasRedefined = 1;
20434 		    break;
20435 		}
20436 		/* Mark it as redefined. */
20437 		(WXS_TYPE_CAST prev)->flags |= XML_SCHEMAS_TYPE_REDEFINED;
20438 		/*
20439 		* Assign the redefined type to the
20440 		* base type of the redefining type.
20441 		* TODO: How
20442 		*/
20443 		((xmlSchemaTypePtr) item)->baseType =
20444 		    (xmlSchemaTypePtr) prev;
20445 		break;
20446 	    case XML_SCHEMA_TYPE_GROUP:
20447 		if ((WXS_MODEL_GROUPDEF_CAST prev)->flags &
20448 		    XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20449 		{
20450 		    wasRedefined = 1;
20451 		    break;
20452 		}
20453 		/* Mark it as redefined. */
20454 		(WXS_MODEL_GROUPDEF_CAST prev)->flags |=
20455 		    XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED;
20456 		if (redef->reference != NULL) {
20457 		    /*
20458 		    * Overwrite the QName-reference with the
20459 		    * referenced model group def.
20460 		    */
20461 		    (WXS_PTC_CAST redef->reference)->children =
20462 			WXS_TREE_CAST prev;
20463 		}
20464 		redef->target = prev;
20465 		break;
20466 	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20467 		if ((WXS_ATTR_GROUP_CAST prev)->flags &
20468 		    XML_SCHEMAS_ATTRGROUP_REDEFINED)
20469 		{
20470 		    wasRedefined = 1;
20471 		    break;
20472 		}
20473 		(WXS_ATTR_GROUP_CAST prev)->flags |=
20474 		    XML_SCHEMAS_ATTRGROUP_REDEFINED;
20475 		if (redef->reference != NULL) {
20476 		    /*
20477 		    * Assign the redefined attribute group to the
20478 		    * QName-reference component.
20479 		    * This is the easy case, since we will just
20480 		    * expand the redefined group.
20481 		    */
20482 		    (WXS_QNAME_CAST redef->reference)->item = prev;
20483 		    redef->target = NULL;
20484 		} else {
20485 		    /*
20486 		    * This is the complicated case: we need
20487 		    * to apply src-redefine (7.2.2) at a later
20488 		    * stage, i.e. when attribute group references
20489 		    * have been expanded and simple types have
20490 		    * been fixed.
20491 		    */
20492 		    redef->target = prev;
20493 		}
20494 		break;
20495 	    default:
20496 		PERROR_INT("xmlSchemaResolveRedefReferences",
20497 		    "Unexpected redefined component type");
20498 		return(-1);
20499 	}
20500 	if (wasRedefined) {
20501 	    xmlChar *str = NULL;
20502 	    xmlNodePtr node;
20503 
20504 	    if (redef->reference)
20505 		node = WXS_ITEM_NODE(redef->reference);
20506 	    else
20507 		node = WXS_ITEM_NODE(redef->item);
20508 
20509 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20510 		/* TODO: error code. */
20511 		XML_SCHEMAP_SRC_REDEFINE,
20512 		node, NULL,
20513 		"The referenced %s was already redefined. Multiple "
20514 		"redefinition of the same component is not supported",
20515 		xmlSchemaGetComponentDesignation(&str, prev),
20516 		NULL);
20517 	    FREE_AND_NULL(str)
20518 	    err = pctxt->err;
20519 	    redef = redef->next;
20520 	    continue;
20521 	}
20522 	redef = redef->next;
20523     } while (redef != NULL);
20524 
20525     return(err);
20526 }
20527 
20528 static int
xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)20529 xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)
20530 {
20531     int err = 0;
20532     xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20533     xmlSchemaBasicItemPtr item;
20534 
20535     if (redef == NULL)
20536 	return(0);
20537 
20538     do {
20539 	if (redef->target == NULL) {
20540 	    redef = redef->next;
20541 	    continue;
20542 	}
20543 	item = redef->item;
20544 
20545 	switch (item->type) {
20546 	    case XML_SCHEMA_TYPE_SIMPLE:
20547 	    case XML_SCHEMA_TYPE_COMPLEX:
20548 		/*
20549 		* Since the spec wants the {name} of the redefined
20550 		* type to be 'absent', we'll NULL it.
20551 		*/
20552 		(WXS_TYPE_CAST redef->target)->name = NULL;
20553 
20554 		/*
20555 		* TODO: Seems like there's nothing more to do. The normal
20556 		* inheritance mechanism is used. But not 100% sure.
20557 		*/
20558 		break;
20559 	    case XML_SCHEMA_TYPE_GROUP:
20560 		/*
20561 		* URGENT TODO:
20562 		* SPEC src-redefine:
20563 		* (6.2.2) "The {model group} of the model group definition
20564 		* which corresponds to it per XML Representation of Model
20565 		* Group Definition Schema Components ($3.7.2) must be a
20566 		* `valid restriction` of the {model group} of that model
20567 		* group definition in I, as defined in Particle Valid
20568 		* (Restriction) ($3.9.6)."
20569 		*/
20570 		break;
20571 	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20572 		/*
20573 		* SPEC src-redefine:
20574 		* (7.2.2) "The {attribute uses} and {attribute wildcard} of
20575 		* the attribute group definition which corresponds to it
20576 		* per XML Representation of Attribute Group Definition Schema
20577 		* Components ($3.6.2) must be `valid restrictions` of the
20578 		* {attribute uses} and {attribute wildcard} of that attribute
20579 		* group definition in I, as defined in clause 2, clause 3 and
20580 		* clause 4 of Derivation Valid (Restriction, Complex)
20581 		* ($3.4.6) (where references to the base type definition are
20582 		* understood as references to the attribute group definition
20583 		* in I)."
20584 		*/
20585 		err = xmlSchemaCheckDerivationOKRestriction2to4(pctxt,
20586 		    XML_SCHEMA_ACTION_REDEFINE,
20587 		    item, redef->target,
20588 		    (WXS_ATTR_GROUP_CAST item)->attrUses,
20589 		    (WXS_ATTR_GROUP_CAST redef->target)->attrUses,
20590 		    (WXS_ATTR_GROUP_CAST item)->attributeWildcard,
20591 		    (WXS_ATTR_GROUP_CAST redef->target)->attributeWildcard);
20592 		if (err == -1)
20593 		    return(-1);
20594 		break;
20595 	    default:
20596 		break;
20597 	}
20598 	redef = redef->next;
20599     } while (redef != NULL);
20600     return(0);
20601 }
20602 
20603 
20604 static int
xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBucketPtr bucket)20605 xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,
20606 		       xmlSchemaBucketPtr bucket)
20607 {
20608     xmlSchemaBasicItemPtr item;
20609     int err;
20610     xmlHashTablePtr *table;
20611     const xmlChar *name;
20612     int i;
20613 
20614 #define WXS_GET_GLOBAL_HASH(c, slot) { \
20615     if (WXS_IS_BUCKET_IMPMAIN((c)->type)) \
20616 	table = &(WXS_IMPBUCKET((c))->schema->slot); \
20617     else \
20618 	table = &(WXS_INCBUCKET((c))->ownerImport->schema->slot); }
20619 
20620     /*
20621     * Add global components to the schema's hash tables.
20622     * This is the place where duplicate components will be
20623     * detected.
20624     * TODO: I think normally we should support imports of the
20625     *   same namespace from multiple locations. We don't do currently,
20626     *   but if we do then according to:
20627     *   http://www.w3.org/Bugs/Public/show_bug.cgi?id=2224
20628     *   we would need, if imported directly, to import redefined
20629     *   components as well to be able to catch clashing components.
20630     *   (I hope I'll still know what this means after some months :-()
20631     */
20632     if (bucket == NULL)
20633 	return(-1);
20634     if (bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED)
20635 	return(0);
20636     bucket->flags |= XML_SCHEMA_BUCKET_COMPS_ADDED;
20637 
20638     for (i = 0; i < bucket->globals->nbItems; i++) {
20639 	item = bucket->globals->items[i];
20640 	table = NULL;
20641 	switch (item->type) {
20642 	    case XML_SCHEMA_TYPE_COMPLEX:
20643 	    case XML_SCHEMA_TYPE_SIMPLE:
20644 		if (WXS_REDEFINED_TYPE(item))
20645 		    continue;
20646 		name = (WXS_TYPE_CAST item)->name;
20647 		WXS_GET_GLOBAL_HASH(bucket, typeDecl)
20648 		break;
20649 	    case XML_SCHEMA_TYPE_ELEMENT:
20650 		name = (WXS_ELEM_CAST item)->name;
20651 		WXS_GET_GLOBAL_HASH(bucket, elemDecl)
20652 		break;
20653 	    case XML_SCHEMA_TYPE_ATTRIBUTE:
20654 		name = (WXS_ATTR_CAST item)->name;
20655 		WXS_GET_GLOBAL_HASH(bucket, attrDecl)
20656 		break;
20657 	    case XML_SCHEMA_TYPE_GROUP:
20658 		if (WXS_REDEFINED_MODEL_GROUP_DEF(item))
20659 		    continue;
20660 		name = (WXS_MODEL_GROUPDEF_CAST item)->name;
20661 		WXS_GET_GLOBAL_HASH(bucket, groupDecl)
20662 		break;
20663 	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20664 		if (WXS_REDEFINED_ATTR_GROUP(item))
20665 		    continue;
20666 		name = (WXS_ATTR_GROUP_CAST item)->name;
20667 		WXS_GET_GLOBAL_HASH(bucket, attrgrpDecl)
20668 		break;
20669 	    case XML_SCHEMA_TYPE_IDC_KEY:
20670 	    case XML_SCHEMA_TYPE_IDC_UNIQUE:
20671 	    case XML_SCHEMA_TYPE_IDC_KEYREF:
20672 		name = (WXS_IDC_CAST item)->name;
20673 		WXS_GET_GLOBAL_HASH(bucket, idcDef)
20674 		break;
20675 	    case XML_SCHEMA_TYPE_NOTATION:
20676 		name = ((xmlSchemaNotationPtr) item)->name;
20677 		WXS_GET_GLOBAL_HASH(bucket, notaDecl)
20678 		break;
20679 	    default:
20680 		PERROR_INT("xmlSchemaAddComponents",
20681 		    "Unexpected global component type");
20682 		continue;
20683 	}
20684 	if (*table == NULL) {
20685 	    *table = xmlHashCreateDict(10, pctxt->dict);
20686 	    if (*table == NULL) {
20687 		PERROR_INT("xmlSchemaAddComponents",
20688 		    "failed to create a component hash table");
20689 		return(-1);
20690 	    }
20691 	}
20692 	err = xmlHashAddEntry(*table, name, item);
20693 	if (err != 0) {
20694 	    xmlChar *str = NULL;
20695 
20696 	    xmlSchemaCustomErr(ACTXT_CAST pctxt,
20697 		XML_SCHEMAP_REDEFINED_TYPE,
20698 		WXS_ITEM_NODE(item),
20699 		WXS_BASIC_CAST item,
20700 		"A global %s '%s' does already exist",
20701 		WXS_ITEM_TYPE_NAME(item),
20702 		xmlSchemaGetComponentQName(&str, item));
20703 	    FREE_AND_NULL(str);
20704 	}
20705     }
20706     /*
20707     * Process imported/included schemas.
20708     */
20709     if (bucket->relations != NULL) {
20710 	xmlSchemaSchemaRelationPtr rel = bucket->relations;
20711 	do {
20712 	    if ((rel->bucket != NULL) &&
20713 		((rel->bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED) == 0)) {
20714 		if (xmlSchemaAddComponents(pctxt, rel->bucket) == -1)
20715 		    return(-1);
20716 	    }
20717 	    rel = rel->next;
20718 	} while (rel != NULL);
20719     }
20720     return(0);
20721 }
20722 
20723 static int
xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt,xmlSchemaBucketPtr rootBucket)20724 xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt,
20725 			 xmlSchemaBucketPtr rootBucket)
20726 {
20727     xmlSchemaConstructionCtxtPtr con = pctxt->constructor;
20728     xmlSchemaTreeItemPtr item, *items;
20729     int nbItems, i, ret = 0;
20730     xmlSchemaBucketPtr oldbucket = con->bucket;
20731     xmlSchemaElementPtr elemDecl;
20732 
20733 #define FIXHFAILURE if (pctxt->err == XML_SCHEMAP_INTERNAL) goto exit_failure;
20734 
20735     if ((con->pending == NULL) ||
20736 	(con->pending->nbItems == 0))
20737 	return(0);
20738 
20739     /*
20740     * Since xmlSchemaFixupComplexType() will create new particles
20741     * (local components), and those particle components need a bucket
20742     * on the constructor, we'll assure here that the constructor has
20743     * a bucket.
20744     * TODO: Think about storing locals _only_ on the main bucket.
20745     */
20746     if (con->bucket == NULL)
20747 	con->bucket = rootBucket;
20748 
20749     /* TODO:
20750     * SPEC (src-redefine):
20751     * (6.2) "If it has no such self-reference, then all of the
20752     * following must be true:"
20753 
20754     * (6.2.2) The {model group} of the model group definition which
20755     * corresponds to it per XML Representation of Model Group
20756     * Definition Schema Components ($3.7.2) must be a `valid
20757     * restriction` of the {model group} of that model group definition
20758     * in I, as defined in Particle Valid (Restriction) ($3.9.6)."
20759     */
20760     xmlSchemaCheckSRCRedefineFirst(pctxt);
20761 
20762     /*
20763     * Add global components to the schemata's hash tables.
20764     */
20765     xmlSchemaAddComponents(pctxt, rootBucket);
20766 
20767     pctxt->ctxtType = NULL;
20768     items = (xmlSchemaTreeItemPtr *) con->pending->items;
20769     nbItems = con->pending->nbItems;
20770     /*
20771     * Now that we have parsed *all* the schema document(s) and converted
20772     * them to schema components, we can resolve references, apply component
20773     * constraints, create the FSA from the content model, etc.
20774     */
20775     /*
20776     * Resolve references of..
20777     *
20778     * 1. element declarations:
20779     *   - the type definition
20780     *   - the substitution group affiliation
20781     * 2. simple/complex types:
20782     *   - the base type definition
20783     *   - the memberTypes of union types
20784     *   - the itemType of list types
20785     * 3. attributes declarations and attribute uses:
20786     *   - the type definition
20787     *   - if an attribute use, then the attribute declaration
20788     * 4. attribute group references:
20789     *   - the attribute group definition
20790     * 5. particles:
20791     *   - the term of the particle (e.g. a model group)
20792     * 6. IDC key-references:
20793     *   - the referenced IDC 'key' or 'unique' definition
20794     * 7. Attribute prohibitions which had a "ref" attribute.
20795     */
20796     for (i = 0; i < nbItems; i++) {
20797 	item = items[i];
20798 	switch (item->type) {
20799 	    case XML_SCHEMA_TYPE_ELEMENT:
20800 		xmlSchemaResolveElementReferences(
20801 		    (xmlSchemaElementPtr) item, pctxt);
20802 		FIXHFAILURE;
20803 		break;
20804 	    case XML_SCHEMA_TYPE_COMPLEX:
20805 	    case XML_SCHEMA_TYPE_SIMPLE:
20806 		xmlSchemaResolveTypeReferences(
20807 		    (xmlSchemaTypePtr) item, pctxt);
20808 		FIXHFAILURE;
20809 		break;
20810 	    case XML_SCHEMA_TYPE_ATTRIBUTE:
20811 		xmlSchemaResolveAttrTypeReferences(
20812 		    (xmlSchemaAttributePtr) item, pctxt);
20813 		FIXHFAILURE;
20814 		break;
20815 	    case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
20816 		xmlSchemaResolveAttrUseReferences(
20817 		    (xmlSchemaAttributeUsePtr) item, pctxt);
20818 		FIXHFAILURE;
20819 		break;
20820 	    case XML_SCHEMA_EXTRA_QNAMEREF:
20821 		if ((WXS_QNAME_CAST item)->itemType ==
20822 		    XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
20823 		{
20824 		    xmlSchemaResolveAttrGroupReferences(
20825 			WXS_QNAME_CAST item, pctxt);
20826 		}
20827 		FIXHFAILURE;
20828 		break;
20829 	    case XML_SCHEMA_TYPE_SEQUENCE:
20830 	    case XML_SCHEMA_TYPE_CHOICE:
20831 	    case XML_SCHEMA_TYPE_ALL:
20832 		xmlSchemaResolveModelGroupParticleReferences(pctxt,
20833 		    WXS_MODEL_GROUP_CAST item);
20834 		FIXHFAILURE;
20835 		break;
20836 	    case XML_SCHEMA_TYPE_IDC_KEY:
20837 	    case XML_SCHEMA_TYPE_IDC_UNIQUE:
20838 	    case XML_SCHEMA_TYPE_IDC_KEYREF:
20839 		xmlSchemaResolveIDCKeyReferences(
20840 		    (xmlSchemaIDCPtr) item, pctxt);
20841 		FIXHFAILURE;
20842 		break;
20843 	    case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
20844 		/*
20845 		* Handle attribute prohibition which had a
20846 		* "ref" attribute.
20847 		*/
20848 		xmlSchemaResolveAttrUseProhibReferences(
20849 		    WXS_ATTR_PROHIB_CAST item, pctxt);
20850 		FIXHFAILURE;
20851 		break;
20852 	    default:
20853 		break;
20854 	}
20855     }
20856     if (pctxt->nberrors != 0)
20857 	goto exit_error;
20858 
20859     /*
20860     * Now that all references are resolved we
20861     * can check for circularity of...
20862     * 1. the base axis of type definitions
20863     * 2. nested model group definitions
20864     * 3. nested attribute group definitions
20865     * TODO: check for circular substitution groups.
20866     */
20867     for (i = 0; i < nbItems; i++) {
20868 	item = items[i];
20869 	/*
20870 	* Let's better stop on the first error here.
20871 	*/
20872 	switch (item->type) {
20873 	    case XML_SCHEMA_TYPE_COMPLEX:
20874 	    case XML_SCHEMA_TYPE_SIMPLE:
20875 		xmlSchemaCheckTypeDefCircular(
20876 		    (xmlSchemaTypePtr) item, pctxt);
20877 		FIXHFAILURE;
20878 		if (pctxt->nberrors != 0)
20879 		    goto exit_error;
20880 		break;
20881 	    case XML_SCHEMA_TYPE_GROUP:
20882 		xmlSchemaCheckGroupDefCircular(
20883 		    (xmlSchemaModelGroupDefPtr) item, pctxt);
20884 		FIXHFAILURE;
20885 		if (pctxt->nberrors != 0)
20886 		    goto exit_error;
20887 		break;
20888 	    case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20889 		xmlSchemaCheckAttrGroupCircular(
20890 		    (xmlSchemaAttributeGroupPtr) item, pctxt);
20891 		FIXHFAILURE;
20892 		if (pctxt->nberrors != 0)
20893 		    goto exit_error;
20894 		break;
20895 	    default:
20896 		break;
20897 	}
20898     }
20899     if (pctxt->nberrors != 0)
20900 	goto exit_error;
20901     /*
20902     * Model group definition references:
20903     * Such a reference is reflected by a particle at the component
20904     * level. Until now the 'term' of such particles pointed
20905     * to the model group definition; this was done, in order to
20906     * ease circularity checks. Now we need to set the 'term' of
20907     * such particles to the model group of the model group definition.
20908     */
20909     for (i = 0; i < nbItems; i++) {
20910 	item = items[i];
20911 	switch (item->type) {
20912 	    case XML_SCHEMA_TYPE_SEQUENCE:
20913 	    case XML_SCHEMA_TYPE_CHOICE:
20914 		xmlSchemaModelGroupToModelGroupDefFixup(pctxt,
20915 		    WXS_MODEL_GROUP_CAST item);
20916 		break;
20917 	    default:
20918 		break;
20919 	}
20920     }
20921     if (pctxt->nberrors != 0)
20922 	goto exit_error;
20923     /*
20924     * Expand attribute group references of attribute group definitions.
20925     */
20926     for (i = 0; i < nbItems; i++) {
20927 	item = items[i];
20928 	switch (item->type) {
20929             case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20930 		if ((! WXS_ATTR_GROUP_EXPANDED(item)) &&
20931 		    WXS_ATTR_GROUP_HAS_REFS(item))
20932 		{
20933 		    xmlSchemaAttributeGroupExpandRefs(pctxt,
20934 			WXS_ATTR_GROUP_CAST item);
20935 		    FIXHFAILURE;
20936 		}
20937 		break;
20938 	    default:
20939 		break;
20940 	}
20941     }
20942     if (pctxt->nberrors != 0)
20943 	goto exit_error;
20944     /*
20945     * First compute the variety of simple types. This is needed as
20946     * a separate step, since otherwise we won't be able to detect
20947     * circular union types in all cases.
20948     */
20949     for (i = 0; i < nbItems; i++) {
20950 	item = items[i];
20951 	switch (item->type) {
20952             case XML_SCHEMA_TYPE_SIMPLE:
20953 		if (WXS_IS_TYPE_NOT_FIXED_1((xmlSchemaTypePtr) item)) {
20954 		    xmlSchemaFixupSimpleTypeStageOne(pctxt,
20955 			(xmlSchemaTypePtr) item);
20956 		    FIXHFAILURE;
20957 		}
20958 		break;
20959 	    default:
20960 		break;
20961 	}
20962     }
20963     if (pctxt->nberrors != 0)
20964 	goto exit_error;
20965     /*
20966     * Detect circular union types. Note that this needs the variety to
20967     * be already computed.
20968     */
20969     for (i = 0; i < nbItems; i++) {
20970 	item = items[i];
20971 	switch (item->type) {
20972             case XML_SCHEMA_TYPE_SIMPLE:
20973 		if (((xmlSchemaTypePtr) item)->memberTypes != NULL) {
20974 		    xmlSchemaCheckUnionTypeDefCircular(pctxt,
20975 			(xmlSchemaTypePtr) item);
20976 		    FIXHFAILURE;
20977 		}
20978 		break;
20979 	    default:
20980 		break;
20981 	}
20982     }
20983     if (pctxt->nberrors != 0)
20984 	goto exit_error;
20985 
20986     /*
20987     * Do the complete type fixup for simple types.
20988     */
20989     for (i = 0; i < nbItems; i++) {
20990 	item = items[i];
20991 	switch (item->type) {
20992             case XML_SCHEMA_TYPE_SIMPLE:
20993 		if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
20994 		    xmlSchemaFixupSimpleTypeStageTwo(pctxt, WXS_TYPE_CAST item);
20995 		    FIXHFAILURE;
20996 		}
20997 		break;
20998 	    default:
20999 		break;
21000 	}
21001     }
21002     if (pctxt->nberrors != 0)
21003 	goto exit_error;
21004     /*
21005     * At this point we need build and check all simple types.
21006     */
21007     /*
21008     * Apply constraints for attribute declarations.
21009     */
21010     for (i = 0; i < nbItems; i++) {
21011 	item = items[i];
21012 	switch (item->type) {
21013 	    case XML_SCHEMA_TYPE_ATTRIBUTE:
21014 		xmlSchemaCheckAttrPropsCorrect(pctxt, WXS_ATTR_CAST item);
21015 		FIXHFAILURE;
21016 		break;
21017 	    default:
21018 		break;
21019 	}
21020     }
21021     if (pctxt->nberrors != 0)
21022 	goto exit_error;
21023     /*
21024     * Apply constraints for attribute uses.
21025     */
21026     for (i = 0; i < nbItems; i++) {
21027 	item = items[i];
21028 	switch (item->type) {
21029 	    case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
21030 		if (((xmlSchemaAttributeUsePtr)item)->defValue != NULL) {
21031 		    xmlSchemaCheckAttrUsePropsCorrect(pctxt,
21032 			WXS_ATTR_USE_CAST item);
21033 		    FIXHFAILURE;
21034 		}
21035 		break;
21036 	    default:
21037 		break;
21038 	}
21039     }
21040     if (pctxt->nberrors != 0)
21041 	goto exit_error;
21042 
21043     /*
21044     * Apply constraints for attribute group definitions.
21045     */
21046     for (i = 0; i < nbItems; i++) {
21047 	item = items[i];
21048 	switch (item->type) {
21049 	case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21050 	    if (( (WXS_ATTR_GROUP_CAST item)->attrUses != NULL) &&
21051 		( (WXS_LIST_CAST (WXS_ATTR_GROUP_CAST item)->attrUses)->nbItems > 1))
21052 	    {
21053 		xmlSchemaCheckAGPropsCorrect(pctxt, WXS_ATTR_GROUP_CAST item);
21054 		FIXHFAILURE;
21055 	    }
21056 	    break;
21057 	default:
21058 	    break;
21059 	}
21060     }
21061     if (pctxt->nberrors != 0)
21062 	goto exit_error;
21063 
21064     /*
21065     * Apply constraints for redefinitions.
21066     */
21067     if (WXS_CONSTRUCTOR(pctxt)->redefs != NULL)
21068 	xmlSchemaCheckSRCRedefineSecond(pctxt);
21069     if (pctxt->nberrors != 0)
21070 	goto exit_error;
21071 
21072     /*
21073     * Complex types are built and checked.
21074     */
21075     for (i = 0; i < nbItems; i++) {
21076 	item = con->pending->items[i];
21077 	switch (item->type) {
21078 	    case XML_SCHEMA_TYPE_COMPLEX:
21079 		if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21080 		    xmlSchemaFixupComplexType(pctxt, WXS_TYPE_CAST item);
21081 		    FIXHFAILURE;
21082 		}
21083 		break;
21084 	    default:
21085 		break;
21086 	}
21087     }
21088     if (pctxt->nberrors != 0)
21089 	goto exit_error;
21090 
21091     /*
21092     * The list could have changed, since xmlSchemaFixupComplexType()
21093     * will create particles and model groups in some cases.
21094     */
21095     items = (xmlSchemaTreeItemPtr *) con->pending->items;
21096     nbItems = con->pending->nbItems;
21097 
21098     /*
21099     * Apply some constraints for element declarations.
21100     */
21101     for (i = 0; i < nbItems; i++) {
21102 	item = items[i];
21103 	switch (item->type) {
21104 	    case XML_SCHEMA_TYPE_ELEMENT:
21105 		elemDecl = (xmlSchemaElementPtr) item;
21106 
21107 		if ((elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED) == 0)
21108 		{
21109 		    xmlSchemaCheckElementDeclComponent(
21110 			(xmlSchemaElementPtr) elemDecl, pctxt);
21111 		    FIXHFAILURE;
21112 		}
21113 
21114 #ifdef WXS_ELEM_DECL_CONS_ENABLED
21115 		/*
21116 		* Schema Component Constraint: Element Declarations Consistent
21117 		* Apply this constraint to local types of element declarations.
21118 		*/
21119 		if ((WXS_ELEM_TYPEDEF(elemDecl) != NULL) &&
21120 		    (WXS_IS_COMPLEX(WXS_ELEM_TYPEDEF(elemDecl))) &&
21121 		    (WXS_TYPE_IS_LOCAL(WXS_ELEM_TYPEDEF(elemDecl))))
21122 		{
21123 		    xmlSchemaCheckElementDeclConsistent(pctxt,
21124 			WXS_BASIC_CAST elemDecl,
21125 			WXS_TYPE_PARTICLE(WXS_ELEM_TYPEDEF(elemDecl)),
21126 			NULL, NULL, 0);
21127 		}
21128 #endif
21129 		break;
21130 	    default:
21131 		break;
21132 	}
21133     }
21134     if (pctxt->nberrors != 0)
21135 	goto exit_error;
21136 
21137     /*
21138     * Finally we can build the automaton from the content model of
21139     * complex types.
21140     */
21141 
21142     for (i = 0; i < nbItems; i++) {
21143 	item = items[i];
21144 	switch (item->type) {
21145 	    case XML_SCHEMA_TYPE_COMPLEX:
21146 		xmlSchemaBuildContentModel((xmlSchemaTypePtr) item, pctxt);
21147 		/* FIXHFAILURE; */
21148 		break;
21149 	    default:
21150 		break;
21151 	}
21152     }
21153     if (pctxt->nberrors != 0)
21154 	goto exit_error;
21155     /*
21156     * URGENT TODO: cos-element-consistent
21157     */
21158     goto exit;
21159 
21160 exit_error:
21161     ret = pctxt->err;
21162     goto exit;
21163 
21164 exit_failure:
21165     ret = -1;
21166 
21167 exit:
21168     /*
21169     * Reset the constructor. This is needed for XSI acquisition, since
21170     * those items will be processed over and over again for every XSI
21171     * if not cleared here.
21172     */
21173     con->bucket = oldbucket;
21174     con->pending->nbItems = 0;
21175     if (con->substGroups != NULL) {
21176 	xmlHashFree(con->substGroups, xmlSchemaSubstGroupFreeEntry);
21177 	con->substGroups = NULL;
21178     }
21179     if (con->redefs != NULL) {
21180 	xmlSchemaRedefListFree(con->redefs);
21181 	con->redefs = NULL;
21182     }
21183     return(ret);
21184 }
21185 /**
21186  * xmlSchemaParse:
21187  * @ctxt:  a schema validation context
21188  *
21189  * parse a schema definition resource and build an internal
21190  * XML Schema structure which can be used to validate instances.
21191  *
21192  * Returns the internal XML Schema structure built from the resource or
21193  *         NULL in case of error
21194  */
21195 xmlSchemaPtr
xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)21196 xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
21197 {
21198     xmlSchemaPtr mainSchema = NULL;
21199     xmlSchemaBucketPtr bucket = NULL;
21200     int res;
21201 
21202     /*
21203     * This one is used if the schema to be parsed was specified via
21204     * the API; i.e. not automatically by the validated instance document.
21205     */
21206 
21207     if (xmlSchemaInitTypes() < 0)
21208         return (NULL);
21209 
21210     if (ctxt == NULL)
21211         return (NULL);
21212 
21213     /* TODO: Init the context. Is this all we need?*/
21214     ctxt->nberrors = 0;
21215     ctxt->err = 0;
21216     ctxt->counter = 0;
21217 
21218     /* Create the *main* schema. */
21219     mainSchema = xmlSchemaNewSchema(ctxt);
21220     if (mainSchema == NULL)
21221 	goto exit_failure;
21222     /*
21223     * Create the schema constructor.
21224     */
21225     if (ctxt->constructor == NULL) {
21226 	ctxt->constructor = xmlSchemaConstructionCtxtCreate(ctxt->dict);
21227 	if (ctxt->constructor == NULL)
21228 	    goto exit_failure;
21229 	/* Take ownership of the constructor to be able to free it. */
21230 	ctxt->ownsConstructor = 1;
21231     }
21232     ctxt->constructor->mainSchema = mainSchema;
21233     /*
21234     * Locate and add the schema document.
21235     */
21236     res = xmlSchemaAddSchemaDoc(ctxt, XML_SCHEMA_SCHEMA_MAIN,
21237 	ctxt->URL, ctxt->doc, ctxt->buffer, ctxt->size, NULL,
21238 	NULL, NULL, &bucket);
21239     if (res == -1)
21240 	goto exit_failure;
21241     if (res != 0)
21242 	goto exit;
21243 
21244     if (bucket == NULL) {
21245 	/* TODO: Error code, actually we failed to *locate* the schema. */
21246 	if (ctxt->URL)
21247 	    xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21248 		NULL, NULL,
21249 		"Failed to locate the main schema resource at '%s'",
21250 		ctxt->URL, NULL);
21251 	else
21252 	    xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21253 		NULL, NULL,
21254 		"Failed to locate the main schema resource",
21255 		    NULL, NULL);
21256 	goto exit;
21257     }
21258     /* Then do the parsing for good. */
21259     if (xmlSchemaParseNewDocWithContext(ctxt, mainSchema, bucket) == -1)
21260 	goto exit_failure;
21261     if (ctxt->nberrors != 0)
21262 	goto exit;
21263 
21264     mainSchema->doc = bucket->doc;
21265     mainSchema->preserve = ctxt->preserve;
21266 
21267     ctxt->schema = mainSchema;
21268 
21269     if (xmlSchemaFixupComponents(ctxt, WXS_CONSTRUCTOR(ctxt)->mainBucket) == -1)
21270 	goto exit_failure;
21271 
21272     /*
21273     * TODO: This is not nice, since we cannot distinguish from the
21274     * result if there was an internal error or not.
21275     */
21276 exit:
21277     if (ctxt->nberrors != 0) {
21278 	if (mainSchema) {
21279 	    xmlSchemaFree(mainSchema);
21280 	    mainSchema = NULL;
21281 	}
21282 	if (ctxt->constructor) {
21283 	    xmlSchemaConstructionCtxtFree(ctxt->constructor);
21284 	    ctxt->constructor = NULL;
21285 	    ctxt->ownsConstructor = 0;
21286 	}
21287     }
21288     ctxt->schema = NULL;
21289     return(mainSchema);
21290 exit_failure:
21291     /*
21292     * Quite verbose, but should catch internal errors, which were
21293     * not communicated.
21294     */
21295     if (mainSchema) {
21296         xmlSchemaFree(mainSchema);
21297 	mainSchema = NULL;
21298     }
21299     if (ctxt->constructor) {
21300 	xmlSchemaConstructionCtxtFree(ctxt->constructor);
21301 	ctxt->constructor = NULL;
21302 	ctxt->ownsConstructor = 0;
21303     }
21304     PERROR_INT2("xmlSchemaParse",
21305 	"An internal error occurred");
21306     ctxt->schema = NULL;
21307     return(NULL);
21308 }
21309 
21310 /**
21311  * xmlSchemaSetParserErrors:
21312  * @ctxt:  a schema validation context
21313  * @err:  the error callback
21314  * @warn:  the warning callback
21315  * @ctx:  contextual data for the callbacks
21316  *
21317  * DEPRECATED: Use xmlSchemaSetParserStructuredErrors.
21318  *
21319  * Set the callback functions used to handle errors for a validation context
21320  */
21321 void
xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,xmlSchemaValidityErrorFunc err,xmlSchemaValidityWarningFunc warn,void * ctx)21322 xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21323                          xmlSchemaValidityErrorFunc err,
21324                          xmlSchemaValidityWarningFunc warn, void *ctx)
21325 {
21326     if (ctxt == NULL)
21327         return;
21328     ctxt->error = err;
21329     ctxt->warning = warn;
21330     ctxt->errCtxt = ctx;
21331     if (ctxt->vctxt != NULL)
21332 	xmlSchemaSetValidErrors(ctxt->vctxt, err, warn, ctx);
21333 }
21334 
21335 /**
21336  * xmlSchemaSetParserStructuredErrors:
21337  * @ctxt:  a schema parser context
21338  * @serror:  the structured error function
21339  * @ctx: the functions context
21340  *
21341  * Set the structured error callback
21342  */
21343 void
xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,xmlStructuredErrorFunc serror,void * ctx)21344 xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,
21345 				   xmlStructuredErrorFunc serror,
21346 				   void *ctx)
21347 {
21348     if (ctxt == NULL)
21349 	return;
21350     ctxt->serror = serror;
21351     ctxt->errCtxt = ctx;
21352     if (ctxt->vctxt != NULL)
21353 	xmlSchemaSetValidStructuredErrors(ctxt->vctxt, serror, ctx);
21354 }
21355 
21356 /**
21357  * xmlSchemaGetParserErrors:
21358  * @ctxt:  a XMl-Schema parser context
21359  * @err: the error callback result
21360  * @warn: the warning callback result
21361  * @ctx: contextual data for the callbacks result
21362  *
21363  * Get the callback information used to handle errors for a parser context
21364  *
21365  * Returns -1 in case of failure, 0 otherwise
21366  */
21367 int
xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,xmlSchemaValidityErrorFunc * err,xmlSchemaValidityWarningFunc * warn,void ** ctx)21368 xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21369 			 xmlSchemaValidityErrorFunc * err,
21370 			 xmlSchemaValidityWarningFunc * warn, void **ctx)
21371 {
21372 	if (ctxt == NULL)
21373 		return(-1);
21374 	if (err != NULL)
21375 		*err = ctxt->error;
21376 	if (warn != NULL)
21377 		*warn = ctxt->warning;
21378 	if (ctx != NULL)
21379 		*ctx = ctxt->errCtxt;
21380 	return(0);
21381 }
21382 
21383 /**
21384  * xmlSchemaSetResourceLoader:
21385  * @ctxt:  schema parser
21386  * @loader:  resource loader
21387  * @data:  user data which will be passed to the loader
21388  *
21389  * Register a callback function that will be called to load documents
21390  * or external entities.
21391  *
21392  * Available since 2.14.0.
21393  */
21394 void
xmlSchemaSetResourceLoader(xmlSchemaParserCtxtPtr ctxt,xmlResourceLoader loader,void * data)21395 xmlSchemaSetResourceLoader(xmlSchemaParserCtxtPtr ctxt,
21396                            xmlResourceLoader loader, void *data) {
21397     if (ctxt == NULL)
21398         return;
21399     ctxt->resourceLoader = loader;
21400     ctxt->resourceCtxt = data;
21401 }
21402 
21403 /**
21404  * xmlSchemaFacetTypeToString:
21405  * @type:  the facet type
21406  *
21407  * Convert the xmlSchemaTypeType to a char string.
21408  *
21409  * Returns the char string representation of the facet type if the
21410  *     type is a facet and an "Internal Error" string otherwise.
21411  */
21412 static const xmlChar *
xmlSchemaFacetTypeToString(xmlSchemaTypeType type)21413 xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
21414 {
21415     switch (type) {
21416         case XML_SCHEMA_FACET_PATTERN:
21417             return (BAD_CAST "pattern");
21418         case XML_SCHEMA_FACET_MAXEXCLUSIVE:
21419             return (BAD_CAST "maxExclusive");
21420         case XML_SCHEMA_FACET_MAXINCLUSIVE:
21421             return (BAD_CAST "maxInclusive");
21422         case XML_SCHEMA_FACET_MINEXCLUSIVE:
21423             return (BAD_CAST "minExclusive");
21424         case XML_SCHEMA_FACET_MININCLUSIVE:
21425             return (BAD_CAST "minInclusive");
21426         case XML_SCHEMA_FACET_WHITESPACE:
21427             return (BAD_CAST "whiteSpace");
21428         case XML_SCHEMA_FACET_ENUMERATION:
21429             return (BAD_CAST "enumeration");
21430         case XML_SCHEMA_FACET_LENGTH:
21431             return (BAD_CAST "length");
21432         case XML_SCHEMA_FACET_MAXLENGTH:
21433             return (BAD_CAST "maxLength");
21434         case XML_SCHEMA_FACET_MINLENGTH:
21435             return (BAD_CAST "minLength");
21436         case XML_SCHEMA_FACET_TOTALDIGITS:
21437             return (BAD_CAST "totalDigits");
21438         case XML_SCHEMA_FACET_FRACTIONDIGITS:
21439             return (BAD_CAST "fractionDigits");
21440         default:
21441             break;
21442     }
21443     return (BAD_CAST "Internal Error");
21444 }
21445 
21446 static xmlSchemaWhitespaceValueType
xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)21447 xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
21448 {
21449     /*
21450     * The normalization type can be changed only for types which are derived
21451     * from xsd:string.
21452     */
21453     if (type->type == XML_SCHEMA_TYPE_BASIC) {
21454 	/*
21455 	* Note that we assume a whitespace of preserve for anySimpleType.
21456 	*/
21457 	if ((type->builtInType == XML_SCHEMAS_STRING) ||
21458 	    (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
21459 	    return(XML_SCHEMA_WHITESPACE_PRESERVE);
21460 	else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
21461 	    return(XML_SCHEMA_WHITESPACE_REPLACE);
21462 	else {
21463 	    /*
21464 	    * For all `atomic` datatypes other than string (and types `derived`
21465 	    * by `restriction` from it) the value of whiteSpace is fixed to
21466 	    * collapse
21467 	    * Note that this includes built-in list datatypes.
21468 	    */
21469 	    return(XML_SCHEMA_WHITESPACE_COLLAPSE);
21470 	}
21471     } else if (WXS_IS_LIST(type)) {
21472 	/*
21473 	* For list types the facet "whiteSpace" is fixed to "collapse".
21474 	*/
21475 	return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21476     } else if (WXS_IS_UNION(type)) {
21477 	return (XML_SCHEMA_WHITESPACE_UNKNOWN);
21478     } else if (WXS_IS_ATOMIC(type)) {
21479 	if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
21480 	    return (XML_SCHEMA_WHITESPACE_PRESERVE);
21481 	else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
21482 	    return (XML_SCHEMA_WHITESPACE_REPLACE);
21483 	else
21484 	    return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21485     }
21486     return (-1);
21487 }
21488 
21489 /************************************************************************
21490  *									*
21491  *			Simple type validation				*
21492  *									*
21493  ************************************************************************/
21494 
21495 
21496 /************************************************************************
21497  *									*
21498  *			DOM Validation code				*
21499  *									*
21500  ************************************************************************/
21501 
21502 /**
21503  * xmlSchemaAssembleByLocation:
21504  * @pctxt:  a schema parser context
21505  * @vctxt:  a schema validation context
21506  * @schema: the existing schema
21507  * @node: the node that fired the assembling
21508  * @nsName: the namespace name of the new schema
21509  * @location: the location of the schema
21510  *
21511  * Expands an existing schema by an additional schema.
21512  *
21513  * Returns 0 if the new schema is correct, a positive error code
21514  * number otherwise and -1 in case of an internal or API error.
21515  */
21516 static int
xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,xmlSchemaPtr schema,xmlNodePtr node,const xmlChar * nsName,const xmlChar * location)21517 xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
21518 			    xmlSchemaPtr schema,
21519 			    xmlNodePtr node,
21520 			    const xmlChar *nsName,
21521 			    const xmlChar *location)
21522 {
21523     int ret = 0;
21524     xmlSchemaParserCtxtPtr pctxt;
21525     xmlSchemaBucketPtr bucket = NULL;
21526 
21527     if ((vctxt == NULL) || (schema == NULL))
21528 	return (-1);
21529 
21530     if (vctxt->pctxt == NULL) {
21531 	VERROR_INT("xmlSchemaAssembleByLocation",
21532 	    "no parser context available");
21533 	return(-1);
21534     }
21535     pctxt = vctxt->pctxt;
21536     if (pctxt->constructor == NULL) {
21537 	PERROR_INT("xmlSchemaAssembleByLocation",
21538 	    "no constructor");
21539 	return(-1);
21540     }
21541     /*
21542     * Acquire the schema document.
21543     */
21544     location = xmlSchemaBuildAbsoluteURI(pctxt->dict,
21545 	location, node);
21546     /*
21547     * Note that we pass XML_SCHEMA_SCHEMA_IMPORT here;
21548     * the process will automatically change this to
21549     * XML_SCHEMA_SCHEMA_MAIN if it is the first schema document.
21550     */
21551     ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
21552 	location, NULL, NULL, 0, node, NULL, nsName,
21553 	&bucket);
21554     if (ret != 0)
21555 	return(ret);
21556     if (bucket == NULL) {
21557 	/*
21558 	* Generate a warning that the document could not be located.
21559 	*/
21560 	xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21561 	    node, NULL,
21562 	    "The document at location '%s' could not be acquired",
21563 	    location, NULL, NULL);
21564 	return(ret);
21565     }
21566     /*
21567     * The first located schema will be handled as if all other
21568     * schemas imported by XSI were imported by this first schema.
21569     */
21570     if ((bucket != NULL) &&
21571 	(WXS_CONSTRUCTOR(pctxt)->bucket == NULL))
21572 	WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
21573     /*
21574     * TODO: Is this handled like an import? I.e. is it not an error
21575     * if the schema cannot be located?
21576     */
21577     if ((bucket == NULL) || (! CAN_PARSE_SCHEMA(bucket)))
21578 	return(0);
21579     /*
21580     * We will reuse the parser context for every schema imported
21581     * directly via XSI. So reset the context.
21582     */
21583     pctxt->nberrors = 0;
21584     pctxt->err = 0;
21585     pctxt->doc = bucket->doc;
21586 
21587     ret = xmlSchemaParseNewDocWithContext(pctxt, schema, bucket);
21588     if (ret == -1) {
21589 	pctxt->doc = NULL;
21590 	goto exit_failure;
21591     }
21592     /* Paranoid error channelling. */
21593     if ((ret == 0) && (pctxt->nberrors != 0))
21594 	ret = pctxt->err;
21595     if (pctxt->nberrors == 0) {
21596 	/*
21597 	* Only bother to fixup pending components, if there was
21598 	* no error yet.
21599 	* For every XSI acquired schema (and its sub-schemata) we will
21600 	* fixup the components.
21601 	*/
21602 	xmlSchemaFixupComponents(pctxt, bucket);
21603 	ret = pctxt->err;
21604 	/*
21605 	* Not nice, but we need somehow to channel the schema parser
21606 	* error to the validation context.
21607 	*/
21608 	if ((ret != 0) && (vctxt->err == 0))
21609 	    vctxt->err = ret;
21610 	vctxt->nberrors += pctxt->nberrors;
21611     } else {
21612 	/* Add to validation error sum. */
21613 	vctxt->nberrors += pctxt->nberrors;
21614     }
21615     pctxt->doc = NULL;
21616     return(ret);
21617 exit_failure:
21618     pctxt->doc = NULL;
21619     return (-1);
21620 }
21621 
21622 static xmlSchemaAttrInfoPtr
xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,int metaType)21623 xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
21624 			 int metaType)
21625 {
21626     if (vctxt->nbAttrInfos == 0)
21627 	return (NULL);
21628     {
21629 	int i;
21630 	xmlSchemaAttrInfoPtr iattr;
21631 
21632 	for (i = 0; i < vctxt->nbAttrInfos; i++) {
21633 	    iattr = vctxt->attrInfos[i];
21634 	    if (iattr->metaType == metaType)
21635 		return (iattr);
21636 	}
21637 
21638     }
21639     return (NULL);
21640 }
21641 
21642 /**
21643  * xmlSchemaAssembleByXSI:
21644  * @vctxt:  a schema validation context
21645  *
21646  * Expands an existing schema by an additional schema using
21647  * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
21648  * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
21649  * must be set to 1.
21650  *
21651  * Returns 0 if the new schema is correct, a positive error code
21652  * number otherwise and -1 in case of an internal or API error.
21653  */
21654 static int
xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)21655 xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
21656 {
21657     const xmlChar *cur, *end;
21658     const xmlChar *nsname = NULL, *location;
21659     int ret = 0;
21660     xmlSchemaAttrInfoPtr iattr;
21661 
21662     /*
21663     * Parse the value; we will assume an even number of values
21664     * to be given (this is how Xerces and XSV work).
21665     *
21666     * URGENT TODO: !! This needs to work for both
21667     * @noNamespaceSchemaLocation AND @schemaLocation on the same
21668     * element !!
21669     */
21670     iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21671 	XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
21672     if (iattr == NULL)
21673 	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21674 	XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
21675     if (iattr == NULL)
21676 	return (0);
21677     cur = iattr->value;
21678     do {
21679 	/*
21680 	* TODO: Move the string parsing mechanism away from here.
21681 	*/
21682 	if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
21683 	    /*
21684 	    * Get the namespace name.
21685 	    */
21686 	    while (IS_BLANK_CH(*cur))
21687 		cur++;
21688 	    end = cur;
21689 	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21690 		end++;
21691 	    if (end == cur)
21692 		break;
21693 	    /* TODO: Don't use the schema's dict. */
21694 	    nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21695 	    cur = end;
21696 	}
21697 	/*
21698 	* Get the URI.
21699 	*/
21700 	while (IS_BLANK_CH(*cur))
21701 	    cur++;
21702 	end = cur;
21703 	while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21704 	    end++;
21705 	if (end == cur) {
21706 	    if (iattr->metaType ==
21707 		XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC)
21708 	    {
21709 		/*
21710 		* If using @schemaLocation then tuples are expected.
21711 		* I.e. the namespace name *and* the document's URI.
21712 		*/
21713 		xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21714 		    iattr->node, NULL,
21715 		    "The value must consist of tuples: the target namespace "
21716 		    "name and the document's URI", NULL, NULL, NULL);
21717 	    }
21718 	    break;
21719 	}
21720 	/* TODO: Don't use the schema's dict. */
21721 	location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21722 	cur = end;
21723 	ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
21724 	    iattr->node, nsname, location);
21725 	if (ret == -1) {
21726 	    VERROR_INT("xmlSchemaAssembleByXSI",
21727 		"assembling schemata");
21728 	    return (-1);
21729 	}
21730     } while (*cur != 0);
21731     return (ret);
21732 }
21733 
21734 static const xmlChar *
xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,const xmlChar * prefix)21735 xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
21736 			 const xmlChar *prefix)
21737 {
21738     if (vctxt->sax != NULL) {
21739 	int i, j;
21740 	xmlSchemaNodeInfoPtr inode;
21741 
21742 	for (i = vctxt->depth; i >= 0; i--) {
21743 	    if (vctxt->elemInfos[i]->nbNsBindings != 0) {
21744 		inode = vctxt->elemInfos[i];
21745 		for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
21746 		    if (((prefix == NULL) &&
21747 			    (inode->nsBindings[j] == NULL)) ||
21748 			((prefix != NULL) && xmlStrEqual(prefix,
21749 			    inode->nsBindings[j]))) {
21750 
21751 			/*
21752 			* Note that the namespace bindings are already
21753 			* in a string dict.
21754 			*/
21755 			return (inode->nsBindings[j+1]);
21756 		    }
21757 		}
21758 	    }
21759 	}
21760 	return (NULL);
21761 #ifdef LIBXML_READER_ENABLED
21762     } else if (vctxt->reader != NULL) {
21763 	xmlChar *nsName;
21764 
21765 	nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
21766 	if (nsName != NULL) {
21767 	    const xmlChar *ret;
21768 
21769 	    ret = xmlDictLookup(vctxt->dict, nsName, -1);
21770 	    xmlFree(nsName);
21771 	    return (ret);
21772 	} else
21773 	    return (NULL);
21774 #endif
21775     } else {
21776 	xmlNsPtr ns;
21777 
21778 	if ((vctxt->inode->node == NULL) ||
21779 	    (vctxt->inode->node->doc == NULL)) {
21780 	    VERROR_INT("xmlSchemaLookupNamespace",
21781 		"no node or node's doc available");
21782 	    return (NULL);
21783 	}
21784 	ns = xmlSearchNs(vctxt->inode->node->doc,
21785 	    vctxt->inode->node, prefix);
21786 	if (ns != NULL)
21787 	    return (ns->href);
21788 	return (NULL);
21789     }
21790 }
21791 
21792 /*
21793 * This one works on the schema of the validation context.
21794 */
21795 static int
xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,xmlSchemaPtr schema,xmlNodePtr node,const xmlChar * value,xmlSchemaValPtr * val,int valNeeded)21796 xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
21797 			  xmlSchemaPtr schema,
21798 			  xmlNodePtr node,
21799 			  const xmlChar *value,
21800 			  xmlSchemaValPtr *val,
21801 			  int valNeeded)
21802 {
21803     int ret;
21804 
21805     if (vctxt && (vctxt->schema == NULL)) {
21806 	VERROR_INT("xmlSchemaValidateNotation",
21807 	    "a schema is needed on the validation context");
21808 	return (-1);
21809     }
21810     ret = xmlValidateQName(value, 1);
21811     if (ret != 0)
21812 	return (ret);
21813     {
21814 	xmlChar *localName = NULL;
21815 	xmlChar *prefix = NULL;
21816 
21817 	localName = xmlSplitQName2(value, &prefix);
21818 	if (prefix != NULL) {
21819 	    const xmlChar *nsName = NULL;
21820 
21821 	    if (vctxt != NULL)
21822 		nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
21823 	    else if (node != NULL) {
21824 		xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
21825 		if (ns != NULL)
21826 		    nsName = ns->href;
21827 	    } else {
21828 		xmlFree(prefix);
21829 		xmlFree(localName);
21830 		return (1);
21831 	    }
21832 	    if (nsName == NULL) {
21833 		xmlFree(prefix);
21834 		xmlFree(localName);
21835 		return (1);
21836 	    }
21837 	    if (xmlSchemaGetNotation(schema, localName, nsName) != NULL) {
21838 		if ((valNeeded) && (val != NULL)) {
21839 		    (*val) = xmlSchemaNewNOTATIONValue(xmlStrdup(localName),
21840 						       xmlStrdup(nsName));
21841 		    if (*val == NULL)
21842 			ret = -1;
21843 		}
21844 	    } else
21845 		ret = 1;
21846 	    xmlFree(prefix);
21847 	    xmlFree(localName);
21848 	} else {
21849 	    if (xmlSchemaGetNotation(schema, value, NULL) != NULL) {
21850 		if (valNeeded && (val != NULL)) {
21851 		    (*val) = xmlSchemaNewNOTATIONValue(
21852 			BAD_CAST xmlStrdup(value), NULL);
21853 		    if (*val == NULL)
21854 			ret = -1;
21855 		}
21856 	    } else
21857 		return (1);
21858 	}
21859     }
21860     return (ret);
21861 }
21862 
21863 static int
xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,const xmlChar * lname,const xmlChar * nsname)21864 xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,
21865 		       const xmlChar* lname,
21866 		       const xmlChar* nsname)
21867 {
21868     int i;
21869 
21870     lname = xmlDictLookup(vctxt->dict, lname, -1);
21871     if (lname == NULL)
21872 	return(-1);
21873     if (nsname != NULL) {
21874 	nsname = xmlDictLookup(vctxt->dict, nsname, -1);
21875 	if (nsname == NULL)
21876 	    return(-1);
21877     }
21878     for (i = 0; i < vctxt->nodeQNames->nbItems; i += 2) {
21879 	if ((vctxt->nodeQNames->items [i] == lname) &&
21880 	    (vctxt->nodeQNames->items[i +1] == nsname))
21881 	    /* Already there */
21882 	    return(i);
21883     }
21884     /* Add new entry. */
21885     i = vctxt->nodeQNames->nbItems;
21886     if (xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) lname) < 0) {
21887         xmlSchemaVErrMemory(vctxt);
21888         return(-1);
21889     }
21890     if (xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) nsname) < 0) {
21891         vctxt->nodeQNames->nbItems--;
21892         xmlSchemaVErrMemory(vctxt);
21893         return(-1);
21894     }
21895     return(i);
21896 }
21897 
21898 /************************************************************************
21899  *									*
21900  *  Validation of identity-constraints (IDC)                            *
21901  *									*
21902  ************************************************************************/
21903 
21904 /**
21905  * xmlSchemaAugmentIDC:
21906  * @idcDef: the IDC definition
21907  *
21908  * Creates an augmented IDC definition item.
21909  *
21910  * Returns the item, or NULL on internal errors.
21911  */
21912 static void
xmlSchemaAugmentIDC(void * payload,void * data,const xmlChar * name ATTRIBUTE_UNUSED)21913 xmlSchemaAugmentIDC(void *payload, void *data,
21914                     const xmlChar *name ATTRIBUTE_UNUSED)
21915 {
21916     xmlSchemaIDCPtr idcDef = (xmlSchemaIDCPtr) payload;
21917     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) data;
21918     xmlSchemaIDCAugPtr aidc;
21919 
21920     aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
21921     if (aidc == NULL) {
21922 	xmlSchemaVErrMemory(vctxt);
21923 	return;
21924     }
21925     aidc->keyrefDepth = -1;
21926     aidc->def = idcDef;
21927     aidc->next = NULL;
21928     if (vctxt->aidcs == NULL)
21929 	vctxt->aidcs = aidc;
21930     else {
21931 	aidc->next = vctxt->aidcs;
21932 	vctxt->aidcs = aidc;
21933     }
21934     /*
21935     * Save if we have keyrefs at all.
21936     */
21937     if ((vctxt->hasKeyrefs == 0) &&
21938 	(idcDef->type == XML_SCHEMA_TYPE_IDC_KEYREF))
21939 	vctxt->hasKeyrefs = 1;
21940 }
21941 
21942 /**
21943  * xmlSchemaAugmentImportedIDC:
21944  * @imported: the imported schema
21945  *
21946  * Creates an augmented IDC definition for the imported schema.
21947  */
21948 static void
xmlSchemaAugmentImportedIDC(void * payload,void * data,const xmlChar * name ATTRIBUTE_UNUSED)21949 xmlSchemaAugmentImportedIDC(void *payload, void *data,
21950                             const xmlChar *name ATTRIBUTE_UNUSED) {
21951     xmlSchemaImportPtr imported = (xmlSchemaImportPtr) payload;
21952     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) data;
21953     if (imported->schema->idcDef != NULL) {
21954 	    xmlHashScan(imported->schema->idcDef, xmlSchemaAugmentIDC, vctxt);
21955     }
21956 }
21957 
21958 /**
21959  * xmlSchemaIDCNewBinding:
21960  * @idcDef: the IDC definition of this binding
21961  *
21962  * Creates a new IDC binding.
21963  *
21964  * Returns the new IDC binding, NULL on internal errors.
21965  */
21966 static xmlSchemaPSVIIDCBindingPtr
xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)21967 xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
21968 {
21969     xmlSchemaPSVIIDCBindingPtr ret;
21970 
21971     ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
21972 	    sizeof(xmlSchemaPSVIIDCBinding));
21973     if (ret == NULL) {
21974 	xmlSchemaVErrMemory(NULL);
21975 	return (NULL);
21976     }
21977     memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
21978     ret->definition = idcDef;
21979     return (ret);
21980 }
21981 
21982 /**
21983  * xmlSchemaIDCStoreNodeTableItem:
21984  * @vctxt: the WXS validation context
21985  * @item: the IDC node table item
21986  *
21987  * The validation context is used to store IDC node table items.
21988  * They are stored to avoid copying them if IDC node-tables are merged
21989  * with corresponding parent IDC node-tables (bubbling).
21990  *
21991  * Returns 0 if succeeded, -1 on internal errors.
21992  */
21993 static int
xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,xmlSchemaPSVIIDCNodePtr item)21994 xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
21995 			       xmlSchemaPSVIIDCNodePtr item)
21996 {
21997     /*
21998     * Add to global list.
21999     */
22000     if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
22001         xmlSchemaPSVIIDCNodePtr *tmp;
22002         int newSize;
22003 
22004         newSize = xmlGrowCapacity(vctxt->sizeIdcNodes, sizeof(tmp[0]),
22005                                   20, XML_MAX_ITEMS);
22006 	if (newSize < 0) {
22007 	    xmlSchemaVErrMemory(vctxt);
22008 	    return (-1);
22009 	}
22010 	tmp = xmlRealloc(vctxt->idcNodes, newSize * sizeof(tmp[0]));
22011 	if (tmp == NULL) {
22012 	    xmlSchemaVErrMemory(vctxt);
22013 	    return (-1);
22014 	}
22015 
22016         vctxt->idcNodes = tmp;
22017         vctxt->sizeIdcNodes = newSize;
22018     }
22019 
22020     vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
22021     return (0);
22022 }
22023 
22024 /**
22025  * xmlSchemaIDCStoreKey:
22026  * @vctxt: the WXS validation context
22027  * @item: the IDC key
22028  *
22029  * The validation context is used to store an IDC key.
22030  *
22031  * Returns 0 if succeeded, -1 on internal errors.
22032  */
22033 static int
xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,xmlSchemaPSVIIDCKeyPtr key)22034 xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
22035 		     xmlSchemaPSVIIDCKeyPtr key)
22036 {
22037     /*
22038     * Add to global list.
22039     */
22040     if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
22041         xmlSchemaPSVIIDCKeyPtr *tmp;
22042         int newSize;
22043 
22044         newSize = xmlGrowCapacity(vctxt->sizeIdcKeys, sizeof(tmp[0]),
22045                                   20, XML_MAX_ITEMS);
22046 	if (newSize < 0) {
22047 	    xmlSchemaVErrMemory(vctxt);
22048 	    return (-1);
22049 	}
22050 	tmp = xmlRealloc(vctxt->idcKeys, newSize * sizeof(tmp[0]));
22051 	if (tmp == NULL) {
22052 	    xmlSchemaVErrMemory(vctxt);
22053 	    return (-1);
22054 	}
22055 
22056         vctxt->idcKeys = tmp;
22057         vctxt->sizeIdcKeys = newSize;
22058     }
22059 
22060     vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
22061     return (0);
22062 }
22063 
22064 /**
22065  * xmlSchemaIDCAppendNodeTableItem:
22066  * @bind: the IDC binding
22067  * @ntItem: the node-table item
22068  *
22069  * Appends the IDC node-table item to the binding.
22070  *
22071  * Returns 0 on success and -1 on internal errors.
22072  */
22073 static int
xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,xmlSchemaPSVIIDCNodePtr ntItem)22074 xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
22075 				xmlSchemaPSVIIDCNodePtr ntItem)
22076 {
22077     if (bind->sizeNodes <= bind->nbNodes) {
22078         xmlSchemaPSVIIDCNodePtr *tmp;
22079         int newSize;
22080 
22081         newSize = xmlGrowCapacity(bind->sizeNodes, sizeof(tmp[0]),
22082                                   10, XML_MAX_ITEMS);
22083 	if (newSize < 0) {
22084 	    xmlSchemaVErrMemory(NULL);
22085 	    return(-1);
22086 	}
22087 	tmp = xmlRealloc(bind->nodeTable, newSize * sizeof(tmp[0]));
22088 	if (tmp == NULL) {
22089 	    xmlSchemaVErrMemory(NULL);
22090 	    return(-1);
22091 	}
22092 
22093         bind->nodeTable = tmp;
22094         bind->sizeNodes = newSize;
22095     }
22096 
22097     bind->nodeTable[bind->nbNodes++] = ntItem;
22098     return(0);
22099 }
22100 
22101 /**
22102  * xmlSchemaIDCAcquireBinding:
22103  * @vctxt: the WXS validation context
22104  * @matcher: the IDC matcher
22105  *
22106  * Looks up an PSVI IDC binding, for the IDC definition and
22107  * of the given matcher. If none found, a new one is created
22108  * and added to the IDC table.
22109  *
22110  * Returns an IDC binding or NULL on internal errors.
22111  */
22112 static xmlSchemaPSVIIDCBindingPtr
xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,xmlSchemaIDCMatcherPtr matcher)22113 xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,
22114 			  xmlSchemaIDCMatcherPtr matcher)
22115 {
22116     xmlSchemaNodeInfoPtr ielem;
22117 
22118     ielem = vctxt->elemInfos[matcher->depth];
22119 
22120     if (ielem->idcTable == NULL) {
22121 	ielem->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
22122 	if (ielem->idcTable == NULL)
22123 	    return (NULL);
22124 	return(ielem->idcTable);
22125     } else {
22126 	xmlSchemaPSVIIDCBindingPtr bind = NULL;
22127 
22128 	bind = ielem->idcTable;
22129 	do {
22130 	    if (bind->definition == matcher->aidc->def)
22131 		return(bind);
22132 	    if (bind->next == NULL) {
22133 		bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
22134 		if (bind->next == NULL)
22135 		    return (NULL);
22136 		return(bind->next);
22137 	    }
22138 	    bind = bind->next;
22139 	} while (bind != NULL);
22140     }
22141     return (NULL);
22142 }
22143 
22144 static xmlSchemaItemListPtr
xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt,xmlSchemaIDCMatcherPtr matcher)22145 xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt,
22146 			      xmlSchemaIDCMatcherPtr matcher)
22147 {
22148     if (matcher->targets == NULL) {
22149 	matcher->targets = xmlSchemaItemListCreate();
22150         if (matcher->targets == NULL)
22151             xmlSchemaVErrMemory(vctxt);
22152     }
22153     return(matcher->targets);
22154 }
22155 
22156 /**
22157  * xmlSchemaIDCFreeKey:
22158  * @key: the IDC key
22159  *
22160  * Frees an IDC key together with its compiled value.
22161  */
22162 static void
xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)22163 xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
22164 {
22165     if (key->val != NULL)
22166 	xmlSchemaFreeValue(key->val);
22167     xmlFree(key);
22168 }
22169 
22170 /**
22171  * xmlSchemaIDCFreeBinding:
22172  *
22173  * Frees an IDC binding. Note that the node table-items
22174  * are not freed.
22175  */
22176 static void
xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)22177 xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
22178 {
22179     if (bind->nodeTable != NULL)
22180 	xmlFree(bind->nodeTable);
22181     if (bind->dupls != NULL)
22182 	xmlSchemaItemListFree(bind->dupls);
22183     xmlFree(bind);
22184 }
22185 
22186 /**
22187  * xmlSchemaIDCFreeIDCTable:
22188  * @bind: the first IDC binding in the list
22189  *
22190  * Frees an IDC table, i.e. all the IDC bindings in the list.
22191  */
22192 static void
xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)22193 xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
22194 {
22195     xmlSchemaPSVIIDCBindingPtr prev;
22196 
22197     while (bind != NULL) {
22198 	prev = bind;
22199 	bind = bind->next;
22200 	xmlSchemaIDCFreeBinding(prev);
22201     }
22202 }
22203 
22204 static void
xmlFreeIDCHashEntry(void * payload,const xmlChar * name ATTRIBUTE_UNUSED)22205 xmlFreeIDCHashEntry (void *payload, const xmlChar *name ATTRIBUTE_UNUSED)
22206 {
22207     xmlIDCHashEntryPtr e = payload, n;
22208     while (e) {
22209 	n = e->next;
22210 	xmlFree(e);
22211 	e = n;
22212     }
22213 }
22214 
22215 /**
22216  * xmlSchemaIDCFreeMatcherList:
22217  * @matcher: the first IDC matcher in the list
22218  *
22219  * Frees a list of IDC matchers.
22220  */
22221 static void
xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)22222 xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
22223 {
22224     xmlSchemaIDCMatcherPtr next;
22225 
22226     while (matcher != NULL) {
22227 	next = matcher->next;
22228 	if (matcher->keySeqs != NULL) {
22229 	    int i;
22230 	    for (i = 0; i < matcher->sizeKeySeqs; i++)
22231 		if (matcher->keySeqs[i] != NULL)
22232 		    xmlFree(matcher->keySeqs[i]);
22233 	    xmlFree(matcher->keySeqs);
22234 	}
22235 	if (matcher->targets != NULL) {
22236 	    if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22237 		int i;
22238 		xmlSchemaPSVIIDCNodePtr idcNode;
22239 		/*
22240 		* Node-table items for keyrefs are not stored globally
22241 		* to the validation context, since they are not bubbled.
22242 		* We need to free them here.
22243 		*/
22244 		for (i = 0; i < matcher->targets->nbItems; i++) {
22245 		    idcNode =
22246 			(xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22247 		    xmlFree(idcNode->keys);
22248 		    xmlFree(idcNode);
22249 		}
22250 	    }
22251 	    xmlSchemaItemListFree(matcher->targets);
22252 	}
22253 	if (matcher->htab != NULL)
22254 	  xmlHashFree(matcher->htab, xmlFreeIDCHashEntry);
22255 	xmlFree(matcher);
22256 	matcher = next;
22257     }
22258 }
22259 
22260 /**
22261  * xmlSchemaIDCReleaseMatcherList:
22262  * @vctxt: the WXS validation context
22263  * @matcher: the first IDC matcher in the list
22264  *
22265  * Caches a list of IDC matchers for reuse.
22266  */
22267 static void
xmlSchemaIDCReleaseMatcherList(xmlSchemaValidCtxtPtr vctxt,xmlSchemaIDCMatcherPtr matcher)22268 xmlSchemaIDCReleaseMatcherList(xmlSchemaValidCtxtPtr vctxt,
22269 			       xmlSchemaIDCMatcherPtr matcher)
22270 {
22271     xmlSchemaIDCMatcherPtr next;
22272 
22273     while (matcher != NULL) {
22274 	next = matcher->next;
22275 	if (matcher->keySeqs != NULL) {
22276 	    int i;
22277 	    /*
22278 	    * Don't free the array, but only the content.
22279 	    */
22280 	    for (i = 0; i < matcher->sizeKeySeqs; i++)
22281 		if (matcher->keySeqs[i] != NULL) {
22282 		    xmlFree(matcher->keySeqs[i]);
22283 		    matcher->keySeqs[i] = NULL;
22284 		}
22285 	}
22286 	if (matcher->targets) {
22287 	    if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22288 		int i;
22289 		xmlSchemaPSVIIDCNodePtr idcNode;
22290 		/*
22291 		* Node-table items for keyrefs are not stored globally
22292 		* to the validation context, since they are not bubbled.
22293 		* We need to free them here.
22294 		*/
22295 		for (i = 0; i < matcher->targets->nbItems; i++) {
22296 		    idcNode =
22297 			(xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22298 		    xmlFree(idcNode->keys);
22299 		    xmlFree(idcNode);
22300 		}
22301 	    }
22302 	    xmlSchemaItemListFree(matcher->targets);
22303 	    matcher->targets = NULL;
22304 	}
22305 	if (matcher->htab != NULL) {
22306 	    xmlHashFree(matcher->htab, xmlFreeIDCHashEntry);
22307 	    matcher->htab = NULL;
22308 	}
22309 	matcher->next = NULL;
22310 	/*
22311 	* Cache the matcher.
22312 	*/
22313 	if (vctxt->idcMatcherCache != NULL)
22314 	    matcher->nextCached = vctxt->idcMatcherCache;
22315 	vctxt->idcMatcherCache = matcher;
22316 
22317 	matcher = next;
22318     }
22319 }
22320 
22321 /**
22322  * xmlSchemaIDCAddStateObject:
22323  * @vctxt: the WXS validation context
22324  * @matcher: the IDC matcher
22325  * @sel: the XPath information
22326  * @parent: the parent "selector" state object if any
22327  * @type: "selector" or "field"
22328  *
22329  * Creates/reuses and activates state objects for the given
22330  * XPath information; if the XPath expression consists of unions,
22331  * multiple state objects are created for every unioned expression.
22332  *
22333  * Returns 0 on success and -1 on internal errors.
22334  */
22335 static int
xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,xmlSchemaIDCMatcherPtr matcher,xmlSchemaIDCSelectPtr sel,int type)22336 xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
22337 			xmlSchemaIDCMatcherPtr matcher,
22338 			xmlSchemaIDCSelectPtr sel,
22339 			int type)
22340 {
22341     xmlSchemaIDCStateObjPtr sto;
22342 
22343     /*
22344     * Reuse the state objects from the pool.
22345     */
22346     if (vctxt->xpathStatePool != NULL) {
22347 	sto = vctxt->xpathStatePool;
22348 	vctxt->xpathStatePool = sto->next;
22349 	sto->next = NULL;
22350     } else {
22351 	/*
22352 	* Create a new state object.
22353 	*/
22354 	sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
22355 	if (sto == NULL) {
22356 	    xmlSchemaVErrMemory(NULL);
22357 	    return (-1);
22358 	}
22359 	memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
22360     }
22361     /*
22362     * Add to global list.
22363     */
22364     if (vctxt->xpathStates != NULL)
22365 	sto->next = vctxt->xpathStates;
22366     vctxt->xpathStates = sto;
22367 
22368     /*
22369     * Free the old xpath validation context.
22370     */
22371     if (sto->xpathCtxt != NULL)
22372 	xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
22373 
22374     /*
22375     * Create a new XPath (pattern) validation context.
22376     */
22377     sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
22378 	(xmlPatternPtr) sel->xpathComp);
22379     if (sto->xpathCtxt == NULL) {
22380 	VERROR_INT("xmlSchemaIDCAddStateObject",
22381 	    "failed to create an XPath validation context");
22382 	return (-1);
22383     }
22384     sto->type = type;
22385     sto->depth = vctxt->depth;
22386     sto->matcher = matcher;
22387     sto->sel = sel;
22388     sto->nbHistory = 0;
22389 
22390     return (0);
22391 }
22392 
22393 /**
22394  * xmlSchemaXPathEvaluate:
22395  * @vctxt: the WXS validation context
22396  * @nodeType: the nodeType of the current node
22397  *
22398  * Evaluates all active XPath state objects.
22399  *
22400  * Returns the number of IC "field" state objects which resolved to
22401  * this node, 0 if none resolved and -1 on internal errors.
22402  */
22403 static int
xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,xmlElementType nodeType)22404 xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
22405 		       xmlElementType nodeType)
22406 {
22407     xmlSchemaIDCStateObjPtr sto, head = NULL, first;
22408     int res, resolved = 0, depth = vctxt->depth;
22409 
22410     if (vctxt->xpathStates == NULL)
22411 	return (0);
22412 
22413     if (nodeType == XML_ATTRIBUTE_NODE)
22414 	depth++;
22415     /*
22416     * Process all active XPath state objects.
22417     */
22418     first = vctxt->xpathStates;
22419     sto = first;
22420     while (sto != head) {
22421 	if (nodeType == XML_ELEMENT_NODE)
22422 	    res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
22423 		vctxt->inode->localName, vctxt->inode->nsName);
22424 	else
22425 	    res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
22426 		vctxt->inode->localName, vctxt->inode->nsName);
22427 
22428 	if (res == -1) {
22429 	    VERROR_INT("xmlSchemaXPathEvaluate",
22430 		"calling xmlStreamPush()");
22431 	    return (-1);
22432 	}
22433 	if (res == 0)
22434 	    goto next_sto;
22435 	/*
22436 	* Full match.
22437 	*/
22438 	/*
22439 	* Register a match in the state object history.
22440 	*/
22441         if (sto->sizeHistory <= sto->nbHistory) {
22442             int *tmp;
22443             int newSize;
22444 
22445             newSize = xmlGrowCapacity(sto->sizeHistory, sizeof(tmp[0]),
22446                                       5, XML_MAX_ITEMS);
22447             if (newSize < 0) {
22448                 xmlSchemaVErrMemory(vctxt);
22449                 return (-1);
22450             }
22451             tmp = xmlRealloc(sto->history, newSize * sizeof(tmp[0]));
22452             if (tmp == NULL) {
22453                 xmlSchemaVErrMemory(vctxt);
22454                 return (-1);
22455             }
22456 
22457             sto->history = tmp;
22458             sto->sizeHistory = newSize;
22459 	}
22460 	sto->history[sto->nbHistory++] = depth;
22461 
22462 	if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22463 	    xmlSchemaIDCSelectPtr sel;
22464 	    /*
22465 	    * Activate state objects for the IDC fields of
22466 	    * the IDC selector.
22467 	    */
22468 	    sel = sto->matcher->aidc->def->fields;
22469 	    while (sel != NULL) {
22470 		if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
22471 		    sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
22472 		    return (-1);
22473 		sel = sel->next;
22474 	    }
22475 	} else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22476 	    /*
22477 	    * An IDC key node was found by the IDC field.
22478 	    */
22479 	    /*
22480 	    * Notify that the character value of this node is
22481 	    * needed.
22482 	    */
22483 	    if (resolved == 0) {
22484 		if ((vctxt->inode->flags &
22485 		    XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
22486 		vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
22487 	    }
22488 	    resolved++;
22489 	}
22490 next_sto:
22491 	if (sto->next == NULL) {
22492 	    /*
22493 	    * Evaluate field state objects created on this node as well.
22494 	    */
22495 	    head = first;
22496 	    sto = vctxt->xpathStates;
22497 	} else
22498 	    sto = sto->next;
22499     }
22500     return (resolved);
22501 }
22502 
22503 static const xmlChar *
xmlSchemaFormatIDCKeySequence_1(xmlSchemaValidCtxtPtr vctxt,xmlChar ** buf,xmlSchemaPSVIIDCKeyPtr * seq,int count,int for_hash)22504 xmlSchemaFormatIDCKeySequence_1(xmlSchemaValidCtxtPtr vctxt,
22505 				xmlChar **buf,
22506 				xmlSchemaPSVIIDCKeyPtr *seq,
22507 				int count, int for_hash)
22508 {
22509     int i, res;
22510     xmlChar *value = NULL;
22511 
22512     *buf = xmlStrdup(BAD_CAST "[");
22513     for (i = 0; i < count; i++) {
22514 	*buf = xmlStrcat(*buf, BAD_CAST "'");
22515 	if (!for_hash)
22516 	    res = xmlSchemaGetCanonValueWhtspExt(seq[i]->val,
22517 		    xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type),
22518 		    &value);
22519 	else {
22520 	    res = xmlSchemaGetCanonValueHash(seq[i]->val, &value);
22521 	}
22522 	if (res == 0)
22523 	    *buf = xmlStrcat(*buf, BAD_CAST value);
22524 	else {
22525 	    VERROR_INT("xmlSchemaFormatIDCKeySequence",
22526 		"failed to compute a canonical value");
22527 	    *buf = xmlStrcat(*buf, BAD_CAST "???");
22528 	}
22529 	if (i < count -1)
22530 	    *buf = xmlStrcat(*buf, BAD_CAST "', ");
22531 	else
22532 	    *buf = xmlStrcat(*buf, BAD_CAST "'");
22533 	if (value != NULL) {
22534 	    xmlFree(value);
22535 	    value = NULL;
22536 	}
22537     }
22538     *buf = xmlStrcat(*buf, BAD_CAST "]");
22539 
22540     return (BAD_CAST *buf);
22541 }
22542 
22543 static const xmlChar *
xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,xmlChar ** buf,xmlSchemaPSVIIDCKeyPtr * seq,int count)22544 xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
22545 			      xmlChar **buf,
22546 			      xmlSchemaPSVIIDCKeyPtr *seq,
22547 			      int count)
22548 {
22549     return xmlSchemaFormatIDCKeySequence_1(vctxt, buf, seq, count, 0);
22550 }
22551 
22552 static const xmlChar *
xmlSchemaHashKeySequence(xmlSchemaValidCtxtPtr vctxt,xmlChar ** buf,xmlSchemaPSVIIDCKeyPtr * seq,int count)22553 xmlSchemaHashKeySequence(xmlSchemaValidCtxtPtr vctxt,
22554 			 xmlChar **buf,
22555 			 xmlSchemaPSVIIDCKeyPtr *seq,
22556 			 int count)
22557 {
22558     return xmlSchemaFormatIDCKeySequence_1(vctxt, buf, seq, count, 1);
22559 }
22560 
22561 /**
22562  * xmlSchemaXPathPop:
22563  * @vctxt: the WXS validation context
22564  *
22565  * Pops all XPath states.
22566  *
22567  * Returns 0 on success and -1 on internal errors.
22568  */
22569 static int
xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)22570 xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)
22571 {
22572     xmlSchemaIDCStateObjPtr sto;
22573     int res;
22574 
22575     if (vctxt->xpathStates == NULL)
22576 	return(0);
22577     sto = vctxt->xpathStates;
22578     do {
22579 	res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22580 	if (res == -1)
22581 	    return (-1);
22582 	sto = sto->next;
22583     } while (sto != NULL);
22584     return(0);
22585 }
22586 
22587 /**
22588  * xmlSchemaXPathProcessHistory:
22589  * @vctxt: the WXS validation context
22590  * @type: the simple/complex type of the current node if any at all
22591  * @val: the precompiled value
22592  *
22593  * Processes and pops the history items of the IDC state objects.
22594  * IDC key-sequences are validated/created on IDC bindings.
22595  *
22596  * Returns 0 on success and -1 on internal errors.
22597  */
22598 static int
xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,int depth)22599 xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
22600 			     int depth)
22601 {
22602     xmlSchemaIDCStateObjPtr sto, nextsto;
22603     int res, matchDepth;
22604     xmlSchemaPSVIIDCKeyPtr key = NULL;
22605     xmlSchemaTypePtr type = vctxt->inode->typeDef, simpleType = NULL;
22606 
22607     if (vctxt->xpathStates == NULL)
22608 	return (0);
22609     sto = vctxt->xpathStates;
22610 
22611     /*
22612     * Evaluate the state objects.
22613     */
22614     while (sto != NULL) {
22615 	res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22616 	if (res == -1) {
22617 	    VERROR_INT("xmlSchemaXPathProcessHistory",
22618 		"calling xmlStreamPop()");
22619 	    return (-1);
22620 	}
22621 	if (sto->nbHistory == 0)
22622 	    goto deregister_check;
22623 
22624 	matchDepth = sto->history[sto->nbHistory -1];
22625 
22626 	/*
22627 	* Only matches at the current depth are of interest.
22628 	*/
22629 	if (matchDepth != depth) {
22630 	    sto = sto->next;
22631 	    continue;
22632 	}
22633 	if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22634 	    /*
22635 	    * NOTE: According to
22636 	    *   http://www.w3.org/Bugs/Public/show_bug.cgi?id=2198
22637 	    *   ... the simple-content of complex types is also allowed.
22638 	    */
22639 
22640 	    if (WXS_IS_COMPLEX(type)) {
22641 		if (WXS_HAS_SIMPLE_CONTENT(type)) {
22642 		    /*
22643 		    * Sanity check for complex types with simple content.
22644 		    */
22645 		    simpleType = type->contentTypeDef;
22646 		    if (simpleType == NULL) {
22647 			VERROR_INT("xmlSchemaXPathProcessHistory",
22648 			    "field resolves to a CT with simple content "
22649 			    "but the CT is missing the ST definition");
22650 			return (-1);
22651 		    }
22652 		} else
22653 		    simpleType = NULL;
22654 	    } else
22655 		simpleType = type;
22656 	    if (simpleType == NULL) {
22657 		xmlChar *str = NULL;
22658 
22659 		/*
22660 		* Not qualified if the field resolves to a node of non
22661 		* simple type.
22662 		*/
22663 		xmlSchemaCustomErr(ACTXT_CAST vctxt,
22664 		    XML_SCHEMAV_CVC_IDC, NULL,
22665 		    WXS_BASIC_CAST sto->matcher->aidc->def,
22666 		    "The XPath '%s' of a field of %s does evaluate to a node of "
22667 		    "non-simple type",
22668 		    sto->sel->xpath,
22669 		    xmlSchemaGetIDCDesignation(&str, sto->matcher->aidc->def));
22670 		FREE_AND_NULL(str);
22671 		sto->nbHistory--;
22672 		goto deregister_check;
22673 	    }
22674 
22675 	    if ((key == NULL) && (vctxt->inode->val == NULL)) {
22676 		/*
22677 		* Failed to provide the normalized value; maybe
22678 		* the value was invalid.
22679 		*/
22680 		VERROR(XML_SCHEMAV_CVC_IDC,
22681 		    WXS_BASIC_CAST sto->matcher->aidc->def,
22682 		    "Warning: No precomputed value available, the value "
22683 		    "was either invalid or something strange happened");
22684 		sto->nbHistory--;
22685 		goto deregister_check;
22686 	    } else {
22687 		xmlSchemaIDCMatcherPtr matcher = sto->matcher;
22688 		xmlSchemaPSVIIDCKeyPtr *keySeq;
22689 		int pos, idx;
22690 
22691 		/*
22692 		* The key will be anchored on the matcher's list of
22693 		* key-sequences. The position in this list is determined
22694 		* by the target node's depth relative to the matcher's
22695 		* depth of creation (i.e. the depth of the scope element).
22696 		*
22697 		* Element        Depth    Pos   List-entries
22698 		* <scope>          0              NULL
22699 		*   <bar>          1              NULL
22700 		*     <target/>    2       2      target
22701 		*   <bar>
22702                 * </scope>
22703 		*
22704 		* The size of the list is only dependent on the depth of
22705 		* the tree.
22706 		* An entry will be NULLed in selector_leave, i.e. when
22707 		* we hit the target's
22708 		*/
22709 		pos = sto->depth - matcher->depth;
22710 		idx = sto->sel->index;
22711 
22712 		/*
22713 		* Create/grow the array of key-sequences.
22714 		*/
22715                 if (pos >= matcher->sizeKeySeqs) {
22716                     xmlSchemaPSVIIDCKeyPtr **tmp;
22717                     int oldSize = matcher->sizeKeySeqs;
22718                     int newSize, i;
22719 
22720                     newSize = xmlGrowCapacity(pos, sizeof(tmp[0]),
22721                                               10, XML_MAX_ITEMS);
22722                     if (newSize < 0) {
22723                         xmlSchemaVErrMemory(vctxt);
22724                         return (-1);
22725                     }
22726                     tmp = xmlRealloc(matcher->keySeqs,
22727                                      newSize * sizeof(tmp[0]));
22728                     if (tmp == NULL) {
22729                         xmlSchemaVErrMemory(vctxt);
22730                         return (-1);
22731                     }
22732 
22733                     matcher->keySeqs = tmp;
22734                     matcher->sizeKeySeqs = newSize;
22735 
22736 		    /*
22737 		    * The array needs to be NULLed.
22738 		    * TODO: Use memset?
22739 		    */
22740 		    for (i = oldSize; i < newSize; i++)
22741 			matcher->keySeqs[i] = NULL;
22742 		}
22743 
22744 		/*
22745 		* Get/create the key-sequence.
22746 		*/
22747 		keySeq = matcher->keySeqs[pos];
22748 		if (keySeq == NULL) {
22749 		    goto create_sequence;
22750 		} else if (keySeq[idx] != NULL) {
22751 		    xmlChar *str = NULL;
22752 		    /*
22753 		    * cvc-identity-constraint:
22754 		    * 3 For each node in the `target node set` all
22755 		    * of the {fields}, with that node as the context
22756 		    * node, evaluate to either an empty node-set or
22757 		    * a node-set with exactly one member, which must
22758 		    * have a simple type.
22759 		    *
22760 		    * The key was already set; report an error.
22761 		    */
22762 		    xmlSchemaCustomErr(ACTXT_CAST vctxt,
22763 			XML_SCHEMAV_CVC_IDC, NULL,
22764 			WXS_BASIC_CAST matcher->aidc->def,
22765 			"The XPath '%s' of a field of %s evaluates to a "
22766 			"node-set with more than one member",
22767 			sto->sel->xpath,
22768 			xmlSchemaGetIDCDesignation(&str, matcher->aidc->def));
22769 		    FREE_AND_NULL(str);
22770 		    sto->nbHistory--;
22771 		    goto deregister_check;
22772 		} else
22773 		    goto create_key;
22774 
22775 create_sequence:
22776 		/*
22777 		* Create a key-sequence.
22778 		*/
22779 		keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
22780 		    matcher->aidc->def->nbFields *
22781 		    sizeof(xmlSchemaPSVIIDCKeyPtr));
22782 		if (keySeq == NULL) {
22783 		    xmlSchemaVErrMemory(NULL);
22784 		    return(-1);
22785 		}
22786 		memset(keySeq, 0, matcher->aidc->def->nbFields *
22787 		    sizeof(xmlSchemaPSVIIDCKeyPtr));
22788 		matcher->keySeqs[pos] = keySeq;
22789 create_key:
22790 		/*
22791 		* Create a key once per node only.
22792 		*/
22793 		if (key == NULL) {
22794 		    key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
22795 			sizeof(xmlSchemaPSVIIDCKey));
22796 		    if (key == NULL) {
22797 			xmlSchemaVErrMemory(NULL);
22798 			xmlFree(keySeq);
22799 			matcher->keySeqs[pos] = NULL;
22800 			return(-1);
22801 		    }
22802 		    /*
22803 		    * Consume the compiled value.
22804 		    */
22805 		    key->type = simpleType;
22806 		    key->val = vctxt->inode->val;
22807 		    vctxt->inode->val = NULL;
22808 		    /*
22809 		    * Store the key in a global list.
22810 		    */
22811 		    if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
22812 			xmlSchemaIDCFreeKey(key);
22813 			return (-1);
22814 		    }
22815 		}
22816 		keySeq[idx] = key;
22817 	    }
22818 	} else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22819 
22820 	    xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
22821 	    /* xmlSchemaPSVIIDCBindingPtr bind; */
22822 	    xmlSchemaPSVIIDCNodePtr ntItem;
22823 	    xmlSchemaIDCMatcherPtr matcher;
22824 	    xmlSchemaIDCPtr idc;
22825 	    xmlSchemaItemListPtr targets;
22826 	    int pos, i, j, nbKeys;
22827 	    /*
22828 	    * Here we have the following scenario:
22829 	    * An IDC 'selector' state object resolved to a target node,
22830 	    * during the time this target node was in the
22831 	    * ancestor-or-self axis, the 'field' state object(s) looked
22832 	    * out for matching nodes to create a key-sequence for this
22833 	    * target node. Now we are back to this target node and need
22834 	    * to put the key-sequence, together with the target node
22835 	    * itself, into the node-table of the corresponding IDC
22836 	    * binding.
22837 	    */
22838 	    matcher = sto->matcher;
22839 	    idc = matcher->aidc->def;
22840 	    nbKeys = idc->nbFields;
22841 	    pos = depth - matcher->depth;
22842 	    /*
22843 	    * Check if the matcher has any key-sequences at all, plus
22844 	    * if it has a key-sequence for the current target node.
22845 	    */
22846 	    if ((matcher->keySeqs == NULL) ||
22847 		(matcher->sizeKeySeqs <= pos)) {
22848 		if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22849 		    goto selector_key_error;
22850 		else
22851 		    goto selector_leave;
22852 	    }
22853 
22854 	    keySeq = &(matcher->keySeqs[pos]);
22855 	    if (*keySeq == NULL) {
22856 		if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22857 		    goto selector_key_error;
22858 		else
22859 		    goto selector_leave;
22860 	    }
22861 
22862 	    for (i = 0; i < nbKeys; i++) {
22863 		if ((*keySeq)[i] == NULL) {
22864 		    /*
22865 		    * Not qualified, if not all fields did resolve.
22866 		    */
22867 		    if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
22868 			/*
22869 			* All fields of a "key" IDC must resolve.
22870 			*/
22871 			goto selector_key_error;
22872 		    }
22873 		    goto selector_leave;
22874 		}
22875 	    }
22876 	    /*
22877 	    * All fields did resolve.
22878 	    */
22879 
22880 	    /*
22881 	    * 4.1 If the {identity-constraint category} is unique(/key),
22882 	    * then no two members of the `qualified node set` have
22883 	    * `key-sequences` whose members are pairwise equal, as
22884 	    * defined by Equal in [XML Schemas: Datatypes].
22885 	    *
22886 	    * Get the IDC binding from the matcher and check for
22887 	    * duplicate key-sequences.
22888 	    */
22889 #if 0
22890 	    bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
22891 #endif
22892 	    targets = xmlSchemaIDCAcquireTargetList(vctxt, matcher);
22893             if (targets == NULL)
22894                 return(-1);
22895 
22896 	    if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
22897 		(targets->nbItems != 0)) {
22898 		xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
22899 		xmlIDCHashEntryPtr e;
22900 
22901 		res = 0;
22902 
22903 		if (!matcher->htab)
22904 		    e = NULL;
22905 		else {
22906 		    xmlChar *value = NULL;
22907 		    xmlSchemaHashKeySequence(vctxt, &value, *keySeq, nbKeys);
22908 		    e = xmlHashLookup(matcher->htab, value);
22909 		    FREE_AND_NULL(value);
22910 		}
22911 
22912 		/*
22913 		* Compare the key-sequences, key by key.
22914 		*/
22915 		for (;e; e = e->next) {
22916 		    bkeySeq =
22917 			((xmlSchemaPSVIIDCNodePtr) targets->items[e->index])->keys;
22918 		    for (j = 0; j < nbKeys; j++) {
22919 			ckey = (*keySeq)[j];
22920 			bkey = bkeySeq[j];
22921 			res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
22922 			if (res == -1) {
22923 			    return (-1);
22924 			} else if (res == 0) {
22925 			    /*
22926 			    * One of the keys differs, so the key-sequence
22927 			    * won't be equal; get out.
22928 			    */
22929 			    break;
22930 			}
22931 		    }
22932 		    if (res == 1) {
22933 			/*
22934 			* Duplicate key-sequence found.
22935 			*/
22936 			break;
22937 		    }
22938 		}
22939 		if (e) {
22940 		    xmlChar *str = NULL, *strB = NULL;
22941 		    /*
22942 		    * TODO: Try to report the key-sequence.
22943 		    */
22944 		    xmlSchemaCustomErr(ACTXT_CAST vctxt,
22945 			XML_SCHEMAV_CVC_IDC, NULL,
22946 			WXS_BASIC_CAST idc,
22947 			"Duplicate key-sequence %s in %s",
22948 			xmlSchemaFormatIDCKeySequence(vctxt, &str,
22949 			    (*keySeq), nbKeys),
22950 			xmlSchemaGetIDCDesignation(&strB, idc));
22951 		    FREE_AND_NULL(str);
22952 		    FREE_AND_NULL(strB);
22953 		    goto selector_leave;
22954 		}
22955 	    }
22956 	    /*
22957 	    * Add a node-table item to the IDC binding.
22958 	    */
22959 	    ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
22960 		sizeof(xmlSchemaPSVIIDCNode));
22961 	    if (ntItem == NULL) {
22962 		xmlSchemaVErrMemory(NULL);
22963 		xmlFree(*keySeq);
22964 		*keySeq = NULL;
22965 		return(-1);
22966 	    }
22967 	    memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
22968 
22969 	    /*
22970 	    * Store the node-table item in a global list.
22971 	    */
22972 	    if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
22973 		if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
22974 		    xmlFree(ntItem);
22975 		    xmlFree(*keySeq);
22976 		    *keySeq = NULL;
22977 		    return (-1);
22978 		}
22979 		ntItem->nodeQNameID = -1;
22980 	    } else {
22981 		/*
22982 		* Save a cached QName for this node on the IDC node, to be
22983 		* able to report it, even if the node is not saved.
22984 		*/
22985 		ntItem->nodeQNameID = xmlSchemaVAddNodeQName(vctxt,
22986 		    vctxt->inode->localName, vctxt->inode->nsName);
22987 		if (ntItem->nodeQNameID == -1) {
22988 		    xmlFree(ntItem);
22989 		    xmlFree(*keySeq);
22990 		    *keySeq = NULL;
22991 		    return (-1);
22992 		}
22993 	    }
22994 	    /*
22995 	    * Init the node-table item: Save the node, position and
22996 	    * consume the key-sequence.
22997 	    */
22998 	    ntItem->node = vctxt->node;
22999 	    ntItem->nodeLine = vctxt->inode->nodeLine;
23000 	    ntItem->keys = *keySeq;
23001 	    *keySeq = NULL;
23002 #if 0
23003 	    if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1)
23004 #endif
23005 	    if (xmlSchemaItemListAdd(targets, ntItem) == -1) {
23006 		if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23007 		    /*
23008 		    * Free the item, since keyref items won't be
23009 		    * put on a global list.
23010 		    */
23011 		    xmlFree(ntItem->keys);
23012 		    xmlFree(ntItem);
23013 		}
23014 		return (-1);
23015 	    }
23016 	    if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
23017 		xmlChar *value = NULL;
23018 		xmlIDCHashEntryPtr r, e;
23019 		if (!matcher->htab)
23020 		  matcher->htab = xmlHashCreate(4);
23021 		xmlSchemaHashKeySequence(vctxt, &value, ntItem->keys, nbKeys);
23022 		e = xmlMalloc(sizeof *e);
23023                 if (e == NULL) {
23024                     xmlSchemaVErrMemory(vctxt);
23025                     goto mem_error;
23026                 }
23027 		e->index = targets->nbItems - 1;
23028 		r = xmlHashLookup(matcher->htab, value);
23029 		if (r) {
23030 		    e->next = r->next;
23031 		    r->next = e;
23032 		} else {
23033 		    e->next = NULL;
23034 		    if (xmlHashAddEntry(matcher->htab, value, e) < 0) {
23035                         xmlSchemaVErrMemory(vctxt);
23036                         xmlFree(e);
23037                     }
23038 		}
23039 mem_error:
23040 		FREE_AND_NULL(value);
23041 	    }
23042 
23043 	    goto selector_leave;
23044 selector_key_error:
23045 	    {
23046 		xmlChar *str = NULL;
23047 		/*
23048 		* 4.2.1 (KEY) The `target node set` and the
23049 		* `qualified node set` are equal, that is, every
23050 		* member of the `target node set` is also a member
23051 		* of the `qualified node set` and vice versa.
23052 		*/
23053 		xmlSchemaCustomErr(ACTXT_CAST vctxt,
23054 		    XML_SCHEMAV_CVC_IDC, NULL,
23055 		    WXS_BASIC_CAST idc,
23056 		    "Not all fields of %s evaluate to a node",
23057 		    xmlSchemaGetIDCDesignation(&str, idc), NULL);
23058 		FREE_AND_NULL(str);
23059 	    }
23060 selector_leave:
23061 	    /*
23062 	    * Free the key-sequence if not added to the IDC table.
23063 	    */
23064 	    if ((keySeq != NULL) && (*keySeq != NULL)) {
23065 		xmlFree(*keySeq);
23066 		*keySeq = NULL;
23067 	    }
23068 	} /* if selector */
23069 
23070 	sto->nbHistory--;
23071 
23072 deregister_check:
23073 	/*
23074 	* Deregister state objects if they reach the depth of creation.
23075 	*/
23076 	if ((sto->nbHistory == 0) && (sto->depth == depth)) {
23077 	    if (vctxt->xpathStates != sto) {
23078 		VERROR_INT("xmlSchemaXPathProcessHistory",
23079 		    "The state object to be removed is not the first "
23080 		    "in the list");
23081 	    }
23082 	    nextsto = sto->next;
23083 	    /*
23084 	    * Unlink from the list of active XPath state objects.
23085 	    */
23086 	    vctxt->xpathStates = sto->next;
23087 	    sto->next = vctxt->xpathStatePool;
23088 	    /*
23089 	    * Link it to the pool of reusable state objects.
23090 	    */
23091 	    vctxt->xpathStatePool = sto;
23092 	    sto = nextsto;
23093 	} else
23094 	    sto = sto->next;
23095     } /* while (sto != NULL) */
23096     return (0);
23097 }
23098 
23099 /**
23100  * xmlSchemaIDCRegisterMatchers:
23101  * @vctxt: the WXS validation context
23102  * @elemDecl: the element declaration
23103  *
23104  * Creates helper objects to evaluate IDC selectors/fields
23105  * successively.
23106  *
23107  * Returns 0 if OK and -1 on internal errors.
23108  */
23109 static int
xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,xmlSchemaElementPtr elemDecl)23110 xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
23111 			     xmlSchemaElementPtr elemDecl)
23112 {
23113     xmlSchemaIDCMatcherPtr matcher, last = NULL;
23114     xmlSchemaIDCPtr idc, refIdc;
23115     xmlSchemaIDCAugPtr aidc;
23116 
23117     idc = (xmlSchemaIDCPtr) elemDecl->idcs;
23118     if (idc == NULL)
23119 	return (0);
23120 
23121     if (vctxt->inode->idcMatchers != NULL) {
23122 	VERROR_INT("xmlSchemaIDCRegisterMatchers",
23123 	    "The chain of IDC matchers is expected to be empty");
23124 	return (-1);
23125     }
23126     do {
23127 	if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23128 	    /*
23129 	    * Since IDCs bubbles are expensive we need to know the
23130 	    * depth at which the bubbles should stop; this will be
23131 	    * the depth of the top-most keyref IDC. If no keyref
23132 	    * references a key/unique IDC, the keyrefDepth will
23133 	    * be -1, indicating that no bubbles are needed.
23134 	    */
23135 	    refIdc = (xmlSchemaIDCPtr) idc->ref->item;
23136 	    if (refIdc != NULL) {
23137 		/*
23138 		* Remember that we have keyrefs on this node.
23139 		*/
23140 		vctxt->inode->hasKeyrefs = 1;
23141 		/*
23142 		* Lookup the referenced augmented IDC info.
23143 		*/
23144 		aidc = vctxt->aidcs;
23145 		while (aidc != NULL) {
23146 		    if (aidc->def == refIdc)
23147 			break;
23148 		    aidc = aidc->next;
23149 		}
23150 		if (aidc == NULL) {
23151 		    VERROR_INT("xmlSchemaIDCRegisterMatchers",
23152 			"Could not find an augmented IDC item for an IDC "
23153 			"definition");
23154 		    return (-1);
23155 		}
23156 		if ((aidc->keyrefDepth == -1) ||
23157 		    (vctxt->depth < aidc->keyrefDepth))
23158 		    aidc->keyrefDepth = vctxt->depth;
23159 	    }
23160 	}
23161 	/*
23162 	* Lookup the augmented IDC item for the IDC definition.
23163 	*/
23164 	aidc = vctxt->aidcs;
23165 	while (aidc != NULL) {
23166 	    if (aidc->def == idc)
23167 		break;
23168 	    aidc = aidc->next;
23169 	}
23170 	if (aidc == NULL) {
23171 	    VERROR_INT("xmlSchemaIDCRegisterMatchers",
23172 		"Could not find an augmented IDC item for an IDC definition");
23173 	    return (-1);
23174 	}
23175 	/*
23176 	* Create an IDC matcher for every IDC definition.
23177 	*/
23178 	if (vctxt->idcMatcherCache != NULL) {
23179 	    /*
23180 	    * Reuse a cached matcher.
23181 	    */
23182 	    matcher = vctxt->idcMatcherCache;
23183 	    vctxt->idcMatcherCache = matcher->nextCached;
23184 	    matcher->nextCached = NULL;
23185 	} else {
23186 	    matcher = (xmlSchemaIDCMatcherPtr)
23187 		xmlMalloc(sizeof(xmlSchemaIDCMatcher));
23188 	    if (matcher == NULL) {
23189 		xmlSchemaVErrMemory(vctxt);
23190 		return (-1);
23191 	    }
23192 	    memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
23193 	}
23194 	if (last == NULL)
23195 	    vctxt->inode->idcMatchers = matcher;
23196 	else
23197 	    last->next = matcher;
23198 	last = matcher;
23199 
23200 	matcher->type = IDC_MATCHER;
23201 	matcher->depth = vctxt->depth;
23202 	matcher->aidc = aidc;
23203 	matcher->idcType = aidc->def->type;
23204 	/*
23205 	* Init the automaton state object.
23206 	*/
23207 	if (xmlSchemaIDCAddStateObject(vctxt, matcher,
23208 	    idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
23209 	    return (-1);
23210 
23211 	idc = idc->next;
23212     } while (idc != NULL);
23213     return (0);
23214 }
23215 
23216 static int
xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,xmlSchemaNodeInfoPtr ielem)23217 xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,
23218 			   xmlSchemaNodeInfoPtr ielem)
23219 {
23220     xmlSchemaPSVIIDCBindingPtr bind;
23221     int res, i, j, k, nbTargets, nbFields, nbDupls, nbNodeTable;
23222     xmlSchemaPSVIIDCKeyPtr *keys, *ntkeys;
23223     xmlSchemaPSVIIDCNodePtr *targets, *dupls;
23224 
23225     xmlSchemaIDCMatcherPtr matcher = ielem->idcMatchers;
23226     /* vctxt->createIDCNodeTables */
23227     while (matcher != NULL) {
23228 	/*
23229 	* Skip keyref IDCs and empty IDC target-lists.
23230 	*/
23231 	if ((matcher->aidc->def->type == XML_SCHEMA_TYPE_IDC_KEYREF) ||
23232 	    WXS_ILIST_IS_EMPTY(matcher->targets))
23233 	{
23234 	    matcher = matcher->next;
23235 	    continue;
23236 	}
23237 	/*
23238 	* If we _want_ the IDC node-table to be created in any case
23239 	* then do so. Otherwise create them only if keyrefs need them.
23240 	*/
23241 	if ((! vctxt->createIDCNodeTables) &&
23242 	    ((matcher->aidc->keyrefDepth == -1) ||
23243 	     (matcher->aidc->keyrefDepth > vctxt->depth)))
23244 	{
23245 	    matcher = matcher->next;
23246 	    continue;
23247 	}
23248 	/*
23249 	* Get/create the IDC binding on this element for the IDC definition.
23250 	*/
23251 	bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
23252 	if (bind == NULL)
23253 	   goto internal_error;
23254 
23255 	if (! WXS_ILIST_IS_EMPTY(bind->dupls)) {
23256 	    dupls = (xmlSchemaPSVIIDCNodePtr *) bind->dupls->items;
23257 	    nbDupls = bind->dupls->nbItems;
23258 	} else {
23259 	    dupls = NULL;
23260 	    nbDupls = 0;
23261 	}
23262 	if (bind->nodeTable != NULL) {
23263 	    nbNodeTable = bind->nbNodes;
23264 	} else {
23265 	    nbNodeTable = 0;
23266 	}
23267 
23268 	if ((nbNodeTable == 0) && (nbDupls == 0)) {
23269 	    /*
23270 	    * Transfer all IDC target-nodes to the IDC node-table.
23271 	    */
23272             if (bind->nodeTable != NULL)
23273                 xmlFree(bind->nodeTable);
23274 	    bind->nodeTable =
23275 		(xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23276 	    bind->sizeNodes = matcher->targets->sizeItems;
23277 	    bind->nbNodes = matcher->targets->nbItems;
23278 
23279 	    matcher->targets->items = NULL;
23280 	    matcher->targets->sizeItems = 0;
23281 	    matcher->targets->nbItems = 0;
23282 	    if (matcher->htab) {
23283 		xmlHashFree(matcher->htab, xmlFreeIDCHashEntry);
23284 		matcher->htab = NULL;
23285 	    }
23286 	} else {
23287 	    /*
23288 	    * Compare the key-sequences and add to the IDC node-table.
23289 	    */
23290 	    nbTargets = matcher->targets->nbItems;
23291 	    targets = (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23292 	    nbFields = matcher->aidc->def->nbFields;
23293 	    i = 0;
23294 	    do {
23295 		keys = targets[i]->keys;
23296 		if (nbDupls) {
23297 		    /*
23298 		    * Search in already found duplicates first.
23299 		    */
23300 		    j = 0;
23301 		    do {
23302 			if (nbFields == 1) {
23303 			    res = xmlSchemaAreValuesEqual(keys[0]->val,
23304 				dupls[j]->keys[0]->val);
23305 			    if (res == -1)
23306 				goto internal_error;
23307 			    if (res == 1) {
23308 				/*
23309 				* Equal key-sequence.
23310 				*/
23311 				goto next_target;
23312 			    }
23313 			} else {
23314 			    res = 0;
23315 			    ntkeys = dupls[j]->keys;
23316 			    for (k = 0; k < nbFields; k++) {
23317 				res = xmlSchemaAreValuesEqual(keys[k]->val,
23318 				    ntkeys[k]->val);
23319 				if (res == -1)
23320 				    goto internal_error;
23321 				if (res == 0) {
23322 				    /*
23323 				    * One of the keys differs.
23324 				    */
23325 				    break;
23326 				}
23327 			    }
23328 			    if (res == 1) {
23329 				/*
23330 				* Equal key-sequence found.
23331 				*/
23332 				goto next_target;
23333 			    }
23334 			}
23335 			j++;
23336 		    } while (j < nbDupls);
23337 		}
23338 		if (nbNodeTable) {
23339 		    j = 0;
23340 		    do {
23341 			if (nbFields == 1) {
23342 			    res = xmlSchemaAreValuesEqual(keys[0]->val,
23343 				bind->nodeTable[j]->keys[0]->val);
23344 			    if (res == -1)
23345 				goto internal_error;
23346 			    if (res == 0) {
23347 				/*
23348 				* The key-sequence differs.
23349 				*/
23350 				goto next_node_table_entry;
23351 			    }
23352 			} else {
23353 			    res = 0;
23354 			    ntkeys = bind->nodeTable[j]->keys;
23355 			    for (k = 0; k < nbFields; k++) {
23356 				res = xmlSchemaAreValuesEqual(keys[k]->val,
23357 				    ntkeys[k]->val);
23358 				if (res == -1)
23359 				    goto internal_error;
23360 				if (res == 0) {
23361 				    /*
23362 				    * One of the keys differs.
23363 				    */
23364 				    goto next_node_table_entry;
23365 				}
23366 			    }
23367 			}
23368 			/*
23369 			* Add the duplicate to the list of duplicates.
23370 			*/
23371 			if (bind->dupls == NULL) {
23372 			    bind->dupls = xmlSchemaItemListCreate();
23373 			    if (bind->dupls == NULL)
23374 				goto internal_error;
23375 			}
23376 			if (xmlSchemaItemListAdd(bind->dupls, bind->nodeTable[j]) == -1)
23377 			    goto internal_error;
23378 			/*
23379 			* Remove the duplicate entry from the IDC node-table.
23380 			*/
23381 			bind->nodeTable[j] = bind->nodeTable[bind->nbNodes -1];
23382 			bind->nbNodes--;
23383 
23384 			goto next_target;
23385 
23386 next_node_table_entry:
23387 			j++;
23388 		    } while (j < nbNodeTable);
23389 		}
23390 		/*
23391 		* If everything is fine, then add the IDC target-node to
23392 		* the IDC node-table.
23393 		*/
23394 		if (xmlSchemaIDCAppendNodeTableItem(bind, targets[i]) == -1)
23395 		    goto internal_error;
23396 
23397 next_target:
23398 		i++;
23399 	    } while (i < nbTargets);
23400 	}
23401 	matcher = matcher->next;
23402     }
23403     return(0);
23404 
23405 internal_error:
23406     return(-1);
23407 }
23408 
23409 /**
23410  * xmlSchemaBubbleIDCNodeTables:
23411  * @depth: the current tree depth
23412  *
23413  * Merges IDC bindings of an element at @depth into the corresponding IDC
23414  * bindings of its parent element. If a duplicate note-table entry is found,
23415  * both, the parent node-table entry and child entry are discarded from the
23416  * node-table of the parent.
23417  *
23418  * Returns 0 if OK and -1 on internal errors.
23419  */
23420 static int
xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)23421 xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
23422 {
23423     xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
23424     xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL; /* parent IDC bindings. */
23425     xmlSchemaPSVIIDCNodePtr node, parNode = NULL, *dupls, *parNodes; /* node-table entries. */
23426     xmlSchemaIDCAugPtr aidc;
23427     int i, j, k, ret = 0, nbFields, oldNum, oldDupls;
23428 
23429     bind = vctxt->inode->idcTable;
23430     if (bind == NULL) {
23431 	/* Fine, no table, no bubbles. */
23432 	return (0);
23433     }
23434 
23435     parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
23436     /*
23437     * Walk all bindings; create new or add to existing bindings.
23438     * Remove duplicate key-sequences.
23439     */
23440     while (bind != NULL) {
23441 
23442 	if ((bind->nbNodes == 0) && WXS_ILIST_IS_EMPTY(bind->dupls))
23443 	    goto next_binding;
23444 	/*
23445 	* Check if the key/unique IDC table needs to be bubbled.
23446 	*/
23447 	if (! vctxt->createIDCNodeTables) {
23448 	    aidc = vctxt->aidcs;
23449 	    do {
23450 		if (aidc->def == bind->definition) {
23451 		    if ((aidc->keyrefDepth == -1) ||
23452 			(aidc->keyrefDepth >= vctxt->depth)) {
23453 			goto next_binding;
23454 		    }
23455 		    break;
23456 		}
23457 		aidc = aidc->next;
23458 	    } while (aidc != NULL);
23459 	}
23460 
23461 	if (parTable != NULL)
23462 	    parBind = *parTable;
23463 	/*
23464 	* Search a matching parent binding for the
23465 	* IDC definition.
23466 	*/
23467 	while (parBind != NULL) {
23468 	    if (parBind->definition == bind->definition)
23469 		break;
23470 	    parBind = parBind->next;
23471 	}
23472 
23473 	if (parBind != NULL) {
23474 	    /*
23475 	    * Compare every node-table entry of the child node,
23476 	    * i.e. the key-sequence within, ...
23477 	    */
23478 	    oldNum = parBind->nbNodes; /* Skip newly added items. */
23479 
23480 	    if (! WXS_ILIST_IS_EMPTY(parBind->dupls)) {
23481 		oldDupls = parBind->dupls->nbItems;
23482 		dupls = (xmlSchemaPSVIIDCNodePtr *) parBind->dupls->items;
23483 	    } else {
23484 		dupls = NULL;
23485 		oldDupls = 0;
23486 	    }
23487 
23488 	    parNodes = parBind->nodeTable;
23489 	    nbFields = bind->definition->nbFields;
23490 
23491 	    for (i = 0; i < bind->nbNodes; i++) {
23492 		node = bind->nodeTable[i];
23493 		if (node == NULL)
23494 		    continue;
23495 		/*
23496 		* ...with every key-sequence of the parent node, already
23497 		* evaluated to be a duplicate key-sequence.
23498 		*/
23499 		if (oldDupls) {
23500 		    j = 0;
23501 		    while (j < oldDupls) {
23502 			if (nbFields == 1) {
23503 			    ret = xmlSchemaAreValuesEqual(
23504 				node->keys[0]->val,
23505 				dupls[j]->keys[0]->val);
23506 			    if (ret == -1)
23507 				goto internal_error;
23508 			    if (ret == 0) {
23509 				j++;
23510 				continue;
23511 			    }
23512 			} else {
23513 			    parNode = dupls[j];
23514 			    for (k = 0; k < nbFields; k++) {
23515 				ret = xmlSchemaAreValuesEqual(
23516 				    node->keys[k]->val,
23517 				    parNode->keys[k]->val);
23518 				if (ret == -1)
23519 				    goto internal_error;
23520 				if (ret == 0)
23521 				    break;
23522 			    }
23523 			}
23524 			if (ret == 1)
23525 			    /* Duplicate found. */
23526 			    break;
23527 			j++;
23528 		    }
23529 		    if (j != oldDupls) {
23530 			/* Duplicate found. Skip this entry. */
23531 			continue;
23532 		    }
23533 		}
23534 		/*
23535 		* ... and with every key-sequence of the parent node.
23536 		*/
23537 		if (oldNum) {
23538 		    j = 0;
23539 		    while (j < oldNum) {
23540 			parNode = parNodes[j];
23541 			if (nbFields == 1) {
23542 			    ret = xmlSchemaAreValuesEqual(
23543 				node->keys[0]->val,
23544 				parNode->keys[0]->val);
23545 			    if (ret == -1)
23546 				goto internal_error;
23547 			    if (ret == 0) {
23548 				j++;
23549 				continue;
23550 			    }
23551 			} else {
23552 			    for (k = 0; k < nbFields; k++) {
23553 				ret = xmlSchemaAreValuesEqual(
23554 				    node->keys[k]->val,
23555 				    parNode->keys[k]->val);
23556 				if (ret == -1)
23557 				    goto internal_error;
23558 				if (ret == 0)
23559 				    break;
23560 			    }
23561 			}
23562 			if (ret == 1)
23563 			    /* Duplicate found. */
23564 			    break;
23565 			j++;
23566 		    }
23567 		    if (j != oldNum) {
23568 			/*
23569 			* Handle duplicates. Move the duplicate in
23570 			* the parent's node-table to the list of
23571 			* duplicates.
23572 			*/
23573 			oldNum--;
23574 			parBind->nbNodes--;
23575 			/*
23576 			* Move last old item to pos of duplicate.
23577 			*/
23578 			parNodes[j] = parNodes[oldNum];
23579 
23580 			if (parBind->nbNodes != oldNum) {
23581 			    /*
23582 			    * If new items exist, move last new item to
23583 			    * last of old items.
23584 			    */
23585 			    parNodes[oldNum] =
23586 				parNodes[parBind->nbNodes];
23587 			}
23588 			if (parBind->dupls == NULL) {
23589 			    parBind->dupls = xmlSchemaItemListCreate();
23590 			    if (parBind->dupls == NULL)
23591 				goto internal_error;
23592 			}
23593 			xmlSchemaItemListAdd(parBind->dupls, parNode);
23594 		    } else {
23595 			/*
23596 			* Add the node-table entry (node and key-sequence) of
23597 			* the child node to the node table of the parent node.
23598 			*/
23599                         if (parBind->nbNodes >= parBind->sizeNodes) {
23600                             xmlSchemaPSVIIDCNodePtr *tmp;
23601                             int newSize;
23602 
23603                             newSize = xmlGrowCapacity(parBind->sizeNodes,
23604                                                       sizeof(tmp[0]),
23605                                                       10, XML_MAX_ITEMS);
23606                             if (newSize < 0) {
23607                                 xmlSchemaVErrMemory(vctxt);
23608                                 goto internal_error;
23609                             }
23610                             tmp = xmlRealloc(parBind->nodeTable,
23611                                              newSize * sizeof(tmp[0]));
23612                             if (tmp == NULL) {
23613                                 xmlSchemaVErrMemory(vctxt);
23614                                 goto internal_error;
23615                             }
23616 
23617                             parBind->nodeTable = tmp;
23618                             parBind->sizeNodes = newSize;
23619 			}
23620 			parNodes = parBind->nodeTable;
23621 			/*
23622 			* Append the new node-table entry to the 'new node-table
23623 			* entries' section.
23624 			*/
23625 			parNodes[parBind->nbNodes++] = node;
23626 		    }
23627 
23628 		}
23629 
23630 	    }
23631 	} else {
23632 	    /*
23633 	    * No binding for the IDC was found: create a new one and
23634 	    * copy all node-tables.
23635 	    */
23636 	    parBind = xmlSchemaIDCNewBinding(bind->definition);
23637 	    if (parBind == NULL)
23638 		goto internal_error;
23639 
23640 	    /*
23641 	    * TODO: Hmm, how to optimize the initial number of
23642 	    * allocated entries?
23643 	    */
23644 	    if (bind->nbNodes != 0) {
23645 		/*
23646 		* Add all IDC node-table entries.
23647 		*/
23648 		if (! vctxt->psviExposeIDCNodeTables) {
23649 		    /*
23650 		    * Just move the entries.
23651 		    * NOTE: this is quite save here, since
23652 		    * all the keyref lookups have already been
23653 		    * performed.
23654 		    */
23655 		    parBind->nodeTable = bind->nodeTable;
23656 		    bind->nodeTable = NULL;
23657 		    parBind->sizeNodes = bind->sizeNodes;
23658 		    bind->sizeNodes = 0;
23659 		    parBind->nbNodes = bind->nbNodes;
23660 		    bind->nbNodes = 0;
23661 		} else {
23662 		    /*
23663 		    * Copy the entries.
23664 		    */
23665 		    parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23666 			xmlMalloc(bind->nbNodes *
23667 			sizeof(xmlSchemaPSVIIDCNodePtr));
23668 		    if (parBind->nodeTable == NULL) {
23669 			xmlSchemaVErrMemory(NULL);
23670 			xmlSchemaIDCFreeBinding(parBind);
23671 			goto internal_error;
23672 		    }
23673 		    parBind->sizeNodes = bind->nbNodes;
23674 		    parBind->nbNodes = bind->nbNodes;
23675 		    memcpy(parBind->nodeTable, bind->nodeTable,
23676 			bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
23677 		}
23678 	    }
23679 	    if (bind->dupls) {
23680 		/*
23681 		* Move the duplicates.
23682 		*/
23683 		if (parBind->dupls != NULL)
23684 		    xmlSchemaItemListFree(parBind->dupls);
23685 		parBind->dupls = bind->dupls;
23686 		bind->dupls = NULL;
23687 	    }
23688             if (parTable != NULL) {
23689                 if (*parTable == NULL)
23690                     *parTable = parBind;
23691                 else {
23692                     parBind->next = *parTable;
23693                     *parTable = parBind;
23694                 }
23695             }
23696 	}
23697 
23698 next_binding:
23699 	bind = bind->next;
23700     }
23701     return (0);
23702 
23703 internal_error:
23704     return(-1);
23705 }
23706 
23707 /**
23708  * xmlSchemaCheckCVCIDCKeyRef:
23709  * @vctxt: the WXS validation context
23710  * @elemDecl: the element declaration
23711  *
23712  * Check the cvc-idc-keyref constraints.
23713  */
23714 static int
xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)23715 xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
23716 {
23717     xmlSchemaIDCMatcherPtr matcher;
23718     xmlSchemaPSVIIDCBindingPtr bind;
23719 
23720     matcher = vctxt->inode->idcMatchers;
23721     /*
23722     * Find a keyref.
23723     */
23724     while (matcher != NULL) {
23725 	if ((matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) &&
23726 	    matcher->targets &&
23727 	    matcher->targets->nbItems)
23728 	{
23729 	    int i, j, k, res, nbFields, hasDupls;
23730 	    xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
23731 	    xmlSchemaPSVIIDCNodePtr refNode = NULL;
23732 	    xmlHashTablePtr table = NULL;
23733 
23734 	    nbFields = matcher->aidc->def->nbFields;
23735 
23736 	    /*
23737 	    * Find the IDC node-table for the referenced IDC key/unique.
23738 	    */
23739 	    bind = vctxt->inode->idcTable;
23740 	    while (bind != NULL) {
23741 		if ((xmlSchemaIDCPtr) matcher->aidc->def->ref->item ==
23742 		    bind->definition)
23743 		    break;
23744 		bind = bind->next;
23745 	    }
23746 	    hasDupls = (bind && bind->dupls && bind->dupls->nbItems) ? 1 : 0;
23747 	    /*
23748 	    * Search for a matching key-sequences.
23749 	    */
23750 	    if (bind) {
23751 		table = xmlHashCreate(bind->nbNodes * 2);
23752 		for (j = 0; j < bind->nbNodes; j++) {
23753 		    xmlChar *value;
23754 		    xmlIDCHashEntryPtr r, e;
23755 		    keys = bind->nodeTable[j]->keys;
23756 		    xmlSchemaHashKeySequence(vctxt, &value, keys, nbFields);
23757 		    e = xmlMalloc(sizeof *e);
23758                     if (e == NULL) {
23759                         xmlSchemaVErrMemory(vctxt);
23760                         goto mem_error;
23761                     }
23762 		    e->index = j;
23763 		    r = xmlHashLookup(table, value);
23764 		    if (r) {
23765 			e->next = r->next;
23766 			r->next = e;
23767 		    } else {
23768 			e->next = NULL;
23769                         if (xmlHashAddEntry(table, value, e) < 0) {
23770                             xmlSchemaVErrMemory(vctxt);
23771                             xmlFree(e);
23772                         }
23773 		    }
23774 mem_error:
23775 		    FREE_AND_NULL(value);
23776 		}
23777 	    }
23778 	    for (i = 0; i < matcher->targets->nbItems; i++) {
23779 		res = 0;
23780 		refNode = matcher->targets->items[i];
23781 		if (bind != NULL) {
23782 		    xmlChar *value;
23783 		    xmlIDCHashEntryPtr e;
23784 		    refKeys = refNode->keys;
23785 		    xmlSchemaHashKeySequence(vctxt, &value, refKeys, nbFields);
23786 		    e = xmlHashLookup(table, value);
23787 		    FREE_AND_NULL(value);
23788 		    res = 0;
23789 		    for (;e; e = e->next) {
23790 			keys = bind->nodeTable[e->index]->keys;
23791 			for (k = 0; k < nbFields; k++) {
23792 			    res = xmlSchemaAreValuesEqual(keys[k]->val,
23793 							  refKeys[k]->val);
23794 			    if (res == 0)
23795 			        break;
23796 			    else if (res == -1) {
23797 				return (-1);
23798 			    }
23799 			}
23800 			if (res == 1) {
23801 			    /*
23802 			     * Match found.
23803 			     */
23804 			    break;
23805 			}
23806 		    }
23807 		    if ((res == 0) && hasDupls) {
23808 			/*
23809 			* Search in duplicates
23810 			*/
23811 			for (j = 0; j < bind->dupls->nbItems; j++) {
23812 			    keys = ((xmlSchemaPSVIIDCNodePtr)
23813 				bind->dupls->items[j])->keys;
23814 			    for (k = 0; k < nbFields; k++) {
23815 				res = xmlSchemaAreValuesEqual(keys[k]->val,
23816 				    refKeys[k]->val);
23817 				if (res == 0)
23818 				    break;
23819 				else if (res == -1) {
23820 				    return (-1);
23821 				}
23822 			    }
23823 			    if (res == 1) {
23824 				/*
23825 				* Match in duplicates found.
23826 				*/
23827 				xmlChar *str = NULL, *strB = NULL;
23828 				xmlSchemaKeyrefErr(vctxt,
23829 				    XML_SCHEMAV_CVC_IDC, refNode,
23830 				    (xmlSchemaTypePtr) matcher->aidc->def,
23831 				    "More than one match found for "
23832 				    "key-sequence %s of keyref '%s'",
23833 				    xmlSchemaFormatIDCKeySequence(vctxt, &str,
23834 					refNode->keys, nbFields),
23835 				    xmlSchemaGetComponentQName(&strB,
23836 					matcher->aidc->def));
23837 				FREE_AND_NULL(str);
23838 				FREE_AND_NULL(strB);
23839 				break;
23840 			    }
23841 			}
23842 		    }
23843 		}
23844 
23845 		if (res == 0) {
23846 		    xmlChar *str = NULL, *strB = NULL;
23847 		    xmlSchemaKeyrefErr(vctxt,
23848 			XML_SCHEMAV_CVC_IDC, refNode,
23849 			(xmlSchemaTypePtr) matcher->aidc->def,
23850 			"No match found for key-sequence %s of keyref '%s'",
23851 			xmlSchemaFormatIDCKeySequence(vctxt, &str,
23852 			    refNode->keys, nbFields),
23853 			xmlSchemaGetComponentQName(&strB, matcher->aidc->def));
23854 		    FREE_AND_NULL(str);
23855 		    FREE_AND_NULL(strB);
23856 		}
23857 	    }
23858 	    if (table) {
23859 		xmlHashFree(table, xmlFreeIDCHashEntry);
23860 	    }
23861 	}
23862 	matcher = matcher->next;
23863     }
23864     /* TODO: Return an error if any error encountered. */
23865     return (0);
23866 }
23867 
23868 /************************************************************************
23869  *									*
23870  *			XML Reader validation code                      *
23871  *									*
23872  ************************************************************************/
23873 
23874 static xmlSchemaAttrInfoPtr
xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)23875 xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
23876 {
23877     xmlSchemaAttrInfoPtr iattr;
23878     /*
23879     * Grow/create list of attribute infos.
23880     */
23881     if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
23882         xmlSchemaAttrInfoPtr *tmp;
23883         int oldSize = vctxt->sizeAttrInfos;
23884         int newSize, i;
23885 
23886         newSize = xmlGrowCapacity(oldSize, sizeof(tmp[0]), 5, XML_MAX_ITEMS);
23887 	if (newSize < 0) {
23888 	    xmlSchemaVErrMemory(vctxt);
23889 	    return (NULL);
23890 	}
23891 	tmp = xmlRealloc(vctxt->attrInfos, newSize * sizeof(tmp[0]));
23892 	if (tmp == NULL) {
23893 	    xmlSchemaVErrMemory(vctxt);
23894 	    return (NULL);
23895 	}
23896 
23897         vctxt->attrInfos = tmp;
23898         vctxt->sizeAttrInfos = newSize;
23899 
23900         for (i = oldSize; i < newSize; i++)
23901             vctxt->attrInfos[i] = NULL;
23902     }
23903 
23904     iattr = vctxt->attrInfos[vctxt->nbAttrInfos];
23905     if (iattr != NULL) {
23906 	if (iattr->localName != NULL) {
23907 	    VERROR_INT("xmlSchemaGetFreshAttrInfo",
23908 		"attr info not cleared");
23909 	    return (NULL);
23910 	}
23911 	iattr->nodeType = XML_ATTRIBUTE_NODE;
23912         vctxt->nbAttrInfos++;
23913 	return (iattr);
23914     }
23915 
23916     /*
23917     * Create an attribute info.
23918     */
23919     iattr = (xmlSchemaAttrInfoPtr)
23920 	xmlMalloc(sizeof(xmlSchemaAttrInfo));
23921     if (iattr == NULL) {
23922 	xmlSchemaVErrMemory(vctxt);
23923 	return (NULL);
23924     }
23925     memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
23926     iattr->nodeType = XML_ATTRIBUTE_NODE;
23927     vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
23928 
23929     return (iattr);
23930 }
23931 
23932 static int
xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,xmlNodePtr attrNode,int nodeLine,const xmlChar * localName,const xmlChar * nsName,int ownedNames,xmlChar * value,int ownedValue)23933 xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
23934 			xmlNodePtr attrNode,
23935 			int nodeLine,
23936 			const xmlChar *localName,
23937 			const xmlChar *nsName,
23938 			int ownedNames,
23939 			xmlChar *value,
23940 			int ownedValue)
23941 {
23942     xmlSchemaAttrInfoPtr attr;
23943 
23944     attr = xmlSchemaGetFreshAttrInfo(vctxt);
23945     if (attr == NULL) {
23946 	VERROR_INT("xmlSchemaPushAttribute",
23947 	    "calling xmlSchemaGetFreshAttrInfo()");
23948 	return (-1);
23949     }
23950     attr->node = attrNode;
23951     attr->nodeLine = nodeLine;
23952     attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
23953     attr->localName = localName;
23954     attr->nsName = nsName;
23955     if (ownedNames)
23956 	attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
23957     /*
23958     * Evaluate if it's an XSI attribute.
23959     */
23960     if (nsName != NULL) {
23961 	if (xmlStrEqual(localName, BAD_CAST "nil")) {
23962 	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23963 		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
23964 	    }
23965 	} else if (xmlStrEqual(localName, BAD_CAST "type")) {
23966 	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23967 		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
23968 	    }
23969 	} else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
23970 	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23971 		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
23972 	    }
23973 	} else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
23974 	    if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23975 		attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
23976 	    }
23977 	} else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
23978 	    attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
23979 	}
23980     }
23981     attr->value = value;
23982     if (ownedValue)
23983 	attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
23984     if (attr->metaType != 0)
23985 	attr->state = XML_SCHEMAS_ATTR_META;
23986     return (0);
23987 }
23988 
23989 /**
23990  * xmlSchemaClearElemInfo:
23991  * @vctxt: the WXS validation context
23992  * @ielem: the element information item
23993  */
23994 static void
xmlSchemaClearElemInfo(xmlSchemaValidCtxtPtr vctxt,xmlSchemaNodeInfoPtr ielem)23995 xmlSchemaClearElemInfo(xmlSchemaValidCtxtPtr vctxt,
23996 		       xmlSchemaNodeInfoPtr ielem)
23997 {
23998     ielem->hasKeyrefs = 0;
23999     ielem->appliedXPath = 0;
24000     if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
24001 	FREE_AND_NULL(ielem->localName);
24002 	FREE_AND_NULL(ielem->nsName);
24003     } else {
24004 	ielem->localName = NULL;
24005 	ielem->nsName = NULL;
24006     }
24007     if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
24008 	FREE_AND_NULL(ielem->value);
24009     } else {
24010 	ielem->value = NULL;
24011     }
24012     if (ielem->val != NULL) {
24013 	/*
24014 	* PSVI TODO: Be careful not to free it when the value is
24015 	* exposed via PSVI.
24016 	*/
24017 	xmlSchemaFreeValue(ielem->val);
24018 	ielem->val = NULL;
24019     }
24020     if (ielem->idcMatchers != NULL) {
24021 	/*
24022 	* REVISIT OPTIMIZE TODO: Use a pool of IDC matchers.
24023 	*   Does it work?
24024 	*/
24025 	xmlSchemaIDCReleaseMatcherList(vctxt, ielem->idcMatchers);
24026 #if 0
24027 	xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
24028 #endif
24029 	ielem->idcMatchers = NULL;
24030     }
24031     if (ielem->idcTable != NULL) {
24032 	/*
24033 	* OPTIMIZE TODO: Use a pool of IDC tables??.
24034 	*/
24035 	xmlSchemaIDCFreeIDCTable(ielem->idcTable);
24036 	ielem->idcTable = NULL;
24037     }
24038     if (ielem->regexCtxt != NULL) {
24039 	xmlRegFreeExecCtxt(ielem->regexCtxt);
24040 	ielem->regexCtxt = NULL;
24041     }
24042     if (ielem->nsBindings != NULL) {
24043 	xmlFree((xmlChar **)ielem->nsBindings);
24044 	ielem->nsBindings = NULL;
24045 	ielem->nbNsBindings = 0;
24046 	ielem->sizeNsBindings = 0;
24047     }
24048 }
24049 
24050 /**
24051  * xmlSchemaGetFreshElemInfo:
24052  * @vctxt: the schema validation context
24053  *
24054  * Creates/reuses and initializes the element info item for
24055  * the current tree depth.
24056  *
24057  * Returns the element info item or NULL on API or internal errors.
24058  */
24059 static xmlSchemaNodeInfoPtr
xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)24060 xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
24061 {
24062     xmlSchemaNodeInfoPtr info = NULL;
24063 
24064     if (vctxt->depth > vctxt->sizeElemInfos) {
24065 	VERROR_INT("xmlSchemaGetFreshElemInfo",
24066 	    "inconsistent depth encountered");
24067 	return (NULL);
24068     }
24069     if (vctxt->sizeElemInfos <= vctxt->depth) {
24070         xmlSchemaNodeInfoPtr *tmp;
24071         int oldSize = vctxt->sizeElemInfos;
24072         int newSize, i;
24073 
24074         newSize = xmlGrowCapacity(oldSize, sizeof(tmp[0]), 10, XML_MAX_ITEMS);
24075         if (newSize < 0) {
24076             xmlSchemaVErrMemory(vctxt);
24077             return (NULL);
24078         }
24079         tmp = xmlRealloc(vctxt->elemInfos, newSize * sizeof(tmp[0]));
24080         if (tmp == NULL) {
24081             xmlSchemaVErrMemory(vctxt);
24082             return (NULL);
24083         }
24084 
24085         vctxt->elemInfos = tmp;
24086         vctxt->sizeElemInfos = newSize;
24087 
24088 	/*
24089 	* We need the new memory to be NULLed.
24090 	* TODO: Use memset instead?
24091 	*/
24092 	for (i = oldSize; i < newSize; i++)
24093 	    vctxt->elemInfos[i] = NULL;
24094     } else
24095 	info = vctxt->elemInfos[vctxt->depth];
24096 
24097     if (info == NULL) {
24098 	info = (xmlSchemaNodeInfoPtr)
24099 	    xmlMalloc(sizeof(xmlSchemaNodeInfo));
24100 	if (info == NULL) {
24101 	    xmlSchemaVErrMemory(vctxt);
24102 	    return (NULL);
24103 	}
24104 	vctxt->elemInfos[vctxt->depth] = info;
24105     } else {
24106 	if (info->localName != NULL) {
24107 	    VERROR_INT("xmlSchemaGetFreshElemInfo",
24108 		"elem info has not been cleared");
24109 	    return (NULL);
24110 	}
24111     }
24112     memset(info, 0, sizeof(xmlSchemaNodeInfo));
24113     info->nodeType = XML_ELEMENT_NODE;
24114     info->depth = vctxt->depth;
24115 
24116     return (info);
24117 }
24118 
24119 #define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
24120 #define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
24121 #define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
24122 
24123 static int
xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,xmlNodePtr node,xmlSchemaTypePtr type,xmlSchemaValType valType,const xmlChar * value,xmlSchemaValPtr val,unsigned long length,int fireErrors)24124 xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
24125 			xmlNodePtr node,
24126 			xmlSchemaTypePtr type,
24127 			xmlSchemaValType valType,
24128 			const xmlChar * value,
24129 			xmlSchemaValPtr val,
24130 			unsigned long length,
24131 			int fireErrors)
24132 {
24133     int ret, error = 0, found;
24134 
24135     xmlSchemaTypePtr tmpType;
24136     xmlSchemaFacetLinkPtr facetLink;
24137     xmlSchemaFacetPtr facet;
24138     unsigned long len = 0;
24139     xmlSchemaWhitespaceValueType ws;
24140 
24141     /*
24142     * In Libxml2, derived built-in types have currently no explicit facets.
24143     */
24144     if (type->type == XML_SCHEMA_TYPE_BASIC)
24145 	return (0);
24146 
24147     /*
24148     * NOTE: Do not jump away, if the facetSet of the given type is
24149     * empty: until now, "pattern" and "enumeration" facets of the
24150     * *base types* need to be checked as well.
24151     */
24152     if (type->facetSet == NULL)
24153 	goto pattern_and_enum;
24154 
24155     if (! WXS_IS_ATOMIC(type)) {
24156 	if (WXS_IS_LIST(type))
24157 	    goto WXS_IS_LIST;
24158 	else
24159 	    goto pattern_and_enum;
24160     }
24161 
24162     /*
24163     * Whitespace handling is only of importance for string-based
24164     * types.
24165     */
24166     tmpType = xmlSchemaGetPrimitiveType(type);
24167     if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
24168 	WXS_IS_ANY_SIMPLE_TYPE(tmpType)) {
24169 	ws = xmlSchemaGetWhiteSpaceFacetValue(type);
24170     } else
24171 	ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
24172 
24173     /*
24174     * If the value was not computed (for string or
24175     * anySimpleType based types), then use the provided
24176     * type.
24177     */
24178     if (val != NULL)
24179 	valType = xmlSchemaGetValType(val);
24180 
24181     ret = 0;
24182     for (facetLink = type->facetSet; facetLink != NULL;
24183 	facetLink = facetLink->next) {
24184 	/*
24185 	* Skip the pattern "whiteSpace": it is used to
24186 	* format the character content beforehand.
24187 	*/
24188 	switch (facetLink->facet->type) {
24189 	    case XML_SCHEMA_FACET_WHITESPACE:
24190 	    case XML_SCHEMA_FACET_PATTERN:
24191 	    case XML_SCHEMA_FACET_ENUMERATION:
24192 		continue;
24193 	    case XML_SCHEMA_FACET_LENGTH:
24194 	    case XML_SCHEMA_FACET_MINLENGTH:
24195 	    case XML_SCHEMA_FACET_MAXLENGTH:
24196 		ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
24197 		    valType, value, val, &len, ws);
24198 		break;
24199 	    default:
24200 		ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
24201 		    valType, value, val, ws);
24202 		break;
24203 	}
24204 	if (ret < 0) {
24205 	    AERROR_INT("xmlSchemaValidateFacets",
24206 		"validating against a atomic type facet");
24207 	    return (-1);
24208 	} else if (ret > 0) {
24209 	    if (fireErrors)
24210 		xmlSchemaFacetErr(actxt, ret, node,
24211 		value, len, type, facetLink->facet, NULL, NULL, NULL);
24212 	    else
24213 		return (ret);
24214 	    if (error == 0)
24215 		error = ret;
24216 	}
24217 	ret = 0;
24218     }
24219 
24220 WXS_IS_LIST:
24221     if (! WXS_IS_LIST(type))
24222 	goto pattern_and_enum;
24223     /*
24224     * "length", "minLength" and "maxLength" of list types.
24225     */
24226     ret = 0;
24227     for (facetLink = type->facetSet; facetLink != NULL;
24228 	facetLink = facetLink->next) {
24229 
24230 	switch (facetLink->facet->type) {
24231 	    case XML_SCHEMA_FACET_LENGTH:
24232 	    case XML_SCHEMA_FACET_MINLENGTH:
24233 	    case XML_SCHEMA_FACET_MAXLENGTH:
24234 		ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
24235 		    value, length, NULL);
24236 		break;
24237 	    default:
24238 		continue;
24239 	}
24240 	if (ret < 0) {
24241 	    AERROR_INT("xmlSchemaValidateFacets",
24242 		"validating against a list type facet");
24243 	    return (-1);
24244 	} else if (ret > 0) {
24245 	    if (fireErrors)
24246 		xmlSchemaFacetErr(actxt, ret, node,
24247 		value, length, type, facetLink->facet, NULL, NULL, NULL);
24248 	    else
24249 		return (ret);
24250 	    if (error == 0)
24251 		error = ret;
24252 	}
24253 	ret = 0;
24254     }
24255 
24256 pattern_and_enum:
24257     found = 0;
24258     /*
24259     * Process enumerations. Facet values are in the value space
24260     * of the defining type's base type. This seems to be a bug in the
24261     * XML Schema 1.0 spec. Use the whitespace type of the base type.
24262     * Only the first set of enumerations in the ancestor-or-self axis
24263     * is used for validation.
24264     */
24265     ret = 0;
24266     tmpType = type;
24267     do {
24268         for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
24269             if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
24270                 continue;
24271             found = 1;
24272             ret = xmlSchemaAreValuesEqual(facet->val, val);
24273             if (ret == 1)
24274                 break;
24275             else if (ret < 0) {
24276                 AERROR_INT("xmlSchemaValidateFacets",
24277                     "validating against an enumeration facet");
24278                 return (-1);
24279             }
24280         }
24281         if (ret != 0)
24282             break;
24283         /*
24284         * Break on the first set of enumerations. Any additional
24285         *  enumerations which might be existent on the ancestors
24286         *  of the current type are restricted by this set; thus
24287         *  *must* *not* be taken into account.
24288         */
24289         if (found)
24290             break;
24291         tmpType = tmpType->baseType;
24292     } while ((tmpType != NULL) &&
24293         (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24294     if (found && (ret == 0)) {
24295         ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
24296         if (fireErrors) {
24297             xmlSchemaFacetErr(actxt, ret, node,
24298                 value, 0, type, NULL, NULL, NULL, NULL);
24299         } else
24300             return (ret);
24301         if (error == 0)
24302             error = ret;
24303     }
24304 
24305     /*
24306     * Process patters. Pattern facets are ORed at type level
24307     * and ANDed if derived. Walk the base type axis.
24308     */
24309     tmpType = type;
24310     facet = NULL;
24311     do {
24312         found = 0;
24313         for (facetLink = tmpType->facetSet; facetLink != NULL;
24314             facetLink = facetLink->next) {
24315             if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
24316                 continue;
24317             found = 1;
24318             /*
24319             * NOTE that for patterns, @value needs to be the
24320             * normalized value.
24321             */
24322             ret = xmlRegexpExec(facetLink->facet->regexp, value);
24323             if (ret == 1)
24324                 break;
24325             else if (ret < 0) {
24326                 AERROR_INT("xmlSchemaValidateFacets",
24327                     "validating against a pattern facet");
24328                 return (-1);
24329             } else {
24330                 /*
24331                 * Save the last non-validating facet.
24332                 */
24333                 facet = facetLink->facet;
24334             }
24335         }
24336         if (found && (ret != 1)) {
24337             ret = XML_SCHEMAV_CVC_PATTERN_VALID;
24338             if (fireErrors) {
24339                 xmlSchemaFacetErr(actxt, ret, node,
24340                     value, 0, type, facet, NULL, NULL, NULL);
24341             } else
24342                 return (ret);
24343             if (error == 0)
24344                 error = ret;
24345             break;
24346         }
24347         tmpType = tmpType->baseType;
24348     } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24349 
24350     return (error);
24351 }
24352 
24353 static xmlChar *
xmlSchemaNormalizeValue(xmlSchemaTypePtr type,const xmlChar * value)24354 xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
24355 			const xmlChar *value)
24356 {
24357     switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
24358 	case XML_SCHEMA_WHITESPACE_COLLAPSE:
24359 	    return (xmlSchemaCollapseString(value));
24360 	case XML_SCHEMA_WHITESPACE_REPLACE:
24361 	    return (xmlSchemaWhiteSpaceReplace(value));
24362 	default:
24363 	    return (NULL);
24364     }
24365 }
24366 
24367 static int
xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,const xmlChar * value,xmlSchemaValPtr * val,int valNeeded)24368 xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
24369 		       const xmlChar *value,
24370 		       xmlSchemaValPtr *val,
24371 		       int valNeeded)
24372 {
24373     int ret;
24374     xmlChar *stripped;
24375     const xmlChar *nsName;
24376     xmlChar *local, *prefix = NULL;
24377 
24378     ret = xmlValidateQName(value, 1);
24379     if (ret != 0) {
24380 	if (ret == -1) {
24381 	    VERROR_INT("xmlSchemaValidateQName",
24382 		"calling xmlValidateQName()");
24383 	    return (-1);
24384 	}
24385 	return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
24386     }
24387     /*
24388     * NOTE: xmlSplitQName2 will always return a duplicated
24389     * strings.
24390     */
24391     /* TODO: Export and use xmlSchemaStrip instead */
24392     stripped = xmlSchemaCollapseString(value);
24393     local = xmlSplitQName2(stripped ? stripped : value, &prefix);
24394     xmlFree(stripped);
24395     if (local == NULL)
24396 	local = xmlStrdup(value);
24397     /*
24398     * OPTIMIZE TODO: Use flags for:
24399     *  - is there any namespace binding?
24400     *  - is there a default namespace?
24401     */
24402     nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24403 
24404     if (prefix != NULL) {
24405 	xmlFree(prefix);
24406 	/*
24407 	* A namespace must be found if the prefix is
24408 	* NOT NULL.
24409 	*/
24410 	if (nsName == NULL) {
24411 	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24412 	    xmlSchemaCustomErr(ACTXT_CAST vctxt, ret, NULL,
24413 		WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24414 		"The QName value '%s' has no "
24415 		"corresponding namespace declaration in "
24416 		"scope", value, NULL);
24417 	    if (local != NULL)
24418 		xmlFree(local);
24419 	    return (ret);
24420 	}
24421     }
24422     if (valNeeded && val) {
24423 	if (nsName != NULL)
24424 	    *val = xmlSchemaNewQNameValue(
24425 		BAD_CAST xmlStrdup(nsName), BAD_CAST local);
24426 	else
24427 	    *val = xmlSchemaNewQNameValue(NULL,
24428 		BAD_CAST local);
24429     } else
24430 	xmlFree(local);
24431     return (0);
24432 }
24433 
24434 /*
24435 * cvc-simple-type
24436 */
24437 static int
xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,xmlNodePtr node,xmlSchemaTypePtr type,const xmlChar * value,xmlSchemaValPtr * retVal,int fireErrors,int normalize,int isNormalized)24438 xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
24439 			     xmlNodePtr node,
24440 			     xmlSchemaTypePtr type,
24441 			     const xmlChar *value,
24442 			     xmlSchemaValPtr *retVal,
24443 			     int fireErrors,
24444 			     int normalize,
24445 			     int isNormalized)
24446 {
24447     int ret = 0, valNeeded = (retVal) ? 1 : 0;
24448     xmlSchemaValPtr val = NULL;
24449     /* xmlSchemaWhitespaceValueType ws; */
24450     xmlChar *normValue = NULL;
24451 
24452 #define NORMALIZE(atype) \
24453     if ((! isNormalized) && \
24454     (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
24455 	normValue = xmlSchemaNormalizeValue(atype, value); \
24456 	if (normValue != NULL) \
24457 	    value = normValue; \
24458 	isNormalized = 1; \
24459     }
24460 
24461     if ((retVal != NULL) && (*retVal != NULL)) {
24462 	xmlSchemaFreeValue(*retVal);
24463 	*retVal = NULL;
24464     }
24465     /*
24466     * 3.14.4 Simple Type Definition Validation Rules
24467     * Validation Rule: String Valid
24468     */
24469     /*
24470     * 1 It is schema-valid with respect to that definition as defined
24471     * by Datatype Valid in [XML Schemas: Datatypes].
24472     */
24473     /*
24474     * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
24475     * the empty set, as defined in Type Derivation OK (Simple) ($3.14.6), then
24476     * the string must be a `declared entity name`.
24477     */
24478     /*
24479     * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
24480     * given the empty set, as defined in Type Derivation OK (Simple) ($3.14.6),
24481     * then every whitespace-delimited substring of the string must be a `declared
24482     * entity name`.
24483     */
24484     /*
24485     * 2.3 otherwise no further condition applies.
24486     */
24487     if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
24488 	valNeeded = 1;
24489     if (value == NULL)
24490 	value = BAD_CAST "";
24491     if (WXS_IS_ANY_SIMPLE_TYPE(type) || WXS_IS_ATOMIC(type)) {
24492 	xmlSchemaTypePtr biType; /* The built-in type. */
24493 	/*
24494 	* SPEC (1.2.1) "if {variety} is `atomic` then the string must `match`
24495 	* a literal in the `lexical space` of {base type definition}"
24496 	*/
24497 	/*
24498 	* Whitespace-normalize.
24499 	*/
24500 	NORMALIZE(type);
24501 	if (type->type != XML_SCHEMA_TYPE_BASIC) {
24502 	    /*
24503 	    * Get the built-in type.
24504 	    */
24505 	    biType = type->baseType;
24506 	    while ((biType != NULL) &&
24507 		(biType->type != XML_SCHEMA_TYPE_BASIC))
24508 		biType = biType->baseType;
24509 
24510 	    if (biType == NULL) {
24511 		AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24512 		    "could not get the built-in type");
24513 		goto internal_error;
24514 	    }
24515 	} else
24516 	    biType = type;
24517 	/*
24518 	* NOTATIONs need to be processed here, since they need
24519 	* to lookup in the hashtable of NOTATION declarations of the schema.
24520 	*/
24521 	if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
24522 	    switch (biType->builtInType) {
24523 		case XML_SCHEMAS_NOTATION:
24524 		    ret = xmlSchemaValidateNotation(
24525 			(xmlSchemaValidCtxtPtr) actxt,
24526 			((xmlSchemaValidCtxtPtr) actxt)->schema,
24527 			NULL, value, &val, valNeeded);
24528 		    break;
24529 		case XML_SCHEMAS_QNAME:
24530 		    ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
24531 			value, &val, valNeeded);
24532 		    break;
24533 		default:
24534 		    /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24535 		    if (valNeeded)
24536 			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24537 			    value, &val, node);
24538 		    else
24539 			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24540 			    value, NULL, node);
24541 		    break;
24542 	    }
24543 	} else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
24544 	    switch (biType->builtInType) {
24545 		case XML_SCHEMAS_NOTATION:
24546 		    ret = xmlSchemaValidateNotation(NULL,
24547 			((xmlSchemaParserCtxtPtr) actxt)->schema, node,
24548 			value, &val, valNeeded);
24549 		    break;
24550 		default:
24551 		    /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24552 		    if (valNeeded)
24553 			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24554 			    value, &val, node);
24555 		    else
24556 			ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24557 			    value, NULL, node);
24558 		    break;
24559 	    }
24560 	} else {
24561 	    /*
24562 	    * Validation via a public API is not implemented yet.
24563 	    */
24564 	    goto internal_error;
24565 	}
24566 	if (ret != 0) {
24567 	    if (ret < 0) {
24568 		AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24569 		    "validating against a built-in type");
24570 		goto internal_error;
24571 	    }
24572 	    if (WXS_IS_LIST(type))
24573 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24574 	    else
24575 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24576 	}
24577 	if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24578 	    /*
24579 	    * Check facets.
24580 	    */
24581 	    ret = xmlSchemaValidateFacets(actxt, node, type,
24582 		(xmlSchemaValType) biType->builtInType, value, val,
24583 		0, fireErrors);
24584 	    if (ret != 0) {
24585 		if (ret < 0) {
24586 		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24587 			"validating facets of atomic simple type");
24588 		    goto internal_error;
24589 		}
24590 		if (WXS_IS_LIST(type))
24591 		    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24592 		else
24593 		    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24594 	    }
24595 	}
24596 	else if (fireErrors && (ret > 0))
24597 	    xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24598     } else if (WXS_IS_LIST(type)) {
24599 
24600 	xmlSchemaTypePtr itemType;
24601 	const xmlChar *cur, *end;
24602 	xmlChar *tmpValue = NULL;
24603 	unsigned long len = 0;
24604 	xmlSchemaValPtr prevVal = NULL, curVal = NULL;
24605 	/* 1.2.2 if {variety} is `list` then the string must be a sequence
24606 	* of white space separated tokens, each of which `match`es a literal
24607 	* in the `lexical space` of {item type definition}
24608 	*/
24609 	/*
24610 	* Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
24611 	* the list type has an enum or pattern facet.
24612 	*/
24613 	NORMALIZE(type);
24614 	/*
24615 	* VAL TODO: Optimize validation of empty values.
24616 	* VAL TODO: We do not have computed values for lists.
24617 	*/
24618 	itemType = WXS_LIST_ITEMTYPE(type);
24619 	cur = value;
24620 	do {
24621 	    while (IS_BLANK_CH(*cur))
24622 		cur++;
24623 	    end = cur;
24624 	    while ((*end != 0) && (!(IS_BLANK_CH(*end))))
24625 		end++;
24626 	    if (end == cur)
24627 		break;
24628 	    tmpValue = xmlStrndup(cur, end - cur);
24629 	    len++;
24630 
24631 	    if (valNeeded)
24632 		ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24633 		    tmpValue, &curVal, fireErrors, 0, 1);
24634 	    else
24635 		ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24636 		    tmpValue, NULL, fireErrors, 0, 1);
24637 	    FREE_AND_NULL(tmpValue);
24638 	    if (curVal != NULL) {
24639 		/*
24640 		* Add to list of computed values.
24641 		*/
24642 		if (val == NULL)
24643 		    val = curVal;
24644 		else
24645 		    xmlSchemaValueAppend(prevVal, curVal);
24646 		prevVal = curVal;
24647 		curVal = NULL;
24648 	    }
24649 	    if (ret != 0) {
24650 		if (ret < 0) {
24651 		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24652 			"validating an item of list simple type");
24653 		    goto internal_error;
24654 		}
24655 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24656 		break;
24657 	    }
24658 	    cur = end;
24659 	} while (*cur != 0);
24660 	FREE_AND_NULL(tmpValue);
24661 	if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24662 	    /*
24663 	    * Apply facets (pattern, enumeration).
24664 	    */
24665 	    ret = xmlSchemaValidateFacets(actxt, node, type,
24666 		XML_SCHEMAS_UNKNOWN, value, val,
24667 		len, fireErrors);
24668 	    if (ret != 0) {
24669 		if (ret < 0) {
24670 		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24671 			"validating facets of list simple type");
24672 		    goto internal_error;
24673 		}
24674 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24675 	    }
24676 	}
24677 	if (fireErrors && (ret > 0)) {
24678 	    /*
24679 	    * Report the normalized value.
24680 	    */
24681 	    normalize = 1;
24682 	    NORMALIZE(type);
24683 	    xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24684 	}
24685     } else if (WXS_IS_UNION(type)) {
24686 	xmlSchemaTypeLinkPtr memberLink;
24687 	/*
24688 	* TODO: For all datatypes `derived` by `union`  whiteSpace does
24689 	* not apply directly; however, the normalization behavior of `union`
24690 	* types is controlled by the value of whiteSpace on that one of the
24691 	* `memberTypes` against which the `union` is successfully validated.
24692 	*
24693 	* This means that the value is normalized by the first validating
24694 	* member type, then the facets of the union type are applied. This
24695 	* needs changing of the value!
24696 	*/
24697 
24698 	/*
24699 	* 1.2.3 if {variety} is `union` then the string must `match` a
24700 	* literal in the `lexical space` of at least one member of
24701 	* {member type definitions}
24702 	*/
24703 	memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
24704 	if (memberLink == NULL) {
24705 	    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24706 		"union simple type has no member types");
24707 	    goto internal_error;
24708 	}
24709 	/*
24710 	* Always normalize union type values, since we currently
24711 	* cannot store the whitespace information with the value
24712 	* itself; otherwise a later value-comparison would be
24713 	* not possible.
24714 	*/
24715 	while (memberLink != NULL) {
24716 	    if (valNeeded)
24717 		ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24718 		    memberLink->type, value, &val, 0, 1, 0);
24719 	    else
24720 		ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24721 		    memberLink->type, value, NULL, 0, 1, 0);
24722 	    if (ret <= 0)
24723 		break;
24724 	    memberLink = memberLink->next;
24725 	}
24726 	if (ret != 0) {
24727 	    if (ret < 0) {
24728 		AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24729 		    "validating members of union simple type");
24730 		goto internal_error;
24731 	    }
24732 	    ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24733 	}
24734 	/*
24735 	* Apply facets (pattern, enumeration).
24736 	*/
24737 	if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24738 	    /*
24739 	    * The normalization behavior of `union` types is controlled by
24740 	    * the value of whiteSpace on that one of the `memberTypes`
24741 	    * against which the `union` is successfully validated.
24742 	    */
24743 	    NORMALIZE(memberLink->type);
24744 	    ret = xmlSchemaValidateFacets(actxt, node, type,
24745 		XML_SCHEMAS_UNKNOWN, value, val,
24746 		0, fireErrors);
24747 	    if (ret != 0) {
24748 		if (ret < 0) {
24749 		    AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24750 			"validating facets of union simple type");
24751 		    goto internal_error;
24752 		}
24753 		ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24754 	    }
24755 	}
24756 	if (fireErrors && (ret > 0))
24757 	    xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24758     }
24759 
24760     if (normValue != NULL)
24761 	xmlFree(normValue);
24762     if (ret == 0) {
24763 	if (retVal != NULL)
24764 	    *retVal = val;
24765 	else if (val != NULL)
24766 	    xmlSchemaFreeValue(val);
24767     } else if (val != NULL)
24768 	xmlSchemaFreeValue(val);
24769     return (ret);
24770 internal_error:
24771     if (normValue != NULL)
24772 	xmlFree(normValue);
24773     if (val != NULL)
24774 	xmlSchemaFreeValue(val);
24775     return (-1);
24776 }
24777 
24778 static int
xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,const xmlChar * value,const xmlChar ** nsName,const xmlChar ** localName)24779 xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
24780 			   const xmlChar *value,
24781 			   const xmlChar **nsName,
24782 			   const xmlChar **localName)
24783 {
24784     int ret = 0;
24785 
24786     if ((nsName == NULL) || (localName == NULL))
24787 	return (-1);
24788     *nsName = NULL;
24789     *localName = NULL;
24790 
24791     ret = xmlValidateQName(value, 1);
24792     if (ret == -1)
24793 	return (-1);
24794     if (ret > 0) {
24795 	xmlSchemaSimpleTypeErr(ACTXT_CAST vctxt,
24796 	    XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24797 	    value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
24798 	return (1);
24799     }
24800     {
24801 	xmlChar *local = NULL;
24802 	xmlChar *prefix;
24803 
24804 	/*
24805 	* NOTE: xmlSplitQName2 will return a duplicated
24806 	* string.
24807 	*/
24808 	local = xmlSplitQName2(value, &prefix);
24809 	if (local == NULL)
24810 	    *localName = xmlDictLookup(vctxt->dict, value, -1);
24811 	else {
24812 	    *localName = xmlDictLookup(vctxt->dict, local, -1);
24813 	    xmlFree(local);
24814 	}
24815 
24816 	*nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24817 
24818 	if (prefix != NULL) {
24819 	    xmlFree(prefix);
24820 	    /*
24821 	    * A namespace must be found if the prefix is NOT NULL.
24822 	    */
24823 	    if (*nsName == NULL) {
24824 		xmlSchemaCustomErr(ACTXT_CAST vctxt,
24825 		    XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24826 		    WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24827 		    "The QName value '%s' has no "
24828 		    "corresponding namespace declaration in scope",
24829 		    value, NULL);
24830 		return (2);
24831 	    }
24832 	}
24833     }
24834     return (0);
24835 }
24836 
24837 static int
xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,xmlSchemaAttrInfoPtr iattr,xmlSchemaTypePtr * localType,xmlSchemaElementPtr elemDecl)24838 xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
24839 			xmlSchemaAttrInfoPtr iattr,
24840 			xmlSchemaTypePtr *localType,
24841 			xmlSchemaElementPtr elemDecl)
24842 {
24843     int ret = 0;
24844     /*
24845     * cvc-elt (3.3.4) : (4)
24846     * AND
24847     * Schema-Validity Assessment (Element) (cvc-assess-elt)
24848     *   (1.2.1.2.1) - (1.2.1.2.4)
24849     * Handle 'xsi:type'.
24850     */
24851     if (localType == NULL)
24852 	return (-1);
24853     *localType = NULL;
24854     if (iattr == NULL)
24855 	return (0);
24856     else {
24857 	const xmlChar *nsName = NULL, *local = NULL;
24858 	/*
24859 	* TODO: We should report a *warning* that the type was overridden
24860 	* by the instance.
24861 	*/
24862 	ACTIVATE_ATTRIBUTE(iattr);
24863 	/*
24864 	* (cvc-elt) (3.3.4) : (4.1)
24865 	* (cvc-assess-elt) (1.2.1.2.2)
24866 	*/
24867 	ret = xmlSchemaVExpandQName(vctxt, iattr->value,
24868 	    &nsName, &local);
24869 	if (ret != 0) {
24870 	    if (ret < 0) {
24871 		VERROR_INT("xmlSchemaValidateElementByDeclaration",
24872 		    "calling xmlSchemaQNameExpand() to validate the "
24873 		    "attribute 'xsi:type'");
24874 		goto internal_error;
24875 	    }
24876 	    goto exit;
24877 	}
24878 	/*
24879 	* (cvc-elt) (3.3.4) : (4.2)
24880 	* (cvc-assess-elt) (1.2.1.2.3)
24881 	*/
24882 	*localType = xmlSchemaGetType(vctxt->schema, local, nsName);
24883 	if (*localType == NULL) {
24884 	    xmlChar *str = NULL;
24885 
24886 	    xmlSchemaCustomErr(ACTXT_CAST vctxt,
24887 		XML_SCHEMAV_CVC_ELT_4_2, NULL,
24888 		WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24889 		"The QName value '%s' of the xsi:type attribute does not "
24890 		"resolve to a type definition",
24891 		xmlSchemaFormatQName(&str, nsName, local), NULL);
24892 	    FREE_AND_NULL(str);
24893 	    ret = vctxt->err;
24894 	    goto exit;
24895 	}
24896 	if (elemDecl != NULL) {
24897 	    int set = 0;
24898 
24899 	    /*
24900 	    * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
24901 	    * "The `local type definition` must be validly
24902 	    * derived from the {type definition} given the union of
24903 	    * the {disallowed substitutions} and the {type definition}'s
24904 	    * {prohibited substitutions}, as defined in
24905 	    * Type Derivation OK (Complex) ($3.4.6)
24906 	    * (if it is a complex type definition),
24907 	    * or given {disallowed substitutions} as defined in Type
24908 	    * Derivation OK (Simple) ($3.14.6) (if it is a simple type
24909 	    * definition)."
24910 	    *
24911 	    * {disallowed substitutions}: the "block" on the element decl.
24912 	    * {prohibited substitutions}: the "block" on the type def.
24913 	    */
24914 	    /*
24915 	    * OPTIMIZE TODO: We could map types already evaluated
24916 	    * to be validly derived from other types to avoid checking
24917 	    * this over and over for the same types.
24918 	    */
24919 	    if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
24920 		(elemDecl->subtypes->flags &
24921 		    XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
24922 		set |= SUBSET_EXTENSION;
24923 
24924 	    if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
24925 		(elemDecl->subtypes->flags &
24926 		    XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
24927 		set |= SUBSET_RESTRICTION;
24928 
24929 	    /*
24930 	    * REMOVED and CHANGED since this produced a parser context
24931 	    * which adds to the string dict of the schema. So this would
24932 	    * change the schema and we don't want this. We don't need
24933 	    * the parser context anymore.
24934 	    *
24935 	    * if ((vctxt->pctxt == NULL) &&
24936 	    *	(xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
24937 	    *	    return (-1);
24938 	    */
24939 
24940 	    if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST vctxt, *localType,
24941 		elemDecl->subtypes, set) != 0) {
24942 		xmlChar *str = NULL;
24943 
24944 		xmlSchemaCustomErr(ACTXT_CAST vctxt,
24945 		    XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
24946 		    "The type definition '%s', specified by xsi:type, is "
24947 		    "blocked or not validly derived from the type definition "
24948 		    "of the element declaration",
24949 		    xmlSchemaFormatQName(&str,
24950 			(*localType)->targetNamespace,
24951 			(*localType)->name),
24952 		    NULL);
24953 		FREE_AND_NULL(str);
24954 		ret = vctxt->err;
24955 		*localType = NULL;
24956 	    }
24957 	}
24958     }
24959 exit:
24960     ACTIVATE_ELEM;
24961     return (ret);
24962 internal_error:
24963     ACTIVATE_ELEM;
24964     return (-1);
24965 }
24966 
24967 static int
xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)24968 xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
24969 {
24970     xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
24971     xmlSchemaTypePtr actualType;
24972 
24973     /*
24974     * cvc-elt (3.3.4) : 1
24975     */
24976     if (elemDecl == NULL) {
24977 	VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
24978 	    "No matching declaration available");
24979         return (vctxt->err);
24980     }
24981     actualType = WXS_ELEM_TYPEDEF(elemDecl);
24982     /*
24983     * cvc-elt (3.3.4) : 2
24984     */
24985     if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
24986 	VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
24987 	    "The element declaration is abstract");
24988         return (vctxt->err);
24989     }
24990     if (actualType == NULL) {
24991 	VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
24992 	    "The type definition is absent");
24993 	return (XML_SCHEMAV_CVC_TYPE_1);
24994     }
24995     if (vctxt->nbAttrInfos != 0) {
24996 	int ret;
24997 	xmlSchemaAttrInfoPtr iattr;
24998 	/*
24999 	* cvc-elt (3.3.4) : 3
25000 	* Handle 'xsi:nil'.
25001 	*/
25002 	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25003 	    XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
25004 	if (iattr) {
25005 	    ACTIVATE_ATTRIBUTE(iattr);
25006 	    /*
25007 	    * Validate the value.
25008 	    */
25009 	    ret = xmlSchemaVCheckCVCSimpleType(
25010 		ACTXT_CAST vctxt, NULL,
25011 		xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
25012 		iattr->value, &(iattr->val), 1, 0, 0);
25013 	    ACTIVATE_ELEM;
25014 	    if (ret < 0) {
25015 		VERROR_INT("xmlSchemaValidateElemDecl",
25016 		    "calling xmlSchemaVCheckCVCSimpleType() to "
25017 		    "validate the attribute 'xsi:nil'");
25018 		return (-1);
25019 	    }
25020 	    if (ret == 0) {
25021 		if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
25022 		    /*
25023 		    * cvc-elt (3.3.4) : 3.1
25024 		    */
25025 		    VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
25026 			"The element is not 'nillable'");
25027 		    /* Does not return an error on purpose. */
25028 		} else {
25029 		    if (xmlSchemaValueGetAsBoolean(iattr->val)) {
25030 			/*
25031 			* cvc-elt (3.3.4) : 3.2.2
25032 			*/
25033 			if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
25034 			    (elemDecl->value != NULL)) {
25035 			    VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
25036 				"The element cannot be 'nilled' because "
25037 				"there is a fixed value constraint defined "
25038 				"for it");
25039 			     /* Does not return an error on purpose. */
25040 			} else
25041 			    vctxt->inode->flags |=
25042 				XML_SCHEMA_ELEM_INFO_NILLED;
25043 		    }
25044 		}
25045 	    }
25046 	}
25047 	/*
25048 	* cvc-elt (3.3.4) : 4
25049 	* Handle 'xsi:type'.
25050 	*/
25051 	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25052 	    XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25053 	if (iattr) {
25054 	    xmlSchemaTypePtr localType = NULL;
25055 
25056 	    ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
25057 		elemDecl);
25058 	    if (ret != 0) {
25059 		if (ret == -1) {
25060 		    VERROR_INT("xmlSchemaValidateElemDecl",
25061 			"calling xmlSchemaProcessXSIType() to "
25062 			"process the attribute 'xsi:type'");
25063 		    return (-1);
25064 		}
25065 		/* Does not return an error on purpose. */
25066 	    }
25067 	    if (localType != NULL) {
25068 		vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
25069 		actualType = localType;
25070 	    }
25071 	}
25072     }
25073     /*
25074     * IDC: Register identity-constraint XPath matchers.
25075     */
25076     if ((elemDecl->idcs != NULL) &&
25077 	(xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
25078 	    return (-1);
25079     /*
25080     * No actual type definition.
25081     */
25082     if (actualType == NULL) {
25083 	VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
25084 	    "The type definition is absent");
25085 	return (XML_SCHEMAV_CVC_TYPE_1);
25086     }
25087     /*
25088     * Remember the actual type definition.
25089     */
25090     vctxt->inode->typeDef = actualType;
25091 
25092     return (0);
25093 }
25094 
25095 static int
xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)25096 xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
25097 {
25098     xmlSchemaAttrInfoPtr iattr;
25099     int ret = 0, i;
25100 
25101     /*
25102     * SPEC cvc-type (3.1.1)
25103     * "The attributes of must be empty, excepting those whose namespace
25104     * name is identical to http://www.w3.org/2001/XMLSchema-instance and
25105     * whose local name is one of type, nil, schemaLocation or
25106     * noNamespaceSchemaLocation."
25107     */
25108     if (vctxt->nbAttrInfos == 0)
25109 	return (0);
25110     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25111 	iattr = vctxt->attrInfos[i];
25112 	if (! iattr->metaType) {
25113 	    ACTIVATE_ATTRIBUTE(iattr)
25114 	    xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25115 		XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
25116 	    ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
25117         }
25118     }
25119     ACTIVATE_ELEM
25120     return (ret);
25121 }
25122 
25123 /*
25124 * Cleanup currently used attribute infos.
25125 */
25126 static void
xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)25127 xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
25128 {
25129     int i;
25130     xmlSchemaAttrInfoPtr attr;
25131 
25132     if (vctxt->nbAttrInfos == 0)
25133 	return;
25134     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25135 	attr = vctxt->attrInfos[i];
25136 	if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
25137 	    if (attr->localName != NULL)
25138 		xmlFree((xmlChar *) attr->localName);
25139 	    if (attr->nsName != NULL)
25140 		xmlFree((xmlChar *) attr->nsName);
25141 	}
25142 	if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
25143 	    if (attr->value != NULL)
25144 		xmlFree((xmlChar *) attr->value);
25145 	}
25146 	if (attr->val != NULL) {
25147 	    xmlSchemaFreeValue(attr->val);
25148 	    attr->val = NULL;
25149 	}
25150 	memset(attr, 0, sizeof(xmlSchemaAttrInfo));
25151     }
25152     vctxt->nbAttrInfos = 0;
25153 }
25154 
25155 /*
25156 * 3.4.4 Complex Type Definition Validation Rules
25157 *   Element Locally Valid (Complex Type) (cvc-complex-type)
25158 * 3.2.4 Attribute Declaration Validation Rules
25159 *   Validation Rule: Attribute Locally Valid (cvc-attribute)
25160 *   Attribute Locally Valid (Use) (cvc-au)
25161 *
25162 * Only "assessed" attribute information items will be visible to
25163 * IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
25164 */
25165 static int
xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)25166 xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
25167 {
25168     xmlSchemaTypePtr type = vctxt->inode->typeDef;
25169     xmlSchemaItemListPtr attrUseList;
25170     xmlSchemaAttributeUsePtr attrUse = NULL;
25171     xmlSchemaAttributePtr attrDecl = NULL;
25172     xmlSchemaAttrInfoPtr iattr, tmpiattr;
25173     int i, j, found, nbAttrs, nbUses;
25174     int xpathRes = 0, res, wildIDs = 0, fixed;
25175     xmlNodePtr defAttrOwnerElem = NULL;
25176 
25177     /*
25178     * SPEC (cvc-attribute)
25179     * (1) "The declaration must not be `absent` (see Missing
25180     * Sub-components ($5.3) for how this can fail to be
25181     * the case)."
25182     * (2) "Its {type definition} must not be absent."
25183     *
25184     * NOTE (1) + (2): This is not handled here, since we currently do not
25185     * allow validation against schemas which have missing sub-components.
25186     *
25187     * SPEC (cvc-complex-type)
25188     * (3) "For each attribute information item in the element information
25189     * item's [attributes] excepting those whose [namespace name] is
25190     * identical to http://www.w3.org/2001/XMLSchema-instance and whose
25191     * [local name] is one of type, nil, schemaLocation or
25192     * noNamespaceSchemaLocation, the appropriate case among the following
25193     * must be true:
25194     *
25195     */
25196     attrUseList = (xmlSchemaItemListPtr) type->attrUses;
25197     /*
25198     * @nbAttrs is the number of attributes present in the instance.
25199     */
25200     nbAttrs = vctxt->nbAttrInfos;
25201     if (attrUseList != NULL)
25202 	nbUses = attrUseList->nbItems;
25203     else
25204 	nbUses = 0;
25205     for (i = 0; i < nbUses; i++) {
25206         found = 0;
25207 	attrUse = attrUseList->items[i];
25208 	attrDecl = WXS_ATTRUSE_DECL(attrUse);
25209         for (j = 0; j < nbAttrs; j++) {
25210 	    iattr = vctxt->attrInfos[j];
25211 	    /*
25212 	    * SPEC (cvc-complex-type) (3)
25213 	    * Skip meta attributes.
25214 	    */
25215 	    if (iattr->metaType)
25216 		continue;
25217 	    if (iattr->localName[0] != attrDecl->name[0])
25218 		continue;
25219 	    if (!xmlStrEqual(iattr->localName, attrDecl->name))
25220 		continue;
25221 	    if (!xmlStrEqual(iattr->nsName, attrDecl->targetNamespace))
25222 		continue;
25223 	    found = 1;
25224 	    /*
25225 	    * SPEC (cvc-complex-type)
25226 	    * (3.1) "If there is among the {attribute uses} an attribute
25227 	    * use with an {attribute declaration} whose {name} matches
25228 	    * the attribute information item's [local name] and whose
25229 	    * {target namespace} is identical to the attribute information
25230 	    * item's [namespace name] (where an `absent` {target namespace}
25231 	    * is taken to be identical to a [namespace name] with no value),
25232 	    * then the attribute information must be `valid` with respect
25233 	    * to that attribute use as per Attribute Locally Valid (Use)
25234 	    * ($3.5.4). In this case the {attribute declaration} of that
25235 	    * attribute use is the `context-determined declaration` for the
25236 	    * attribute information item with respect to Schema-Validity
25237 	    * Assessment (Attribute) ($3.2.4) and
25238 	    * Assessment Outcome (Attribute) ($3.2.5).
25239 	    */
25240 	    iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25241 	    iattr->use = attrUse;
25242 	    /*
25243 	    * Context-determined declaration.
25244 	    */
25245 	    iattr->decl = attrDecl;
25246 	    iattr->typeDef = attrDecl->subtypes;
25247 	    break;
25248 	}
25249 
25250 	if (found)
25251 	    continue;
25252 
25253 	if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
25254 	    /*
25255 	    * Handle non-existent, required attributes.
25256 	    *
25257 	    * SPEC (cvc-complex-type)
25258 	    * (4) "The {attribute declaration} of each attribute use in
25259 	    * the {attribute uses} whose {required} is true matches one
25260 	    * of the attribute information items in the element information
25261 	    * item's [attributes] as per clause 3.1 above."
25262 	    */
25263 	    tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25264 	    if (tmpiattr == NULL) {
25265 		VERROR_INT(
25266 		    "xmlSchemaVAttributesComplex",
25267 		    "calling xmlSchemaGetFreshAttrInfo()");
25268 		return (-1);
25269 	    }
25270 	    tmpiattr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
25271 	    tmpiattr->use = attrUse;
25272 	    tmpiattr->decl = attrDecl;
25273 	} else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
25274 	    ((attrUse->defValue != NULL) ||
25275 	     (attrDecl->defValue != NULL))) {
25276 	    /*
25277 	    * Handle non-existent, optional, default/fixed attributes.
25278 	    */
25279 	    tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25280 	    if (tmpiattr == NULL) {
25281 		VERROR_INT(
25282 		    "xmlSchemaVAttributesComplex",
25283 		    "calling xmlSchemaGetFreshAttrInfo()");
25284 		return (-1);
25285 	    }
25286 	    tmpiattr->state = XML_SCHEMAS_ATTR_DEFAULT;
25287 	    tmpiattr->use = attrUse;
25288 	    tmpiattr->decl = attrDecl;
25289 	    tmpiattr->typeDef = attrDecl->subtypes;
25290 	    tmpiattr->localName = attrDecl->name;
25291 	    tmpiattr->nsName = attrDecl->targetNamespace;
25292 	}
25293     }
25294 
25295     if (vctxt->nbAttrInfos == 0)
25296 	return (0);
25297     /*
25298     * Validate against the wildcard.
25299     */
25300     if (type->attributeWildcard != NULL) {
25301 	/*
25302 	* SPEC (cvc-complex-type)
25303 	* (3.2.1) "There must be an {attribute wildcard}."
25304 	*/
25305 	for (i = 0; i < nbAttrs; i++) {
25306 	    iattr = vctxt->attrInfos[i];
25307 	    /*
25308 	    * SPEC (cvc-complex-type) (3)
25309 	    * Skip meta attributes.
25310 	    */
25311 	    if (iattr->state != XML_SCHEMAS_ATTR_UNKNOWN)
25312 		continue;
25313 	    /*
25314 	    * SPEC (cvc-complex-type)
25315 	    * (3.2.2) "The attribute information item must be `valid` with
25316 	    * respect to it as defined in Item Valid (Wildcard) ($3.10.4)."
25317 	    *
25318 	    * SPEC Item Valid (Wildcard) (cvc-wildcard)
25319 	    * "... its [namespace name] must be `valid` with respect to
25320 	    * the wildcard constraint, as defined in Wildcard allows
25321 	    * Namespace Name ($3.10.4)."
25322 	    */
25323 	    if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
25324 		    iattr->nsName) == 0) {
25325 		/*
25326 		* Handle processContents.
25327 		*
25328 		* SPEC (cvc-wildcard):
25329 		* processContents | context-determined declaration:
25330 		* "strict"          "mustFind"
25331 		* "lax"             "none"
25332 		* "skip"            "skip"
25333 		*/
25334 		if (type->attributeWildcard->processContents ==
25335 		    XML_SCHEMAS_ANY_SKIP) {
25336 		     /*
25337 		    * context-determined declaration = "skip"
25338 		    *
25339 		    * SPEC PSVI Assessment Outcome (Attribute)
25340 		    * [validity] = "notKnown"
25341 		    * [validation attempted] = "none"
25342 		    */
25343 		    iattr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
25344 		    continue;
25345 		}
25346 		/*
25347 		* Find an attribute declaration.
25348 		*/
25349 		iattr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
25350 		    iattr->localName, iattr->nsName);
25351 		if (iattr->decl != NULL) {
25352 		    iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25353 		    /*
25354 		    * SPEC (cvc-complex-type)
25355 		    * (5) "Let [Definition:]  the wild IDs be the set of
25356 		    * all attribute information item to which clause 3.2
25357 		    * applied and whose `validation` resulted in a
25358 		    * `context-determined declaration` of mustFind or no
25359 		    * `context-determined declaration` at all, and whose
25360 		    * [local name] and [namespace name] resolve (as
25361 		    * defined by QName resolution (Instance) ($3.15.4)) to
25362 		    * an attribute declaration whose {type definition} is
25363 		    * or is derived from ID. Then all of the following
25364 		    * must be true:"
25365 		    */
25366 		    iattr->typeDef = WXS_ATTR_TYPEDEF(iattr->decl);
25367 		    if (xmlSchemaIsDerivedFromBuiltInType(
25368 			iattr->typeDef, XML_SCHEMAS_ID)) {
25369 			/*
25370 			* SPEC (5.1) "There must be no more than one
25371 			* item in `wild IDs`."
25372 			*/
25373 			if (wildIDs != 0) {
25374 			    /* VAL TODO */
25375 			    iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
25376 			    continue;
25377 			}
25378 			wildIDs++;
25379 			/*
25380 			* SPEC (cvc-complex-type)
25381 			* (5.2) "If `wild IDs` is non-empty, there must not
25382 			* be any attribute uses among the {attribute uses}
25383 			* whose {attribute declaration}'s {type definition}
25384 			* is or is derived from ID."
25385 			*/
25386                         if (attrUseList != NULL) {
25387                             for (j = 0; j < attrUseList->nbItems; j++) {
25388                                 if (xmlSchemaIsDerivedFromBuiltInType(
25389                                     WXS_ATTRUSE_TYPEDEF(attrUseList->items[j]),
25390                                     XML_SCHEMAS_ID)) {
25391                                     /* URGENT VAL TODO: implement */
25392                             iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
25393                                     break;
25394                                 }
25395                             }
25396                         }
25397 		    }
25398 		} else if (type->attributeWildcard->processContents ==
25399 		    XML_SCHEMAS_ANY_LAX) {
25400 		    iattr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
25401 		    /*
25402 		    * SPEC PSVI Assessment Outcome (Attribute)
25403 		    * [validity] = "notKnown"
25404 		    * [validation attempted] = "none"
25405 		    */
25406 		} else {
25407 		    iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
25408 		}
25409 	    }
25410 	}
25411     }
25412 
25413     if (vctxt->nbAttrInfos == 0)
25414 	return (0);
25415 
25416     /*
25417     * Get the owner element; needed for creation of default attributes.
25418     * This fixes bug #341337, reported by David Grohmann.
25419     */
25420     if (vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
25421 	xmlSchemaNodeInfoPtr ielem = vctxt->elemInfos[vctxt->depth];
25422 	if (ielem && ielem->node && ielem->node->doc)
25423 	    defAttrOwnerElem = ielem->node;
25424     }
25425     /*
25426     * Validate values, create default attributes, evaluate IDCs.
25427     */
25428     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25429 	iattr = vctxt->attrInfos[i];
25430 	/*
25431 	* VAL TODO: Note that we won't try to resolve IDCs to
25432 	* "lax" and "skip" validated attributes. Check what to
25433 	* do in this case.
25434 	*/
25435 	if ((iattr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
25436 	    (iattr->state != XML_SCHEMAS_ATTR_DEFAULT))
25437 	    continue;
25438 	/*
25439 	* VAL TODO: What to do if the type definition is missing?
25440 	*/
25441 	if (iattr->typeDef == NULL) {
25442 	    iattr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
25443 	    continue;
25444 	}
25445 
25446 	ACTIVATE_ATTRIBUTE(iattr);
25447 	fixed = 0;
25448 	xpathRes = 0;
25449 
25450 	if (vctxt->xpathStates != NULL) {
25451 	    /*
25452 	    * Evaluate IDCs.
25453 	    */
25454 	    xpathRes = xmlSchemaXPathEvaluate(vctxt,
25455 		XML_ATTRIBUTE_NODE);
25456 	    if (xpathRes == -1) {
25457 		VERROR_INT("xmlSchemaVAttributesComplex",
25458 		    "calling xmlSchemaXPathEvaluate()");
25459 		goto internal_error;
25460 	    }
25461 	}
25462 
25463 	if (iattr->state == XML_SCHEMAS_ATTR_DEFAULT) {
25464 	    /*
25465 	    * Default/fixed attributes.
25466 	    * We need the value only if we need to resolve IDCs or
25467 	    * will create default attributes.
25468 	    */
25469 	    if ((xpathRes) || (defAttrOwnerElem)) {
25470 		if (iattr->use->defValue != NULL) {
25471 		    iattr->value = (xmlChar *) iattr->use->defValue;
25472 		    iattr->val = iattr->use->defVal;
25473 		} else {
25474 		    iattr->value = (xmlChar *) iattr->decl->defValue;
25475 		    iattr->val = iattr->decl->defVal;
25476 		}
25477 		/*
25478 		* IDCs will consume the precomputed default value,
25479 		* so we need to clone it.
25480 		*/
25481 		if (iattr->val == NULL) {
25482 		    VERROR_INT("xmlSchemaVAttributesComplex",
25483 			"default/fixed value on an attribute use was "
25484 			"not precomputed");
25485 		    goto internal_error;
25486 		}
25487 		iattr->val = xmlSchemaCopyValue(iattr->val);
25488 		if (iattr->val == NULL) {
25489 		    VERROR_INT("xmlSchemaVAttributesComplex",
25490 			"calling xmlSchemaCopyValue()");
25491 		    goto internal_error;
25492 		}
25493 	    }
25494 	    /*
25495 	    * PSVI: Add the default attribute to the current element.
25496 	    * VAL TODO: Should we use the *normalized* value? This currently
25497 	    *   uses the *initial* value.
25498 	    */
25499 
25500 	    if (defAttrOwnerElem) {
25501 		xmlChar *normValue;
25502 		const xmlChar *value;
25503 
25504 		value = iattr->value;
25505 		/*
25506 		* Normalize the value.
25507 		*/
25508 		normValue = xmlSchemaNormalizeValue(iattr->typeDef,
25509 		    iattr->value);
25510 		if (normValue != NULL)
25511 		    value = BAD_CAST normValue;
25512 
25513 		if (iattr->nsName == NULL) {
25514 		    if (xmlNewProp(defAttrOwnerElem,
25515 			iattr->localName, value) == NULL) {
25516 			VERROR_INT("xmlSchemaVAttributesComplex",
25517 			    "calling xmlNewProp()");
25518 			if (normValue != NULL)
25519 			    xmlFree(normValue);
25520 			goto internal_error;
25521 		    }
25522 		} else {
25523 		    xmlNsPtr ns;
25524 
25525 		    ns = xmlSearchNsByHref(defAttrOwnerElem->doc,
25526 			defAttrOwnerElem, iattr->nsName);
25527 		    if (ns == NULL) {
25528 			xmlChar prefix[13];
25529 			int counter = 0;
25530 
25531 			/*
25532 			* Create a namespace declaration on the validation
25533 			* root node if no namespace declaration is in scope.
25534 			*/
25535 			do {
25536 			    snprintf((char *) prefix, 13, "p%d", counter++);
25537 			    ns = xmlSearchNs(defAttrOwnerElem->doc,
25538 				defAttrOwnerElem, BAD_CAST prefix);
25539 			    if (counter > 1000) {
25540 				VERROR_INT(
25541 				    "xmlSchemaVAttributesComplex",
25542 				    "could not compute a ns prefix for a "
25543 				    "default/fixed attribute");
25544 				if (normValue != NULL)
25545 				    xmlFree(normValue);
25546 				goto internal_error;
25547 			    }
25548 			} while (ns != NULL);
25549 			ns = xmlNewNs(vctxt->validationRoot,
25550 			    iattr->nsName, BAD_CAST prefix);
25551 		    }
25552 		    /*
25553 		    * TODO:
25554 		    * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0406.html
25555 		    * If we have QNames: do we need to ensure there's a
25556 		    * prefix defined for the QName?
25557 		    */
25558 		    xmlNewNsProp(defAttrOwnerElem, ns, iattr->localName, value);
25559 		}
25560 		if (normValue != NULL)
25561 		    xmlFree(normValue);
25562 	    }
25563 	    /*
25564 	    * Go directly to IDC evaluation.
25565 	    */
25566 	    goto eval_idcs;
25567 	}
25568 	/*
25569 	* Validate the value.
25570 	*/
25571 	if (vctxt->value != NULL) {
25572 	    /*
25573 	    * Free last computed value; just for safety reasons.
25574 	    */
25575 	    xmlSchemaFreeValue(vctxt->value);
25576 	    vctxt->value = NULL;
25577 	}
25578 	/*
25579 	* Note that the attribute *use* can be unavailable, if
25580 	* the attribute was a wild attribute.
25581 	*/
25582 	if ((iattr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
25583 	    ((iattr->use != NULL) &&
25584 	     (iattr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
25585 	    fixed = 1;
25586 	else
25587 	    fixed = 0;
25588 	/*
25589 	* SPEC (cvc-attribute)
25590 	* (3) "The item's `normalized value` must be locally `valid`
25591 	* with respect to that {type definition} as per
25592 	* String Valid ($3.14.4)."
25593 	*
25594 	* VAL TODO: Do we already have the
25595 	* "normalized attribute value" here?
25596 	*/
25597 	if (xpathRes || fixed) {
25598 	    iattr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
25599 	    /*
25600 	    * Request a computed value.
25601 	    */
25602 	    res = xmlSchemaVCheckCVCSimpleType(
25603 		ACTXT_CAST vctxt,
25604 		iattr->node, iattr->typeDef, iattr->value, &(iattr->val),
25605 		1, 1, 0);
25606 	} else {
25607 	    res = xmlSchemaVCheckCVCSimpleType(
25608 		ACTXT_CAST vctxt,
25609 		iattr->node, iattr->typeDef, iattr->value, NULL,
25610 		1, 0, 0);
25611 	}
25612 
25613 	if (res != 0) {
25614 	    if (res == -1) {
25615 		VERROR_INT("xmlSchemaVAttributesComplex",
25616 		    "calling xmlSchemaStreamValidateSimpleTypeValue()");
25617 		goto internal_error;
25618 	    }
25619 	    iattr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
25620 	    /*
25621 	    * SPEC PSVI Assessment Outcome (Attribute)
25622 	    * [validity] = "invalid"
25623 	    */
25624 	    goto eval_idcs;
25625 	}
25626 
25627 	if (fixed) {
25628 	    /*
25629 	    * SPEC Attribute Locally Valid (Use) (cvc-au)
25630 	    * "For an attribute information item to be `valid`
25631 	    * with respect to an attribute use its *normalized*
25632 	    * value must match the *canonical* lexical
25633 	    * representation of the attribute use's {value
25634 	    * constraint}value, if it is present and fixed."
25635 	    *
25636 	    * VAL TODO: The requirement for the *canonical* value
25637 	    * will be removed in XML Schema 1.1.
25638 	    */
25639 	    /*
25640 	    * SPEC Attribute Locally Valid (cvc-attribute)
25641 	    * (4) "The item's *actual* value must match the *value* of
25642 	    * the {value constraint}, if it is present and fixed."
25643 	    */
25644 	    if (iattr->val == NULL) {
25645 		/* VAL TODO: A value was not precomputed. */
25646 		goto eval_idcs;
25647 	    }
25648 	    if ((iattr->use != NULL) &&
25649 		(iattr->use->defValue != NULL)) {
25650 		if (iattr->use->defVal == NULL) {
25651 		    /* VAL TODO: A default value was not precomputed. */
25652 		    goto eval_idcs;
25653 		}
25654 		iattr->vcValue = iattr->use->defValue;
25655 		/*
25656 		if (xmlSchemaCompareValuesWhtsp(attr->val,
25657 		    (xmlSchemaWhitespaceValueType) ws,
25658 		    attr->use->defVal,
25659 		    (xmlSchemaWhitespaceValueType) ws) != 0) {
25660 		*/
25661 		if (! xmlSchemaAreValuesEqual(iattr->val, iattr->use->defVal))
25662 		    iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25663 	    } else {
25664 		if (iattr->decl->defVal == NULL) {
25665 		    /* VAL TODO: A default value was not precomputed. */
25666 		    goto eval_idcs;
25667 		}
25668 		iattr->vcValue = iattr->decl->defValue;
25669 		/*
25670 		if (xmlSchemaCompareValuesWhtsp(attr->val,
25671 		    (xmlSchemaWhitespaceValueType) ws,
25672 		    attrDecl->defVal,
25673 		    (xmlSchemaWhitespaceValueType) ws) != 0) {
25674 		*/
25675 		if (! xmlSchemaAreValuesEqual(iattr->val, iattr->decl->defVal))
25676 		    iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25677 	    }
25678 	    /*
25679 	    * [validity] = "valid"
25680 	    */
25681 	}
25682 eval_idcs:
25683 	/*
25684 	* Evaluate IDCs.
25685 	*/
25686 	if (xpathRes) {
25687 	    if (xmlSchemaXPathProcessHistory(vctxt,
25688 		vctxt->depth +1) == -1) {
25689 		VERROR_INT("xmlSchemaVAttributesComplex",
25690 		    "calling xmlSchemaXPathEvaluate()");
25691 		goto internal_error;
25692 	    }
25693 	} else if (vctxt->xpathStates != NULL)
25694 	    xmlSchemaXPathPop(vctxt);
25695     }
25696 
25697     /*
25698     * Report errors.
25699     */
25700     for (i = 0; i < vctxt->nbAttrInfos; i++) {
25701 	iattr = vctxt->attrInfos[i];
25702 	if ((iattr->state == XML_SCHEMAS_ATTR_META) ||
25703 	    (iattr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
25704 	    (iattr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
25705 	    (iattr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
25706 	    continue;
25707 	ACTIVATE_ATTRIBUTE(iattr);
25708 	switch (iattr->state) {
25709 	    case XML_SCHEMAS_ATTR_ERR_MISSING: {
25710 		    xmlChar *str = NULL;
25711 		    ACTIVATE_ELEM;
25712 		    xmlSchemaCustomErr(ACTXT_CAST vctxt,
25713 			XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
25714 			"The attribute '%s' is required but missing",
25715 			xmlSchemaFormatQName(&str,
25716 			    iattr->decl->targetNamespace,
25717 			    iattr->decl->name),
25718 			NULL);
25719 		    FREE_AND_NULL(str)
25720 		    break;
25721 		}
25722 	    case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
25723 		VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
25724 		    "The type definition is absent");
25725 		break;
25726 	    case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
25727 		xmlSchemaCustomErr(ACTXT_CAST vctxt,
25728 		    XML_SCHEMAV_CVC_AU, NULL, NULL,
25729 		    "The value '%s' does not match the fixed "
25730 		    "value constraint '%s'",
25731 		    iattr->value, iattr->vcValue);
25732 		break;
25733 	    case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
25734 		VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
25735 		    "No matching global attribute declaration available, but "
25736 		    "demanded by the strict wildcard");
25737 		break;
25738 	    case XML_SCHEMAS_ATTR_UNKNOWN:
25739 		if (iattr->metaType)
25740 		    break;
25741 		/*
25742 		* MAYBE VAL TODO: One might report different error messages
25743 		* for the following errors.
25744 		*/
25745 		if (type->attributeWildcard == NULL) {
25746 		    xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25747 			XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, iattr, NULL);
25748 		} else {
25749 		    xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25750 			XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, iattr, NULL);
25751 		}
25752 		break;
25753 	    default:
25754 		break;
25755 	}
25756     }
25757 
25758     ACTIVATE_ELEM;
25759     return (0);
25760 internal_error:
25761     ACTIVATE_ELEM;
25762     return (-1);
25763 }
25764 
25765 static int
xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,int * skip)25766 xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
25767 			      int *skip)
25768 {
25769     xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
25770     /*
25771     * The namespace of the element was already identified to be
25772     * matching the wildcard.
25773     */
25774     if ((skip == NULL) || (wild == NULL) ||
25775 	(wild->type != XML_SCHEMA_TYPE_ANY)) {
25776 	VERROR_INT("xmlSchemaValidateElemWildcard",
25777 	    "bad arguments");
25778 	return (-1);
25779     }
25780     *skip = 0;
25781     if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
25782 	/*
25783 	* URGENT VAL TODO: Either we need to position the stream to the
25784 	* next sibling, or walk the whole subtree.
25785 	*/
25786 	*skip = 1;
25787 	return (0);
25788     }
25789     {
25790 	xmlSchemaElementPtr decl = NULL;
25791 
25792 	decl = xmlSchemaGetElem(vctxt->schema,
25793 	    vctxt->inode->localName, vctxt->inode->nsName);
25794 	if (decl != NULL) {
25795 	    vctxt->inode->decl = decl;
25796 	    return (0);
25797 	}
25798     }
25799     if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
25800 	/* VAL TODO: Change to proper error code. */
25801 	VERROR(XML_SCHEMAV_CVC_ELT_1, NULL, /* WXS_BASIC_CAST wild */
25802 	    "No matching global element declaration available, but "
25803 	    "demanded by the strict wildcard");
25804 	return (vctxt->err);
25805     }
25806     if (vctxt->nbAttrInfos != 0) {
25807 	xmlSchemaAttrInfoPtr iattr;
25808 	/*
25809 	* SPEC Validation Rule: Schema-Validity Assessment (Element)
25810 	* (1.2.1.2.1) - (1.2.1.2.3 )
25811 	*
25812 	* Use the xsi:type attribute for the type definition.
25813 	*/
25814 	iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25815 	    XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25816 	if (iattr != NULL) {
25817 	    if (xmlSchemaProcessXSIType(vctxt, iattr,
25818 		&(vctxt->inode->typeDef), NULL) == -1) {
25819 		VERROR_INT("xmlSchemaValidateElemWildcard",
25820 		    "calling xmlSchemaProcessXSIType() to "
25821 		    "process the attribute 'xsi:nil'");
25822 		return (-1);
25823 	    }
25824 	    /*
25825 	    * Don't return an error on purpose.
25826 	    */
25827 	    return (0);
25828 	}
25829     }
25830     /*
25831     * SPEC Validation Rule: Schema-Validity Assessment (Element)
25832     *
25833     * Fallback to "anyType".
25834     */
25835     vctxt->inode->typeDef =
25836 	xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
25837     return (0);
25838 }
25839 
25840 /*
25841 * xmlSchemaCheckCOSValidDefault:
25842 *
25843 * This will be called if: not nilled, no content and a default/fixed
25844 * value is provided.
25845 */
25846 
25847 static int
xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,const xmlChar * value,xmlSchemaValPtr * val)25848 xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
25849 			      const xmlChar *value,
25850 			      xmlSchemaValPtr *val)
25851 {
25852     int ret = 0;
25853     xmlSchemaNodeInfoPtr inode = vctxt->inode;
25854 
25855     /*
25856     * cos-valid-default:
25857     * Schema Component Constraint: Element Default Valid (Immediate)
25858     * For a string to be a valid default with respect to a type
25859     * definition the appropriate case among the following must be true:
25860     */
25861     if WXS_IS_COMPLEX(inode->typeDef) {
25862 	/*
25863 	* Complex type.
25864 	*
25865 	* SPEC (2.1) "its {content type} must be a simple type definition
25866 	* or mixed."
25867 	* SPEC (2.2.2) "If the {content type} is mixed, then the {content
25868 	* type}'s particle must be `emptiable` as defined by
25869 	* Particle Emptiable ($3.9.6)."
25870 	*/
25871 	if ((! WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) &&
25872 	    ((! WXS_HAS_MIXED_CONTENT(inode->typeDef)) ||
25873 	     (! WXS_EMPTIABLE(inode->typeDef)))) {
25874 	    ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
25875 	    /* NOTE that this covers (2.2.2) as well. */
25876 	    VERROR(ret, NULL,
25877 		"For a string to be a valid default, the type definition "
25878 		"must be a simple type or a complex type with simple content "
25879 		"or mixed content and a particle emptiable");
25880 	    return(ret);
25881 	}
25882     }
25883     /*
25884     * 1 If the type definition is a simple type definition, then the string
25885     * must be `valid` with respect to that definition as defined by String
25886     * Valid ($3.14.4).
25887     *
25888     * AND
25889     *
25890     * 2.2.1 If the {content type} is a simple type definition, then the
25891     * string must be `valid` with respect to that simple type definition
25892     * as defined by String Valid ($3.14.4).
25893     */
25894     if (WXS_IS_SIMPLE(inode->typeDef)) {
25895 
25896 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
25897 	    NULL, inode->typeDef, value, val, 1, 1, 0);
25898 
25899     } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
25900 
25901 	ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
25902 	    NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
25903     }
25904     if (ret < 0) {
25905 	VERROR_INT("xmlSchemaCheckCOSValidDefault",
25906 	    "calling xmlSchemaVCheckCVCSimpleType()");
25907     }
25908     return (ret);
25909 }
25910 
25911 static void
xmlSchemaVContentModelCallback(xmlRegExecCtxtPtr exec ATTRIBUTE_UNUSED,const xmlChar * name ATTRIBUTE_UNUSED,void * transdata,void * inputdata)25912 xmlSchemaVContentModelCallback(xmlRegExecCtxtPtr exec ATTRIBUTE_UNUSED,
25913 			       const xmlChar * name ATTRIBUTE_UNUSED,
25914 			       void *transdata, void *inputdata)
25915 {
25916     xmlSchemaElementPtr item = (xmlSchemaElementPtr) transdata;
25917     xmlSchemaNodeInfoPtr inode = (xmlSchemaNodeInfoPtr) inputdata;
25918     inode->decl = item;
25919 }
25920 
25921 static int
xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)25922 xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
25923 {
25924     vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
25925     if (vctxt->inode == NULL) {
25926 	VERROR_INT("xmlSchemaValidatorPushElem",
25927 	    "calling xmlSchemaGetFreshElemInfo()");
25928 	return (-1);
25929     }
25930     vctxt->nbAttrInfos = 0;
25931     return (0);
25932 }
25933 
25934 static int
xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,xmlSchemaNodeInfoPtr inode,xmlSchemaTypePtr type,const xmlChar * value)25935 xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
25936 			     xmlSchemaNodeInfoPtr inode,
25937 			     xmlSchemaTypePtr type,
25938 			     const xmlChar *value)
25939 {
25940     if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
25941 	return (xmlSchemaVCheckCVCSimpleType(
25942 	    ACTXT_CAST vctxt, NULL,
25943 	    type, value, &(inode->val), 1, 1, 0));
25944     else
25945 	return (xmlSchemaVCheckCVCSimpleType(
25946 	    ACTXT_CAST vctxt, NULL,
25947 	    type, value, NULL, 1, 0, 0));
25948 }
25949 
25950 
25951 
25952 /*
25953 * Process END of element.
25954 */
25955 static int
xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)25956 xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
25957 {
25958     int ret = 0;
25959     xmlSchemaNodeInfoPtr inode = vctxt->inode;
25960 
25961     if (vctxt->nbAttrInfos != 0)
25962 	xmlSchemaClearAttrInfos(vctxt);
25963     if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
25964 	/*
25965 	* This element was not expected;
25966 	* we will not validate child elements of broken parents.
25967 	* Skip validation of all content of the parent.
25968 	*/
25969 	vctxt->skipDepth = vctxt->depth -1;
25970 	goto end_elem;
25971     }
25972     if ((inode->typeDef == NULL) ||
25973 	(inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
25974 	/*
25975 	* 1. the type definition might be missing if the element was
25976 	*    error prone
25977 	* 2. it might be abstract.
25978 	*/
25979 	goto end_elem;
25980     }
25981     /*
25982     * Check the content model.
25983     */
25984     if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
25985 	(inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
25986 
25987 	/*
25988 	* Workaround for "anyType".
25989 	*/
25990 	if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
25991 	    goto character_content;
25992 
25993 	if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
25994 	    xmlChar *values[10];
25995 	    int terminal, nbval = 10, nbneg;
25996 
25997 	    if (inode->regexCtxt == NULL) {
25998 		/*
25999 		* Create the regex context.
26000 		*/
26001 		inode->regexCtxt =
26002 		    xmlRegNewExecCtxt(inode->typeDef->contModel,
26003 		    xmlSchemaVContentModelCallback, vctxt);
26004 		if (inode->regexCtxt == NULL) {
26005 		    VERROR_INT("xmlSchemaValidatorPopElem",
26006 			"failed to create a regex context");
26007 		    goto internal_error;
26008 		}
26009 	    }
26010 
26011 	    /*
26012 	     * Do not check further content if the node has been nilled
26013 	     */
26014 	    if (INODE_NILLED(inode)) {
26015 		ret = 0;
26016                 goto skip_nilled;
26017 	    }
26018 
26019 	    /*
26020 	    * Get hold of the still expected content, since a further
26021 	    * call to xmlRegExecPushString() will lose this information.
26022 	    */
26023 	    xmlRegExecNextValues(inode->regexCtxt,
26024 		&nbval, &nbneg, &values[0], &terminal);
26025 	    ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
26026 	    if ((ret<0) || ((ret==0) && (!INODE_NILLED(inode)))) {
26027 		/*
26028 		* Still missing something.
26029 		*/
26030 		ret = 1;
26031 		inode->flags |=
26032 		    XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26033 		xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26034 		    XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
26035 		    "Missing child element(s)",
26036 		    nbval, nbneg, values);
26037 	    } else {
26038 		/*
26039 		* Content model is satisfied.
26040 		*/
26041 		ret = 0;
26042 	    }
26043 
26044 	}
26045     }
26046 
26047 skip_nilled:
26048 
26049     if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
26050 	goto end_elem;
26051 
26052 character_content:
26053 
26054     if (vctxt->value != NULL) {
26055 	xmlSchemaFreeValue(vctxt->value);
26056 	vctxt->value = NULL;
26057     }
26058     /*
26059     * Check character content.
26060     */
26061     if (inode->decl == NULL) {
26062 	/*
26063 	* Speedup if no declaration exists.
26064 	*/
26065 	if (WXS_IS_SIMPLE(inode->typeDef)) {
26066 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26067 		inode, inode->typeDef, inode->value);
26068 	} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26069 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26070 		inode, inode->typeDef->contentTypeDef,
26071 		inode->value);
26072 	}
26073 	if (ret < 0) {
26074 	    VERROR_INT("xmlSchemaValidatorPopElem",
26075 		"calling xmlSchemaVCheckCVCSimpleType()");
26076 	    goto internal_error;
26077 	}
26078 	goto end_elem;
26079     }
26080     /*
26081     * cvc-elt (3.3.4) : 5
26082     * The appropriate case among the following must be true:
26083     */
26084     /*
26085     * cvc-elt (3.3.4) : 5.1
26086     * If the declaration has a {value constraint},
26087     * the item has neither element nor character [children] and
26088     * clause 3.2 has not applied, then all of the following must be true:
26089     */
26090     if ((inode->decl->value != NULL) &&
26091 	(inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
26092 	(! INODE_NILLED(inode))) {
26093 	/*
26094 	* cvc-elt (3.3.4) : 5.1.1
26095 	* If the `actual type definition` is a `local type definition`
26096 	* then the canonical lexical representation of the {value constraint}
26097 	* value must be a valid default for the `actual type definition` as
26098 	* defined in Element Default Valid (Immediate) ($3.3.6).
26099 	*/
26100 	/*
26101 	* NOTE: 'local' above means types acquired by xsi:type.
26102 	* NOTE: Although the *canonical* value is stated, it is not
26103 	* relevant if canonical or not. Additionally XML Schema 1.1
26104 	* will removed this requirement as well.
26105 	*/
26106 	if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
26107 
26108 	    ret = xmlSchemaCheckCOSValidDefault(vctxt,
26109 		inode->decl->value, &(inode->val));
26110 	    if (ret != 0) {
26111 		if (ret < 0) {
26112 		    VERROR_INT("xmlSchemaValidatorPopElem",
26113 			"calling xmlSchemaCheckCOSValidDefault()");
26114 		    goto internal_error;
26115 		}
26116 		goto end_elem;
26117 	    }
26118 	    /*
26119 	    * Stop here, to avoid redundant validation of the value
26120 	    * (see following).
26121 	    */
26122 	    goto default_psvi;
26123 	}
26124 	/*
26125 	* cvc-elt (3.3.4) : 5.1.2
26126 	* The element information item with the canonical lexical
26127 	* representation of the {value constraint} value used as its
26128 	* `normalized value` must be `valid` with respect to the
26129 	* `actual type definition` as defined by Element Locally Valid (Type)
26130 	* ($3.3.4).
26131 	*/
26132 	if (WXS_IS_SIMPLE(inode->typeDef)) {
26133 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26134 		inode, inode->typeDef, inode->decl->value);
26135 	} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26136 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26137 		inode, inode->typeDef->contentTypeDef,
26138 		inode->decl->value);
26139 	}
26140 	if (ret != 0) {
26141 	    if (ret < 0) {
26142 		VERROR_INT("xmlSchemaValidatorPopElem",
26143 		    "calling xmlSchemaVCheckCVCSimpleType()");
26144 		goto internal_error;
26145 	    }
26146 	    goto end_elem;
26147 	}
26148 
26149 default_psvi:
26150 	/*
26151 	* PSVI: Create a text node on the instance element.
26152 	*/
26153 	if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
26154 	    (inode->node != NULL)) {
26155 	    xmlNodePtr textChild;
26156 	    xmlChar *normValue;
26157 	    /*
26158 	    * VAL TODO: Normalize the value.
26159 	    */
26160 	    normValue = xmlSchemaNormalizeValue(inode->typeDef,
26161 		inode->decl->value);
26162 	    if (normValue != NULL) {
26163 		textChild = xmlNewDocText(inode->node->doc,
26164                         BAD_CAST normValue);
26165 		xmlFree(normValue);
26166 	    } else
26167 		textChild = xmlNewDocText(inode->node->doc,
26168                         inode->decl->value);
26169 	    if (textChild == NULL) {
26170 		VERROR_INT("xmlSchemaValidatorPopElem",
26171 		    "calling xmlNewDocText()");
26172 		goto internal_error;
26173 	    } else
26174 		xmlAddChild(inode->node, textChild);
26175 	}
26176 
26177     } else if (! INODE_NILLED(inode)) {
26178 	/*
26179 	* 5.2.1 The element information item must be `valid` with respect
26180 	* to the `actual type definition` as defined by Element Locally
26181 	* Valid (Type) ($3.3.4).
26182 	*/
26183 	if (WXS_IS_SIMPLE(inode->typeDef)) {
26184 	     /*
26185 	    * SPEC (cvc-type) (3.1)
26186 	    * "If the type definition is a simple type definition, ..."
26187 	    * (3.1.3) "If clause 3.2 of Element Locally Valid
26188 	    * (Element) ($3.3.4) did not apply, then the `normalized value`
26189 	    * must be `valid` with respect to the type definition as defined
26190 	    * by String Valid ($3.14.4).
26191 	    */
26192 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26193 		    inode, inode->typeDef, inode->value);
26194 	} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26195 	    /*
26196 	    * SPEC (cvc-type) (3.2) "If the type definition is a complex type
26197 	    * definition, then the element information item must be
26198 	    * `valid` with respect to the type definition as per
26199 	    * Element Locally Valid (Complex Type) ($3.4.4);"
26200 	    *
26201 	    * SPEC (cvc-complex-type) (2.2)
26202 	    * "If the {content type} is a simple type definition, ...
26203 	    * the `normalized value` of the element information item is
26204 	    * `valid` with respect to that simple type definition as
26205 	    * defined by String Valid ($3.14.4)."
26206 	    */
26207 	    ret = xmlSchemaVCheckINodeDataType(vctxt,
26208 		inode, inode->typeDef->contentTypeDef, inode->value);
26209 	}
26210 	if (ret != 0) {
26211 	    if (ret < 0) {
26212 		VERROR_INT("xmlSchemaValidatorPopElem",
26213 		    "calling xmlSchemaVCheckCVCSimpleType()");
26214 		goto internal_error;
26215 	    }
26216 	    goto end_elem;
26217 	}
26218 	/*
26219 	* 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
26220 	* not applied, all of the following must be true:
26221 	*/
26222 	if ((inode->decl->value != NULL) &&
26223 	    (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
26224 
26225 	    /*
26226 	    * TODO: We will need a computed value, when comparison is
26227 	    * done on computed values.
26228 	    */
26229 	    /*
26230 	    * 5.2.2.1 The element information item must have no element
26231 	    * information item [children].
26232 	    */
26233 	    if (inode->flags &
26234 		    XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
26235 		ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
26236 		VERROR(ret, NULL,
26237 		    "The content must not contain element nodes since "
26238 		    "there is a fixed value constraint");
26239 		goto end_elem;
26240 	    } else {
26241 		/*
26242 		* 5.2.2.2 The appropriate case among the following must
26243 		* be true:
26244 		*/
26245 		if (WXS_HAS_MIXED_CONTENT(inode->typeDef)) {
26246 		    /*
26247 		    * 5.2.2.2.1 If the {content type} of the `actual type
26248 		    * definition` is mixed, then the *initial value* of the
26249 		    * item must match the canonical lexical representation
26250 		    * of the {value constraint} value.
26251 		    *
26252 		    * ... the *initial value* of an element information
26253 		    * item is the string composed of, in order, the
26254 		    * [character code] of each character information item in
26255 		    * the [children] of that element information item.
26256 		    */
26257 		    if (! xmlStrEqual(inode->value, inode->decl->value)){
26258 			/*
26259 			* VAL TODO: Report invalid & expected values as well.
26260 			* VAL TODO: Implement the canonical stuff.
26261 			*/
26262 			ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
26263 			xmlSchemaCustomErr(ACTXT_CAST vctxt,
26264 			    ret, NULL, NULL,
26265 			    "The initial value '%s' does not match the fixed "
26266 			    "value constraint '%s'",
26267 			    inode->value, inode->decl->value);
26268 			goto end_elem;
26269 		    }
26270 		} else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26271 		    /*
26272 		    * 5.2.2.2.2 If the {content type} of the `actual type
26273 		    * definition` is a simple type definition, then the
26274 		    * *actual value* of the item must match the canonical
26275 		    * lexical representation of the {value constraint} value.
26276 		    */
26277 		    /*
26278 		    * VAL TODO: *actual value* is the normalized value, impl.
26279 		    *           this.
26280 		    * VAL TODO: Report invalid & expected values as well.
26281 		    * VAL TODO: Implement a comparison with the computed values.
26282 		    */
26283 		    if (! xmlStrEqual(inode->value,
26284 			    inode->decl->value)) {
26285 			ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
26286 			xmlSchemaCustomErr(ACTXT_CAST vctxt,
26287 			    ret, NULL, NULL,
26288 			    "The actual value '%s' does not match the fixed "
26289 			    "value constraint '%s'",
26290 			    inode->value,
26291 			    inode->decl->value);
26292 			goto end_elem;
26293 		    }
26294 		}
26295 	    }
26296 	}
26297     }
26298 
26299 end_elem:
26300     if (vctxt->depth < 0) {
26301 	/* TODO: raise error? */
26302 	return (0);
26303     }
26304     if (vctxt->depth == vctxt->skipDepth)
26305 	vctxt->skipDepth = -1;
26306     /*
26307     * Evaluate the history of XPath state objects.
26308     */
26309     if (inode->appliedXPath &&
26310 	(xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1))
26311 	goto internal_error;
26312     /*
26313     * MAYBE TODO:
26314     * SPEC (6) "The element information item must be `valid` with
26315     * respect to each of the {identity-constraint definitions} as per
26316     * Identity-constraint Satisfied ($3.11.4)."
26317     */
26318     /*
26319     * PSVI TODO: If we expose IDC node-tables via PSVI then the tables
26320     *   need to be built in any case.
26321     *   We will currently build IDC node-tables and bubble them only if
26322     *   keyrefs do exist.
26323     */
26324 
26325     /*
26326     * Add the current IDC target-nodes to the IDC node-tables.
26327     */
26328     if ((inode->idcMatchers != NULL) &&
26329 	(vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26330     {
26331 	if (xmlSchemaIDCFillNodeTables(vctxt, inode) == -1)
26332 	    goto internal_error;
26333     }
26334     /*
26335     * Validate IDC keyrefs.
26336     */
26337     if (vctxt->inode->hasKeyrefs)
26338 	if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
26339 	    goto internal_error;
26340     /*
26341     * Merge/free the IDC table.
26342     */
26343     if (inode->idcTable != NULL) {
26344 	if ((vctxt->depth > 0) &&
26345 	    (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26346 	{
26347 	    /*
26348 	    * Merge the IDC node table with the table of the parent node.
26349 	    */
26350 	    if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
26351 		goto internal_error;
26352 	}
26353     }
26354     /*
26355     * Clear the current ielem.
26356     * VAL TODO: Don't free the PSVI IDC tables if they are
26357     * requested for the PSVI.
26358     */
26359     xmlSchemaClearElemInfo(vctxt, inode);
26360     /*
26361     * Skip further processing if we are on the validation root.
26362     */
26363     if (vctxt->depth == 0) {
26364 	vctxt->depth--;
26365 	vctxt->inode = NULL;
26366 	return (0);
26367     }
26368     /*
26369     * Reset the keyrefDepth if needed.
26370     */
26371     if (vctxt->aidcs != NULL) {
26372 	xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
26373 	do {
26374 	    if (aidc->keyrefDepth == vctxt->depth) {
26375 		/*
26376 		* A 'keyrefDepth' of a key/unique IDC matches the current
26377 		* depth, this means that we are leaving the scope of the
26378 		* top-most keyref IDC which refers to this IDC.
26379 		*/
26380 		aidc->keyrefDepth = -1;
26381 	    }
26382 	    aidc = aidc->next;
26383 	} while (aidc != NULL);
26384     }
26385     vctxt->depth--;
26386     vctxt->inode = vctxt->elemInfos[vctxt->depth];
26387     /*
26388     * VAL TODO: 7 If the element information item is the `validation root`, it must be
26389     * `valid` per Validation Root Valid (ID/IDREF) ($3.3.4).
26390     */
26391     return (ret);
26392 
26393 internal_error:
26394     vctxt->err = -1;
26395     return (-1);
26396 }
26397 
26398 /*
26399 * 3.4.4 Complex Type Definition Validation Rules
26400 * Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
26401 */
26402 static int
xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)26403 xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
26404 {
26405     xmlSchemaNodeInfoPtr pielem;
26406     xmlSchemaTypePtr ptype;
26407     int ret = 0;
26408 
26409     if (vctxt->depth <= 0) {
26410 	VERROR_INT("xmlSchemaValidateChildElem",
26411 	    "not intended for the validation root");
26412 	return (-1);
26413     }
26414     pielem = vctxt->elemInfos[vctxt->depth -1];
26415     if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26416 	pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26417     /*
26418     * Handle 'nilled' elements.
26419     */
26420     if (INODE_NILLED(pielem)) {
26421 	/*
26422 	* SPEC (cvc-elt) (3.3.4) : (3.2.1)
26423 	*/
26424 	ACTIVATE_PARENT_ELEM;
26425 	ret = XML_SCHEMAV_CVC_ELT_3_2_1;
26426 	VERROR(ret, NULL,
26427 	    "Neither character nor element content is allowed, "
26428 	    "because the element was 'nilled'");
26429 	ACTIVATE_ELEM;
26430 	goto unexpected_elem;
26431     }
26432 
26433     ptype = pielem->typeDef;
26434 
26435     if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
26436 	/*
26437 	* Workaround for "anyType": we have currently no content model
26438 	* assigned for "anyType", so handle it explicitly.
26439 	* "anyType" has an unbounded, lax "any" wildcard.
26440 	*/
26441 	vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26442 	    vctxt->inode->localName,
26443 	    vctxt->inode->nsName);
26444 
26445 	if (vctxt->inode->decl == NULL) {
26446 	    xmlSchemaAttrInfoPtr iattr;
26447 	    /*
26448 	    * Process "xsi:type".
26449 	    * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
26450 	    */
26451 	    iattr = xmlSchemaGetMetaAttrInfo(vctxt,
26452 		XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
26453 	    if (iattr != NULL) {
26454 		ret = xmlSchemaProcessXSIType(vctxt, iattr,
26455 		    &(vctxt->inode->typeDef), NULL);
26456 		if (ret != 0) {
26457 		    if (ret == -1) {
26458 			VERROR_INT("xmlSchemaValidateChildElem",
26459 			    "calling xmlSchemaProcessXSIType() to "
26460 			    "process the attribute 'xsi:nil'");
26461 			return (-1);
26462 		    }
26463 		    return (ret);
26464 		}
26465 	    } else {
26466 		 /*
26467 		 * Fallback to "anyType".
26468 		 *
26469 		 * SPEC (cvc-assess-elt)
26470 		 * "If the item cannot be `strictly assessed`, [...]
26471 		 * an element information item's schema validity may be laxly
26472 		 * assessed if its `context-determined declaration` is not
26473 		 * skip by `validating` with respect to the `ur-type
26474 		 * definition` as per Element Locally Valid (Type) ($3.3.4)."
26475 		*/
26476 		vctxt->inode->typeDef =
26477 		    xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
26478 	    }
26479 	}
26480 	return (0);
26481     }
26482 
26483     switch (ptype->contentType) {
26484 	case XML_SCHEMA_CONTENT_EMPTY:
26485 	    /*
26486 	    * SPEC (2.1) "If the {content type} is empty, then the
26487 	    * element information item has no character or element
26488 	    * information item [children]."
26489 	    */
26490 	    ACTIVATE_PARENT_ELEM
26491 	    ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
26492 	    VERROR(ret, NULL,
26493 		"Element content is not allowed, "
26494 		"because the content type is empty");
26495 	    ACTIVATE_ELEM
26496 	    goto unexpected_elem;
26497 	    break;
26498 
26499 	case XML_SCHEMA_CONTENT_MIXED:
26500         case XML_SCHEMA_CONTENT_ELEMENTS: {
26501 	    xmlRegExecCtxtPtr regexCtxt;
26502 	    xmlChar *values[10];
26503 	    int terminal, nbval = 10, nbneg;
26504 
26505 	    /* VAL TODO: Optimized "anyType" validation.*/
26506 
26507 	    if (ptype->contModel == NULL) {
26508 		VERROR_INT("xmlSchemaValidateChildElem",
26509 		    "type has elem content but no content model");
26510 		return (-1);
26511 	    }
26512 	    /*
26513 	    * Safety belt for evaluation if the cont. model was already
26514 	    * examined to be invalid.
26515 	    */
26516 	    if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
26517 		VERROR_INT("xmlSchemaValidateChildElem",
26518 		    "validating elem, but elem content is already invalid");
26519 		return (-1);
26520 	    }
26521 
26522 	    regexCtxt = pielem->regexCtxt;
26523 	    if (regexCtxt == NULL) {
26524 		/*
26525 		* Create the regex context.
26526 		*/
26527 		regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
26528 		    xmlSchemaVContentModelCallback, vctxt);
26529 		if (regexCtxt == NULL) {
26530 		    VERROR_INT("xmlSchemaValidateChildElem",
26531 			"failed to create a regex context");
26532 		    return (-1);
26533 		}
26534 		pielem->regexCtxt = regexCtxt;
26535 	    }
26536 
26537 	    /*
26538 	    * SPEC (2.4) "If the {content type} is element-only or mixed,
26539 	    * then the sequence of the element information item's
26540 	    * element information item [children], if any, taken in
26541 	    * order, is `valid` with respect to the {content type}'s
26542 	    * particle, as defined in Element Sequence Locally Valid
26543 	    * (Particle) ($3.9.4)."
26544 	    */
26545 	    ret = xmlRegExecPushString2(regexCtxt,
26546 		vctxt->inode->localName,
26547 		vctxt->inode->nsName,
26548 		vctxt->inode);
26549 	    if (vctxt->err == XML_SCHEMAV_INTERNAL) {
26550 		VERROR_INT("xmlSchemaValidateChildElem",
26551 		    "calling xmlRegExecPushString2()");
26552 		return (-1);
26553 	    }
26554 	    if (ret < 0) {
26555 		xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
26556 		    &values[0], &terminal);
26557 		xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26558 		    XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
26559 		    "This element is not expected",
26560 		    nbval, nbneg, values);
26561 		ret = vctxt->err;
26562 		goto unexpected_elem;
26563 	    } else
26564 		ret = 0;
26565 	}
26566 	    break;
26567 	case XML_SCHEMA_CONTENT_SIMPLE:
26568 	case XML_SCHEMA_CONTENT_BASIC:
26569 	    ACTIVATE_PARENT_ELEM
26570 	    if (WXS_IS_COMPLEX(ptype)) {
26571 		/*
26572 		* SPEC (cvc-complex-type) (2.2)
26573 		* "If the {content type} is a simple type definition, then
26574 		* the element information item has no element information
26575 		* item [children], ..."
26576 		*/
26577 		ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
26578 		VERROR(ret, NULL, "Element content is not allowed, "
26579 		    "because the content type is a simple type definition");
26580 	    } else {
26581 		/*
26582 		* SPEC (cvc-type) (3.1.2) "The element information item must
26583 		* have no element information item [children]."
26584 		*/
26585 		ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
26586 		VERROR(ret, NULL, "Element content is not allowed, "
26587 		    "because the type definition is simple");
26588 	    }
26589 	    ACTIVATE_ELEM
26590 	    ret = vctxt->err;
26591 	    goto unexpected_elem;
26592 	    break;
26593 
26594 	default:
26595 	    break;
26596     }
26597     return (ret);
26598 unexpected_elem:
26599     /*
26600     * Pop this element and set the skipDepth to skip
26601     * all further content of the parent element.
26602     */
26603     vctxt->skipDepth = vctxt->depth;
26604     vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
26605     pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26606     return (ret);
26607 }
26608 
26609 #define XML_SCHEMA_PUSH_TEXT_PERSIST 1
26610 #define XML_SCHEMA_PUSH_TEXT_CREATED 2
26611 #define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
26612 
26613 static int
xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,int nodeType,const xmlChar * value,int len,int mode,int * consumed)26614 xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
26615 		  int nodeType, const xmlChar *value, int len,
26616 		  int mode, int *consumed)
26617 {
26618     /*
26619     * Unfortunately we have to duplicate the text sometimes.
26620     * OPTIMIZE: Maybe we could skip it, if:
26621     *   1. content type is simple
26622     *   2. whitespace is "collapse"
26623     *   3. it consists of whitespace only
26624     *
26625     * Process character content.
26626     */
26627     if (consumed != NULL)
26628 	*consumed = 0;
26629     if (INODE_NILLED(vctxt->inode)) {
26630 	/*
26631 	* SPEC cvc-elt (3.3.4 - 3.2.1)
26632 	* "The element information item must have no character or
26633 	* element information item [children]."
26634 	*/
26635 	VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
26636 	    "Neither character nor element content is allowed "
26637 	    "because the element is 'nilled'");
26638 	return (vctxt->err);
26639     }
26640     /*
26641     * SPEC (2.1) "If the {content type} is empty, then the
26642     * element information item has no character or element
26643     * information item [children]."
26644     */
26645     if (vctxt->inode->typeDef->contentType ==
26646 	    XML_SCHEMA_CONTENT_EMPTY) {
26647 	VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
26648 	    "Character content is not allowed, "
26649 	    "because the content type is empty");
26650 	return (vctxt->err);
26651     }
26652 
26653     if (vctxt->inode->typeDef->contentType ==
26654 	    XML_SCHEMA_CONTENT_ELEMENTS) {
26655 	if ((nodeType != XML_TEXT_NODE) ||
26656 	    (! xmlSchemaIsBlank((xmlChar *) value, len))) {
26657 	    /*
26658 	    * SPEC cvc-complex-type (2.3)
26659 	    * "If the {content type} is element-only, then the
26660 	    * element information item has no character information
26661 	    * item [children] other than those whose [character
26662 	    * code] is defined as a white space in [XML 1.0 (Second
26663 	    * Edition)]."
26664 	    */
26665 	    VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
26666 		"Character content other than whitespace is not allowed "
26667 		"because the content type is 'element-only'");
26668 	    return (vctxt->err);
26669 	}
26670 	return (0);
26671     }
26672 
26673     if ((value == NULL) || (value[0] == 0))
26674 	return (0);
26675     /*
26676     * Save the value.
26677     * NOTE that even if the content type is *mixed*, we need the
26678     * *initial value* for default/fixed value constraints.
26679     */
26680     if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
26681 	((vctxt->inode->decl == NULL) ||
26682 	(vctxt->inode->decl->value == NULL)))
26683 	return (0);
26684 
26685     if (vctxt->inode->value == NULL) {
26686 	/*
26687 	* Set the value.
26688 	*/
26689 	switch (mode) {
26690 	    case XML_SCHEMA_PUSH_TEXT_PERSIST:
26691 		/*
26692 		* When working on a tree.
26693 		*/
26694 		vctxt->inode->value = value;
26695 		vctxt->inode->flags &=
26696 		    ~XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26697 		break;
26698 	    case XML_SCHEMA_PUSH_TEXT_CREATED:
26699 		/*
26700 		* When working with the reader.
26701 		* The value will be freed by the element info.
26702 		*/
26703 		vctxt->inode->value = value;
26704 		if (consumed != NULL)
26705 		    *consumed = 1;
26706 		vctxt->inode->flags |=
26707 		    XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26708 		break;
26709 	    case XML_SCHEMA_PUSH_TEXT_VOLATILE:
26710 		/*
26711 		* When working with SAX.
26712 		* The value will be freed by the element info.
26713 		*/
26714 		if (len != -1)
26715 		    vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
26716 		else
26717 		    vctxt->inode->value = BAD_CAST xmlStrdup(value);
26718 		vctxt->inode->flags |=
26719 		    XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26720 		break;
26721 	    default:
26722 		break;
26723 	}
26724     } else {
26725 	if (len < 0)
26726 	    len = xmlStrlen(value);
26727 	/*
26728 	* Concat the value.
26729 	*/
26730 	if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
26731 	    vctxt->inode->value = BAD_CAST xmlStrncat(
26732 		(xmlChar *) vctxt->inode->value, value, len);
26733 	} else {
26734 	    vctxt->inode->value =
26735 		BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
26736 	    vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26737 	}
26738     }
26739 
26740     return (0);
26741 }
26742 
26743 static int
xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)26744 xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
26745 {
26746     int ret = 0;
26747 
26748     if ((vctxt->skipDepth != -1) &&
26749 	(vctxt->depth >= vctxt->skipDepth)) {
26750 	VERROR_INT("xmlSchemaValidateElem",
26751 	    "in skip-state");
26752 	goto internal_error;
26753     }
26754     if (vctxt->xsiAssemble) {
26755 	/*
26756 	* We will stop validation if there was an error during
26757 	* dynamic schema construction.
26758 	* Note that we simply set @skipDepth to 0, this could
26759 	* mean that a streaming document via SAX would be
26760 	* still read to the end but it won't be validated any more.
26761 	* TODO: If we are sure how to stop the validation at once
26762 	*   for all input scenarios, then this should be changed to
26763 	*   instantly stop the validation.
26764 	*/
26765 	ret = xmlSchemaAssembleByXSI(vctxt);
26766 	if (ret != 0) {
26767 	    if (ret == -1)
26768 		goto internal_error;
26769 	    vctxt->skipDepth = 0;
26770 	    return(ret);
26771 	}
26772         /*
26773          * Augment the IDC definitions for the main schema and all imported ones
26774          * NOTE: main schema is the first in the imported list
26775          */
26776         xmlHashScan(vctxt->schema->schemasImports, xmlSchemaAugmentImportedIDC,
26777                     vctxt);
26778     }
26779     if (vctxt->depth > 0) {
26780 	/*
26781 	* Validate this element against the content model
26782 	* of the parent.
26783 	*/
26784 	ret = xmlSchemaValidateChildElem(vctxt);
26785 	if (ret != 0) {
26786 	    if (ret < 0) {
26787 		VERROR_INT("xmlSchemaValidateElem",
26788 		    "calling xmlSchemaStreamValidateChildElement()");
26789 		goto internal_error;
26790 	    }
26791 	    goto exit;
26792 	}
26793 	if (vctxt->depth == vctxt->skipDepth)
26794 	    goto exit;
26795 	if ((vctxt->inode->decl == NULL) &&
26796 	    (vctxt->inode->typeDef == NULL)) {
26797 	    VERROR_INT("xmlSchemaValidateElem",
26798 		"the child element was valid but neither the "
26799 		"declaration nor the type was set");
26800 	    goto internal_error;
26801 	}
26802     } else {
26803 	/*
26804 	* Get the declaration of the validation root.
26805 	*/
26806 	vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26807 	    vctxt->inode->localName,
26808 	    vctxt->inode->nsName);
26809 	if (vctxt->inode->decl == NULL) {
26810 	    ret = XML_SCHEMAV_CVC_ELT_1;
26811 	    VERROR(ret, NULL,
26812 		"No matching global declaration available "
26813 		"for the validation root");
26814 	    goto exit;
26815 	}
26816     }
26817 
26818     if (vctxt->inode->decl == NULL)
26819 	goto type_validation;
26820 
26821     if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
26822 	int skip;
26823 	/*
26824 	* Wildcards.
26825 	*/
26826 	ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
26827 	if (ret != 0) {
26828 	    if (ret < 0) {
26829 		VERROR_INT("xmlSchemaValidateElem",
26830 		    "calling xmlSchemaValidateElemWildcard()");
26831 		goto internal_error;
26832 	    }
26833 	    goto exit;
26834 	}
26835 	if (skip) {
26836 	    vctxt->skipDepth = vctxt->depth;
26837 	    goto exit;
26838 	}
26839 	/*
26840 	* The declaration might be set by the wildcard validation,
26841 	* when the processContents is "lax" or "strict".
26842 	*/
26843 	if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
26844 	    /*
26845 	    * Clear the "decl" field to not confuse further processing.
26846 	    */
26847 	    vctxt->inode->decl = NULL;
26848 	    goto type_validation;
26849 	}
26850     }
26851     /*
26852     * Validate against the declaration.
26853     */
26854     ret = xmlSchemaValidateElemDecl(vctxt);
26855     if (ret != 0) {
26856 	if (ret < 0) {
26857 	    VERROR_INT("xmlSchemaValidateElem",
26858 		"calling xmlSchemaValidateElemDecl()");
26859 	    goto internal_error;
26860 	}
26861 	goto exit;
26862     }
26863     /*
26864     * Validate against the type definition.
26865     */
26866 type_validation:
26867 
26868     if (vctxt->inode->typeDef == NULL) {
26869 	vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26870 	ret = XML_SCHEMAV_CVC_TYPE_1;
26871 	VERROR(ret, NULL,
26872 	    "The type definition is absent");
26873 	goto exit;
26874     }
26875     if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
26876 	vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26877 	ret = XML_SCHEMAV_CVC_TYPE_2;
26878 	    VERROR(ret, NULL,
26879 	    "The type definition is abstract");
26880 	goto exit;
26881     }
26882     /*
26883     * Evaluate IDCs. Do it here, since new IDC matchers are registered
26884     * during validation against the declaration. This must be done
26885     * _before_ attribute validation.
26886     */
26887     if (vctxt->xpathStates != NULL) {
26888 	ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
26889 	vctxt->inode->appliedXPath = 1;
26890 	if (ret == -1) {
26891 	    VERROR_INT("xmlSchemaValidateElem",
26892 		"calling xmlSchemaXPathEvaluate()");
26893 	    goto internal_error;
26894 	}
26895     }
26896     /*
26897     * Validate attributes.
26898     */
26899     if (WXS_IS_COMPLEX(vctxt->inode->typeDef)) {
26900 	if ((vctxt->nbAttrInfos != 0) ||
26901 	    (vctxt->inode->typeDef->attrUses != NULL)) {
26902 
26903 	    ret = xmlSchemaVAttributesComplex(vctxt);
26904 	}
26905     } else if (vctxt->nbAttrInfos != 0) {
26906 
26907 	ret = xmlSchemaVAttributesSimple(vctxt);
26908     }
26909     /*
26910     * Clear registered attributes.
26911     */
26912     if (vctxt->nbAttrInfos != 0)
26913 	xmlSchemaClearAttrInfos(vctxt);
26914     if (ret == -1) {
26915 	VERROR_INT("xmlSchemaValidateElem",
26916 	    "calling attributes validation");
26917 	goto internal_error;
26918     }
26919     /*
26920     * Don't return an error if attributes are invalid on purpose.
26921     */
26922     ret = 0;
26923 
26924 exit:
26925     if (ret != 0)
26926 	vctxt->skipDepth = vctxt->depth;
26927     return (ret);
26928 internal_error:
26929     return (-1);
26930 }
26931 
26932 #ifdef XML_SCHEMA_READER_ENABLED
26933 static int
xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)26934 xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
26935 {
26936     const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
26937     int depth, nodeType, ret = 0, consumed;
26938     xmlSchemaNodeInfoPtr ielem;
26939 
26940     vctxt->depth = -1;
26941     ret = xmlTextReaderRead(vctxt->reader);
26942     /*
26943     * Move to the document element.
26944     */
26945     while (ret == 1) {
26946 	nodeType = xmlTextReaderNodeType(vctxt->reader);
26947 	if (nodeType == XML_ELEMENT_NODE)
26948 	    goto root_found;
26949 	ret = xmlTextReaderRead(vctxt->reader);
26950     }
26951     goto exit;
26952 
26953 root_found:
26954 
26955     do {
26956 	depth = xmlTextReaderDepth(vctxt->reader);
26957 	nodeType = xmlTextReaderNodeType(vctxt->reader);
26958 
26959 	if (nodeType == XML_ELEMENT_NODE) {
26960 
26961 	    vctxt->depth++;
26962 	    if (xmlSchemaValidatorPushElem(vctxt) == -1) {
26963 		VERROR_INT("xmlSchemaVReaderWalk",
26964 		    "calling xmlSchemaValidatorPushElem()");
26965 		goto internal_error;
26966 	    }
26967 	    ielem = vctxt->inode;
26968 	    ielem->localName = xmlTextReaderLocalName(vctxt->reader);
26969 	    ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
26970 	    ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
26971 	    /*
26972 	    * Is the element empty?
26973 	    */
26974 	    ret = xmlTextReaderIsEmptyElement(vctxt->reader);
26975 	    if (ret == -1) {
26976 		VERROR_INT("xmlSchemaVReaderWalk",
26977 		    "calling xmlTextReaderIsEmptyElement()");
26978 		goto internal_error;
26979 	    }
26980 	    if (ret) {
26981 		ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
26982 	    }
26983 	    /*
26984 	    * Register attributes.
26985 	    */
26986 	    vctxt->nbAttrInfos = 0;
26987 	    ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
26988 	    if (ret == -1) {
26989 		VERROR_INT("xmlSchemaVReaderWalk",
26990 		    "calling xmlTextReaderMoveToFirstAttribute()");
26991 		goto internal_error;
26992 	    }
26993 	    if (ret == 1) {
26994 		do {
26995 		    /*
26996 		    * VAL TODO: How do we know that the reader works on a
26997 		    * node tree, to be able to pass a node here?
26998 		    */
26999 		    if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
27000 			(const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
27001 			xmlTextReaderNamespaceUri(vctxt->reader), 1,
27002 			xmlTextReaderValue(vctxt->reader), 1) == -1) {
27003 
27004 			VERROR_INT("xmlSchemaVReaderWalk",
27005 			    "calling xmlSchemaValidatorPushAttribute()");
27006 			goto internal_error;
27007 		    }
27008 		    ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
27009 		    if (ret == -1) {
27010 			VERROR_INT("xmlSchemaVReaderWalk",
27011 			    "calling xmlTextReaderMoveToFirstAttribute()");
27012 			goto internal_error;
27013 		    }
27014 		} while (ret == 1);
27015 		/*
27016 		* Back to element position.
27017 		*/
27018 		ret = xmlTextReaderMoveToElement(vctxt->reader);
27019 		if (ret == -1) {
27020 		    VERROR_INT("xmlSchemaVReaderWalk",
27021 			"calling xmlTextReaderMoveToElement()");
27022 		    goto internal_error;
27023 		}
27024 	    }
27025 	    /*
27026 	    * Validate the element.
27027 	    */
27028 	    ret= xmlSchemaValidateElem(vctxt);
27029 	    if (ret != 0) {
27030 		if (ret == -1) {
27031 		    VERROR_INT("xmlSchemaVReaderWalk",
27032 			"calling xmlSchemaValidateElem()");
27033 		    goto internal_error;
27034 		}
27035 		goto exit;
27036 	    }
27037 	    if (vctxt->depth == vctxt->skipDepth) {
27038 		int curDepth;
27039 		/*
27040 		* Skip all content.
27041 		*/
27042 		if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
27043 		    ret = xmlTextReaderRead(vctxt->reader);
27044 		    curDepth = xmlTextReaderDepth(vctxt->reader);
27045 		    while ((ret == 1) && (curDepth != depth)) {
27046 			ret = xmlTextReaderRead(vctxt->reader);
27047 			curDepth = xmlTextReaderDepth(vctxt->reader);
27048 		    }
27049 		    if (ret < 0) {
27050 			/*
27051 			* VAL TODO: A reader error occurred; what to do here?
27052 			*/
27053 			ret = 1;
27054 			goto exit;
27055 		    }
27056 		}
27057 		goto leave_elem;
27058 	    }
27059 	    /*
27060 	    * READER VAL TODO: Is an END_ELEM really never called
27061 	    * if the elem is empty?
27062 	    */
27063 	    if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27064 		goto leave_elem;
27065 	} else if (nodeType == END_ELEM) {
27066 	    /*
27067 	    * Process END of element.
27068 	    */
27069 leave_elem:
27070 	    ret = xmlSchemaValidatorPopElem(vctxt);
27071 	    if (ret != 0) {
27072 		if (ret < 0) {
27073 		    VERROR_INT("xmlSchemaVReaderWalk",
27074 			"calling xmlSchemaValidatorPopElem()");
27075 		    goto internal_error;
27076 		}
27077 		goto exit;
27078 	    }
27079 	    if (vctxt->depth >= 0)
27080 		ielem = vctxt->inode;
27081 	    else
27082 		ielem = NULL;
27083 	} else if ((nodeType == XML_TEXT_NODE) ||
27084 	    (nodeType == XML_CDATA_SECTION_NODE) ||
27085 	    (nodeType == WHTSP) ||
27086 	    (nodeType == SIGN_WHTSP)) {
27087 	    /*
27088 	    * Process character content.
27089 	    */
27090 	    xmlChar *value;
27091 
27092 	    if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
27093 		nodeType = XML_TEXT_NODE;
27094 
27095 	    value = xmlTextReaderValue(vctxt->reader);
27096 	    ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
27097 		-1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
27098 	    if (! consumed)
27099 		xmlFree(value);
27100 	    if (ret == -1) {
27101 		VERROR_INT("xmlSchemaVReaderWalk",
27102 		    "calling xmlSchemaVPushText()");
27103 		goto internal_error;
27104 	    }
27105 	} else if ((nodeType == XML_ENTITY_NODE) ||
27106 	    (nodeType == XML_ENTITY_REF_NODE)) {
27107 	    /*
27108 	    * VAL TODO: What to do with entities?
27109 	    */
27110 	    TODO
27111 	}
27112 	/*
27113 	* Read next node.
27114 	*/
27115 	ret = xmlTextReaderRead(vctxt->reader);
27116     } while (ret == 1);
27117 
27118 exit:
27119     return (ret);
27120 internal_error:
27121     return (-1);
27122 }
27123 #endif
27124 
27125 /************************************************************************
27126  *									*
27127  *			SAX validation handlers				*
27128  *									*
27129  ************************************************************************/
27130 
27131 /*
27132 * Process text content.
27133 */
27134 static void
xmlSchemaSAXHandleText(void * ctx,const xmlChar * ch,int len)27135 xmlSchemaSAXHandleText(void *ctx,
27136 		       const xmlChar * ch,
27137 		       int len)
27138 {
27139     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27140 
27141     if (vctxt->depth < 0)
27142 	return;
27143     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27144 	return;
27145     if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27146 	vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27147     if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
27148 	XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27149 	VERROR_INT("xmlSchemaSAXHandleCDataSection",
27150 	    "calling xmlSchemaVPushText()");
27151 	vctxt->err = -1;
27152 	xmlStopParser(vctxt->parserCtxt);
27153     }
27154 }
27155 
27156 /*
27157 * Process CDATA content.
27158 */
27159 static void
xmlSchemaSAXHandleCDataSection(void * ctx,const xmlChar * ch,int len)27160 xmlSchemaSAXHandleCDataSection(void *ctx,
27161 			     const xmlChar * ch,
27162 			     int len)
27163 {
27164     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27165 
27166     if (vctxt->depth < 0)
27167 	return;
27168     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27169 	return;
27170     if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27171 	vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27172     if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
27173 	XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27174 	VERROR_INT("xmlSchemaSAXHandleCDataSection",
27175 	    "calling xmlSchemaVPushText()");
27176 	vctxt->err = -1;
27177 	xmlStopParser(vctxt->parserCtxt);
27178     }
27179 }
27180 
27181 static void
xmlSchemaSAXHandleReference(void * ctx ATTRIBUTE_UNUSED,const xmlChar * name ATTRIBUTE_UNUSED)27182 xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
27183 			    const xmlChar * name ATTRIBUTE_UNUSED)
27184 {
27185     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27186 
27187     if (vctxt->depth < 0)
27188 	return;
27189     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27190 	return;
27191     /* SAX VAL TODO: What to do here? */
27192 }
27193 
27194 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)27195 xmlSchemaSAXHandleStartElementNs(void *ctx,
27196 				 const xmlChar * localname,
27197 				 const xmlChar * prefix ATTRIBUTE_UNUSED,
27198 				 const xmlChar * URI,
27199 				 int nb_namespaces,
27200 				 const xmlChar ** namespaces,
27201 				 int nb_attributes,
27202 				 int nb_defaulted ATTRIBUTE_UNUSED,
27203 				 const xmlChar ** attributes)
27204 {
27205     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27206     int ret;
27207     xmlSchemaNodeInfoPtr ielem;
27208     int i, j;
27209 
27210     /*
27211     * SAX VAL TODO: What to do with nb_defaulted?
27212     */
27213     /*
27214     * Skip elements if inside a "skip" wildcard or invalid.
27215     */
27216     vctxt->depth++;
27217     if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27218 	return;
27219     /*
27220     * Push the element.
27221     */
27222     if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27223 	VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27224 	    "calling xmlSchemaValidatorPushElem()");
27225 	goto internal_error;
27226     }
27227     ielem = vctxt->inode;
27228     /*
27229     * TODO: Is this OK?
27230     */
27231     ielem->nodeLine = xmlSAX2GetLineNumber(vctxt->parserCtxt);
27232     ielem->localName = localname;
27233     ielem->nsName = URI;
27234     ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27235     /*
27236     * Register namespaces on the elem info.
27237     */
27238     if (nb_namespaces != 0) {
27239 	/*
27240 	* Although the parser builds its own namespace list,
27241 	* we have no access to it, so we'll use an own one.
27242 	*/
27243         for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
27244 	    /*
27245 	    * Store prefix and namespace name.
27246 	    */
27247             if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
27248                 const xmlChar **tmp;
27249                 size_t elemSize = 2 * sizeof(tmp[0]);
27250                 int newSize;
27251 
27252                 newSize = xmlGrowCapacity(ielem->sizeNsBindings, elemSize,
27253                                           5, XML_MAX_ITEMS);
27254                 if (newSize < 0) {
27255                     xmlSchemaVErrMemory(vctxt);
27256                     goto internal_error;
27257                 }
27258                 tmp = xmlRealloc(ielem->nsBindings, newSize * elemSize);
27259                 if (tmp == NULL) {
27260                     xmlSchemaVErrMemory(vctxt);
27261                     goto internal_error;
27262                 }
27263 
27264                 ielem->nsBindings = tmp;
27265                 ielem->sizeNsBindings = newSize;
27266 	    }
27267 
27268 	    ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
27269 	    if (namespaces[j+1][0] == 0) {
27270 		/*
27271 		* Handle xmlns="".
27272 		*/
27273 		ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
27274 	    } else
27275 		ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
27276 		    namespaces[j+1];
27277 	    ielem->nbNsBindings++;
27278 	}
27279     }
27280     /*
27281     * Register attributes.
27282     * SAX VAL TODO: We are not adding namespace declaration
27283     * attributes yet.
27284     */
27285     if (nb_attributes != 0) {
27286 	int valueLen, k, l;
27287 	xmlChar *value;
27288 
27289         for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
27290 	    /*
27291 	    * Duplicate the value, changing any &#38; to a literal ampersand.
27292 	    *
27293 	    * libxml2 differs from normal SAX here in that it escapes all ampersands
27294 	    * as &#38; instead of delivering the raw converted string. Changing the
27295 	    * behavior at this point would break applications that use this API, so
27296 	    * we are forced to work around it.
27297 	    */
27298 	    valueLen = attributes[j+4] - attributes[j+3];
27299 	    value = xmlMalloc(valueLen + 1);
27300 	    if (value == NULL) {
27301 		xmlSchemaVErrMemory(vctxt);
27302 		goto internal_error;
27303 	    }
27304 	    for (k = 0, l = 0; k < valueLen; l++) {
27305 		if (k < valueLen - 4 &&
27306 		    attributes[j+3][k+0] == '&' &&
27307 		    attributes[j+3][k+1] == '#' &&
27308 		    attributes[j+3][k+2] == '3' &&
27309 		    attributes[j+3][k+3] == '8' &&
27310 		    attributes[j+3][k+4] == ';') {
27311 		    value[l] = '&';
27312 		    k += 5;
27313 		} else {
27314 		    value[l] = attributes[j+3][k];
27315 		    k++;
27316 		}
27317 	    }
27318 	    value[l] = '\0';
27319 	    /*
27320 	    * TODO: Set the node line.
27321 	    */
27322 	    ret = xmlSchemaValidatorPushAttribute(vctxt,
27323 		NULL, ielem->nodeLine, attributes[j], attributes[j+2], 0,
27324 		value, 1);
27325 	    if (ret == -1) {
27326 		VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27327 		    "calling xmlSchemaValidatorPushAttribute()");
27328 		goto internal_error;
27329 	    }
27330 	}
27331     }
27332     /*
27333     * Validate the element.
27334     */
27335     ret = xmlSchemaValidateElem(vctxt);
27336     if (ret != 0) {
27337 	if (ret == -1) {
27338 	    VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27339 		"calling xmlSchemaValidateElem()");
27340 	    goto internal_error;
27341 	}
27342 	goto exit;
27343     }
27344 
27345 exit:
27346     return;
27347 internal_error:
27348     vctxt->err = -1;
27349     xmlStopParser(vctxt->parserCtxt);
27350 }
27351 
27352 static void
xmlSchemaSAXHandleEndElementNs(void * ctx,const xmlChar * localname ATTRIBUTE_UNUSED,const xmlChar * prefix ATTRIBUTE_UNUSED,const xmlChar * URI ATTRIBUTE_UNUSED)27353 xmlSchemaSAXHandleEndElementNs(void *ctx,
27354 			       const xmlChar * localname ATTRIBUTE_UNUSED,
27355 			       const xmlChar * prefix ATTRIBUTE_UNUSED,
27356 			       const xmlChar * URI ATTRIBUTE_UNUSED)
27357 {
27358     xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27359     int res;
27360 
27361     /*
27362     * Skip elements if inside a "skip" wildcard or if invalid.
27363     */
27364     if (vctxt->skipDepth != -1) {
27365 	if (vctxt->depth > vctxt->skipDepth) {
27366 	    vctxt->depth--;
27367 	    return;
27368 	} else
27369 	    vctxt->skipDepth = -1;
27370     }
27371     /*
27372     * SAX VAL TODO: Just a temporary check.
27373     */
27374     if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
27375 	(!xmlStrEqual(vctxt->inode->nsName, URI))) {
27376 	VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27377 	    "elem pop mismatch");
27378     }
27379     res = xmlSchemaValidatorPopElem(vctxt);
27380     if (res != 0) {
27381 	if (res < 0) {
27382 	    VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27383 		"calling xmlSchemaValidatorPopElem()");
27384 	    goto internal_error;
27385 	}
27386 	goto exit;
27387     }
27388 exit:
27389     return;
27390 internal_error:
27391     vctxt->err = -1;
27392     xmlStopParser(vctxt->parserCtxt);
27393 }
27394 
27395 /************************************************************************
27396  *									*
27397  *			Validation interfaces				*
27398  *									*
27399  ************************************************************************/
27400 
27401 /**
27402  * xmlSchemaNewValidCtxt:
27403  * @schema:  a precompiled XML Schemas
27404  *
27405  * Create an XML Schemas validation context based on the given schema.
27406  *
27407  * Returns the validation context or NULL in case of error
27408  */
27409 xmlSchemaValidCtxtPtr
xmlSchemaNewValidCtxt(xmlSchemaPtr schema)27410 xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
27411 {
27412     xmlSchemaValidCtxtPtr ret;
27413 
27414     ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
27415     if (ret == NULL) {
27416         xmlSchemaVErrMemory(NULL);
27417         return (NULL);
27418     }
27419     memset(ret, 0, sizeof(xmlSchemaValidCtxt));
27420     ret->type = XML_SCHEMA_CTXT_VALIDATOR;
27421     ret->dict = xmlDictCreate();
27422     if (ret->dict == NULL) {
27423         xmlSchemaFreeValidCtxt(ret);
27424         return(NULL);
27425     }
27426     ret->nodeQNames = xmlSchemaItemListCreate();
27427     if (ret->nodeQNames == NULL) {
27428         xmlSchemaFreeValidCtxt(ret);
27429         return(NULL);
27430     }
27431     ret->schema = schema;
27432     return (ret);
27433 }
27434 
27435 /**
27436  * xmlSchemaValidateSetFilename:
27437  * @vctxt: the schema validation context
27438  * @filename: the file name
27439  *
27440  * Workaround to provide file error reporting information when this is
27441  * not provided by current APIs
27442  */
27443 void
xmlSchemaValidateSetFilename(xmlSchemaValidCtxtPtr vctxt,const char * filename)27444 xmlSchemaValidateSetFilename(xmlSchemaValidCtxtPtr vctxt, const char *filename) {
27445     if (vctxt == NULL)
27446         return;
27447     if (vctxt->filename != NULL)
27448         xmlFree(vctxt->filename);
27449     if (filename != NULL)
27450         vctxt->filename = (char *) xmlStrdup((const xmlChar *) filename);
27451     else
27452         vctxt->filename = NULL;
27453 }
27454 
27455 /**
27456  * xmlSchemaClearValidCtxt:
27457  * @vctxt: the schema validation context
27458  *
27459  * Free the resources associated to the schema validation context;
27460  * leaves some fields alive intended for reuse of the context.
27461  */
27462 static void
xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)27463 xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
27464 {
27465     if (vctxt == NULL)
27466         return;
27467 
27468     /*
27469     * TODO: Should we clear the flags?
27470     *   Might be problematic if one reuses the context
27471     *   and assumes that the options remain the same.
27472     */
27473     vctxt->flags = 0;
27474     vctxt->validationRoot = NULL;
27475     vctxt->doc = NULL;
27476 #ifdef LIBXML_READER_ENABLED
27477     vctxt->reader = NULL;
27478 #endif
27479     vctxt->hasKeyrefs = 0;
27480 
27481     if (vctxt->value != NULL) {
27482         xmlSchemaFreeValue(vctxt->value);
27483 	vctxt->value = NULL;
27484     }
27485     /*
27486     * Augmented IDC information.
27487     */
27488     if (vctxt->aidcs != NULL) {
27489 	xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
27490 	do {
27491 	    next = cur->next;
27492 	    xmlFree(cur);
27493 	    cur = next;
27494 	} while (cur != NULL);
27495 	vctxt->aidcs = NULL;
27496     }
27497 
27498     if (vctxt->idcNodes != NULL) {
27499 	int i;
27500 	xmlSchemaPSVIIDCNodePtr item;
27501 
27502 	for (i = 0; i < vctxt->nbIdcNodes; i++) {
27503 	    item = vctxt->idcNodes[i];
27504 	    xmlFree(item->keys);
27505 	    xmlFree(item);
27506 	}
27507 	xmlFree(vctxt->idcNodes);
27508 	vctxt->idcNodes = NULL;
27509 	vctxt->nbIdcNodes = 0;
27510 	vctxt->sizeIdcNodes = 0;
27511     }
27512 
27513     if (vctxt->idcKeys != NULL) {
27514 	int i;
27515 	for (i = 0; i < vctxt->nbIdcKeys; i++)
27516 	    xmlSchemaIDCFreeKey(vctxt->idcKeys[i]);
27517 	xmlFree(vctxt->idcKeys);
27518 	vctxt->idcKeys = NULL;
27519 	vctxt->nbIdcKeys = 0;
27520 	vctxt->sizeIdcKeys = 0;
27521     }
27522 
27523     /*
27524     * Note that we won't delete the XPath state pool here.
27525     */
27526     if (vctxt->xpathStates != NULL) {
27527 	xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
27528 	vctxt->xpathStates = NULL;
27529     }
27530     /*
27531     * Attribute info.
27532     */
27533     if (vctxt->nbAttrInfos != 0) {
27534 	xmlSchemaClearAttrInfos(vctxt);
27535     }
27536     /*
27537     * Element info.
27538     */
27539     if (vctxt->elemInfos != NULL) {
27540 	int i;
27541 	xmlSchemaNodeInfoPtr ei;
27542 
27543 	for (i = 0; i < vctxt->sizeElemInfos; i++) {
27544 	    ei = vctxt->elemInfos[i];
27545 	    if (ei == NULL)
27546 		break;
27547 	    xmlSchemaClearElemInfo(vctxt, ei);
27548 	}
27549     }
27550     xmlSchemaItemListClear(vctxt->nodeQNames);
27551     /* Recreate the dict. */
27552     xmlDictFree(vctxt->dict);
27553     /*
27554     * TODO: Is is save to recreate it? Do we have a scenario
27555     * where the user provides the dict?
27556     */
27557     vctxt->dict = xmlDictCreate();
27558 
27559     if (vctxt->filename != NULL) {
27560         xmlFree(vctxt->filename);
27561 	vctxt->filename = NULL;
27562     }
27563 
27564     /*
27565      * Note that some cleanup functions can move items to the cache,
27566      * so the cache shouldn't be freed too early.
27567      */
27568     if (vctxt->idcMatcherCache != NULL) {
27569 	xmlSchemaIDCMatcherPtr matcher = vctxt->idcMatcherCache, tmp;
27570 
27571 	while (matcher) {
27572 	    tmp = matcher;
27573 	    matcher = matcher->nextCached;
27574 	    xmlSchemaIDCFreeMatcherList(tmp);
27575 	}
27576 	vctxt->idcMatcherCache = NULL;
27577     }
27578 }
27579 
27580 /**
27581  * xmlSchemaFreeValidCtxt:
27582  * @ctxt:  the schema validation context
27583  *
27584  * Free the resources associated to the schema validation context
27585  */
27586 void
xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)27587 xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
27588 {
27589     if (ctxt == NULL)
27590         return;
27591     if (ctxt->value != NULL)
27592         xmlSchemaFreeValue(ctxt->value);
27593     if (ctxt->pctxt != NULL)
27594 	xmlSchemaFreeParserCtxt(ctxt->pctxt);
27595     if (ctxt->idcNodes != NULL) {
27596 	int i;
27597 	xmlSchemaPSVIIDCNodePtr item;
27598 
27599 	for (i = 0; i < ctxt->nbIdcNodes; i++) {
27600 	    item = ctxt->idcNodes[i];
27601 	    xmlFree(item->keys);
27602 	    xmlFree(item);
27603 	}
27604 	xmlFree(ctxt->idcNodes);
27605     }
27606     if (ctxt->idcKeys != NULL) {
27607 	int i;
27608 	for (i = 0; i < ctxt->nbIdcKeys; i++)
27609 	    xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
27610 	xmlFree(ctxt->idcKeys);
27611     }
27612 
27613     if (ctxt->xpathStates != NULL) {
27614 	xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
27615 	ctxt->xpathStates = NULL;
27616     }
27617     if (ctxt->xpathStatePool != NULL) {
27618 	xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
27619 	ctxt->xpathStatePool = NULL;
27620     }
27621 
27622     /*
27623     * Augmented IDC information.
27624     */
27625     if (ctxt->aidcs != NULL) {
27626 	xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
27627 	do {
27628 	    next = cur->next;
27629 	    xmlFree(cur);
27630 	    cur = next;
27631 	} while (cur != NULL);
27632     }
27633     if (ctxt->attrInfos != NULL) {
27634 	int i;
27635 	xmlSchemaAttrInfoPtr attr;
27636 
27637 	/* Just a paranoid call to the cleanup. */
27638 	if (ctxt->nbAttrInfos != 0)
27639 	    xmlSchemaClearAttrInfos(ctxt);
27640 	for (i = 0; i < ctxt->sizeAttrInfos; i++) {
27641 	    attr = ctxt->attrInfos[i];
27642 	    xmlFree(attr);
27643 	}
27644 	xmlFree(ctxt->attrInfos);
27645     }
27646     if (ctxt->elemInfos != NULL) {
27647 	int i;
27648 	xmlSchemaNodeInfoPtr ei;
27649 
27650 	for (i = 0; i < ctxt->sizeElemInfos; i++) {
27651 	    ei = ctxt->elemInfos[i];
27652 	    if (ei == NULL)
27653 		break;
27654 	    xmlSchemaClearElemInfo(ctxt, ei);
27655 	    xmlFree(ei);
27656 	}
27657 	xmlFree(ctxt->elemInfos);
27658     }
27659     if (ctxt->nodeQNames != NULL)
27660 	xmlSchemaItemListFree(ctxt->nodeQNames);
27661     if (ctxt->dict != NULL)
27662 	xmlDictFree(ctxt->dict);
27663     if (ctxt->filename != NULL)
27664 	xmlFree(ctxt->filename);
27665     xmlFree(ctxt);
27666 }
27667 
27668 /**
27669  * xmlSchemaIsValid:
27670  * @ctxt: the schema validation context
27671  *
27672  * Check if any error was detected during validation.
27673  *
27674  * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
27675  *         of internal error.
27676  */
27677 int
xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)27678 xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
27679 {
27680     if (ctxt == NULL)
27681         return(-1);
27682     return(ctxt->err == 0);
27683 }
27684 
27685 /**
27686  * xmlSchemaSetValidErrors:
27687  * @ctxt:  a schema validation context
27688  * @err:  the error function
27689  * @warn: the warning function
27690  * @ctx: the functions context
27691  *
27692  * DEPRECATED: Use xmlSchemaSetValidStructuredErrors.
27693  *
27694  * Set the error and warning callback information
27695  */
27696 void
xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,xmlSchemaValidityErrorFunc err,xmlSchemaValidityWarningFunc warn,void * ctx)27697 xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
27698                         xmlSchemaValidityErrorFunc err,
27699                         xmlSchemaValidityWarningFunc warn, void *ctx)
27700 {
27701     if (ctxt == NULL)
27702         return;
27703     ctxt->error = err;
27704     ctxt->warning = warn;
27705     ctxt->errCtxt = ctx;
27706     if (ctxt->pctxt != NULL)
27707 	xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
27708 }
27709 
27710 /**
27711  * xmlSchemaSetValidStructuredErrors:
27712  * @ctxt:  a schema validation context
27713  * @serror:  the structured error function
27714  * @ctx: the functions context
27715  *
27716  * Set the structured error callback
27717  */
27718 void
xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,xmlStructuredErrorFunc serror,void * ctx)27719 xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
27720 				  xmlStructuredErrorFunc serror, void *ctx)
27721 {
27722     if (ctxt == NULL)
27723         return;
27724     ctxt->serror = serror;
27725     ctxt->error = NULL;
27726     ctxt->warning = NULL;
27727     ctxt->errCtxt = ctx;
27728     if (ctxt->pctxt != NULL)
27729 	xmlSchemaSetParserStructuredErrors(ctxt->pctxt, serror, ctx);
27730 }
27731 
27732 /**
27733  * xmlSchemaGetValidErrors:
27734  * @ctxt: a XML-Schema validation context
27735  * @err: the error function result
27736  * @warn: the warning function result
27737  * @ctx: the functions context result
27738  *
27739  * Get the error and warning callback information
27740  *
27741  * Returns -1 in case of error and 0 otherwise
27742  */
27743 int
xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,xmlSchemaValidityErrorFunc * err,xmlSchemaValidityWarningFunc * warn,void ** ctx)27744 xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
27745 			xmlSchemaValidityErrorFunc * err,
27746 			xmlSchemaValidityWarningFunc * warn, void **ctx)
27747 {
27748 	if (ctxt == NULL)
27749 		return (-1);
27750 	if (err != NULL)
27751 		*err = ctxt->error;
27752 	if (warn != NULL)
27753 		*warn = ctxt->warning;
27754 	if (ctx != NULL)
27755 		*ctx = ctxt->errCtxt;
27756 	return (0);
27757 }
27758 
27759 
27760 /**
27761  * xmlSchemaSetValidOptions:
27762  * @ctxt:	a schema validation context
27763  * @options: a combination of xmlSchemaValidOption
27764  *
27765  * Sets the options to be used during the validation.
27766  *
27767  * Returns 0 in case of success, -1 in case of an
27768  * API error.
27769  */
27770 int
xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,int options)27771 xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
27772 			 int options)
27773 
27774 {
27775     int i;
27776 
27777     if (ctxt == NULL)
27778 	return (-1);
27779     /*
27780     * WARNING: Change the start value if adding to the
27781     * xmlSchemaValidOption.
27782     * TODO: Is there an other, more easy to maintain,
27783     * way?
27784     */
27785     for (i = 1; i < (int) sizeof(int) * 8; i++) {
27786         if (options & 1<<i)
27787 	    return (-1);
27788     }
27789     ctxt->options = options;
27790     return (0);
27791 }
27792 
27793 /**
27794  * xmlSchemaValidCtxtGetOptions:
27795  * @ctxt: a schema validation context
27796  *
27797  * Get the validation context options.
27798  *
27799  * Returns the option combination or -1 on error.
27800  */
27801 int
xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)27802 xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
27803 
27804 {
27805     if (ctxt == NULL)
27806 	return (-1);
27807     else
27808 	return (ctxt->options);
27809 }
27810 
27811 static int
xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)27812 xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
27813 {
27814     xmlAttrPtr attr;
27815     int ret = 0;
27816     xmlSchemaNodeInfoPtr ielem = NULL;
27817     xmlNodePtr node, valRoot;
27818     const xmlChar *nsName;
27819 
27820     /* DOC VAL TODO: Move this to the start function. */
27821     if (vctxt->validationRoot != NULL)
27822         valRoot = vctxt->validationRoot;
27823     else
27824 	valRoot = xmlDocGetRootElement(vctxt->doc);
27825     if (valRoot == NULL) {
27826 	/* VAL TODO: Error code? */
27827 	VERROR(1, NULL, "The document has no document element");
27828 	return (1);
27829     }
27830     vctxt->depth = -1;
27831     vctxt->validationRoot = valRoot;
27832     node = valRoot;
27833     while (node != NULL) {
27834 	if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27835 	    goto next_sibling;
27836 	if (node->type == XML_ELEMENT_NODE) {
27837 
27838 	    /*
27839 	    * Init the node-info.
27840 	    */
27841 	    vctxt->depth++;
27842 	    if (xmlSchemaValidatorPushElem(vctxt) == -1)
27843 		goto internal_error;
27844 	    ielem = vctxt->inode;
27845 	    ielem->node = node;
27846 	    ielem->nodeLine = node->line;
27847 	    ielem->localName = node->name;
27848 	    if (node->ns != NULL)
27849 		ielem->nsName = node->ns->href;
27850 	    ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27851 	    /*
27852 	    * Register attributes.
27853 	    * DOC VAL TODO: We do not register namespace declaration
27854 	    * attributes yet.
27855 	    */
27856 	    vctxt->nbAttrInfos = 0;
27857 	    if (node->properties != NULL) {
27858 		attr = node->properties;
27859 		do {
27860                     xmlChar *content;
27861 
27862 		    if (attr->ns != NULL)
27863 			nsName = attr->ns->href;
27864 		    else
27865 			nsName = NULL;
27866                     content = xmlNodeListGetString(attr->doc,
27867                                                    attr->children, 1);
27868 		    ret = xmlSchemaValidatorPushAttribute(vctxt,
27869 			(xmlNodePtr) attr,
27870 			/*
27871 			* Note that we give it the line number of the
27872 			* parent element.
27873 			*/
27874 			ielem->nodeLine,
27875 			attr->name, nsName, 0,
27876 			content, 1);
27877 		    if (ret == -1) {
27878 			VERROR_INT("xmlSchemaDocWalk",
27879 			    "calling xmlSchemaValidatorPushAttribute()");
27880                         xmlFree(content);
27881 			goto internal_error;
27882 		    }
27883 		    attr = attr->next;
27884 		} while (attr);
27885 	    }
27886 	    /*
27887 	    * Validate the element.
27888 	    */
27889 	    ret = xmlSchemaValidateElem(vctxt);
27890 	    if (ret != 0) {
27891 		if (ret == -1) {
27892 		    VERROR_INT("xmlSchemaDocWalk",
27893 			"calling xmlSchemaValidateElem()");
27894 		    goto internal_error;
27895 		}
27896 		/*
27897 		* Don't stop validation; just skip the content
27898 		* of this element.
27899 		*/
27900 		goto leave_node;
27901 	    }
27902 	    if ((vctxt->skipDepth != -1) &&
27903 		(vctxt->depth >= vctxt->skipDepth))
27904 		goto leave_node;
27905 	} else if ((node->type == XML_TEXT_NODE) ||
27906 	    (node->type == XML_CDATA_SECTION_NODE)) {
27907 	    /*
27908 	    * Process character content.
27909 	    */
27910 	    if ((ielem != NULL) && (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY))
27911 		ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27912 	    ret = xmlSchemaVPushText(vctxt, node->type, node->content,
27913 		-1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
27914 	    if (ret < 0) {
27915 		VERROR_INT("xmlSchemaVDocWalk",
27916 		    "calling xmlSchemaVPushText()");
27917 		goto internal_error;
27918 	    }
27919 	    /*
27920 	    * DOC VAL TODO: Should we skip further validation of the
27921 	    * element content here?
27922 	    */
27923 	} else if ((node->type == XML_ENTITY_NODE) ||
27924 	    (node->type == XML_ENTITY_REF_NODE)) {
27925 	    /*
27926 	    * DOC VAL TODO: What to do with entities?
27927 	    */
27928 	    VERROR_INT("xmlSchemaVDocWalk",
27929 		"there is at least one entity reference in the node-tree "
27930 		"currently being validated. Processing of entities with "
27931 		"this XML Schema processor is not supported (yet). Please "
27932 		"substitute entities before validation.");
27933 	    goto internal_error;
27934 	} else {
27935 	    goto leave_node;
27936 	    /*
27937 	    * DOC VAL TODO: XInclude nodes, etc.
27938 	    */
27939 	}
27940 	/*
27941 	* Walk the doc.
27942 	*/
27943 	if (node->children != NULL) {
27944 	    node = node->children;
27945 	    continue;
27946 	}
27947 leave_node:
27948 	if (node->type == XML_ELEMENT_NODE) {
27949 	    /*
27950 	    * Leaving the scope of an element.
27951 	    */
27952 	    if (node != vctxt->inode->node) {
27953 		VERROR_INT("xmlSchemaVDocWalk",
27954 		    "element position mismatch");
27955 		goto internal_error;
27956 	    }
27957 	    ret = xmlSchemaValidatorPopElem(vctxt);
27958 	    if (ret != 0) {
27959 		if (ret < 0) {
27960 		    VERROR_INT("xmlSchemaVDocWalk",
27961 			"calling xmlSchemaValidatorPopElem()");
27962 		    goto internal_error;
27963 		}
27964 	    }
27965 	    if (node == valRoot)
27966 		goto exit;
27967 	}
27968 next_sibling:
27969 	if (node->next != NULL)
27970 	    node = node->next;
27971 	else {
27972 	    node = node->parent;
27973 	    goto leave_node;
27974 	}
27975     }
27976 
27977 exit:
27978     return (ret);
27979 internal_error:
27980     return (-1);
27981 }
27982 
27983 static int
xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt)27984 xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
27985     /*
27986     * Some initialization.
27987     */
27988     vctxt->err = 0;
27989     vctxt->nberrors = 0;
27990     vctxt->depth = -1;
27991     vctxt->skipDepth = -1;
27992     vctxt->hasKeyrefs = 0;
27993 #ifdef ENABLE_IDC_NODE_TABLES_TEST
27994     vctxt->createIDCNodeTables = 1;
27995 #else
27996     vctxt->createIDCNodeTables = 0;
27997 #endif
27998     /*
27999     * Create a schema + parser if necessary.
28000     */
28001     if (vctxt->schema == NULL) {
28002 	xmlSchemaParserCtxtPtr pctxt;
28003 
28004 	vctxt->xsiAssemble = 1;
28005 	/*
28006 	* If not schema was given then we will create a schema
28007 	* dynamically using XSI schema locations.
28008 	*
28009 	* Create the schema parser context.
28010 	*/
28011 	if ((vctxt->pctxt == NULL) &&
28012 	   (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
28013 	   return (-1);
28014 	pctxt = vctxt->pctxt;
28015 	pctxt->xsiAssemble = 1;
28016 	/*
28017 	* Create the schema.
28018 	*/
28019 	vctxt->schema = xmlSchemaNewSchema(pctxt);
28020 	if (vctxt->schema == NULL)
28021 	    return (-1);
28022 	/*
28023 	* Create the schema construction context.
28024 	*/
28025 	pctxt->constructor = xmlSchemaConstructionCtxtCreate(pctxt->dict);
28026 	if (pctxt->constructor == NULL)
28027 	    return(-1);
28028 	pctxt->constructor->mainSchema = vctxt->schema;
28029 	/*
28030 	* Take ownership of the constructor to be able to free it.
28031 	*/
28032 	pctxt->ownsConstructor = 1;
28033     }
28034     /*
28035     * Augment the IDC definitions for the main schema and all imported ones
28036     * NOTE: main schema if the first in the imported list
28037     */
28038     xmlHashScan(vctxt->schema->schemasImports, xmlSchemaAugmentImportedIDC,
28039                 vctxt);
28040 
28041     return(0);
28042 }
28043 
28044 static void
xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt)28045 xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
28046     if (vctxt->xsiAssemble) {
28047 	if (vctxt->schema != NULL) {
28048 	    xmlSchemaFree(vctxt->schema);
28049 	    vctxt->schema = NULL;
28050 	}
28051     }
28052     xmlSchemaClearValidCtxt(vctxt);
28053 }
28054 
28055 static int
xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)28056 xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
28057 {
28058     int ret = 0;
28059 
28060     if (xmlSchemaPreRun(vctxt) < 0)
28061         return(-1);
28062 
28063     if (vctxt->doc != NULL) {
28064 	/*
28065 	 * Tree validation.
28066 	 */
28067 	ret = xmlSchemaVDocWalk(vctxt);
28068 #ifdef LIBXML_READER_ENABLED
28069     } else if (vctxt->reader != NULL) {
28070 	/*
28071 	 * XML Reader validation.
28072 	 */
28073 #ifdef XML_SCHEMA_READER_ENABLED
28074 	ret = xmlSchemaVReaderWalk(vctxt);
28075 #endif
28076 #endif
28077     } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
28078 	/*
28079 	 * SAX validation.
28080 	 */
28081 	ret = xmlParseDocument(vctxt->parserCtxt);
28082     } else {
28083 	VERROR_INT("xmlSchemaVStart",
28084 	    "no instance to validate");
28085 	ret = -1;
28086     }
28087 
28088     xmlSchemaPostRun(vctxt);
28089     if (ret == 0)
28090 	ret = vctxt->err;
28091     return (ret);
28092 }
28093 
28094 /**
28095  * xmlSchemaValidateOneElement:
28096  * @ctxt:  a schema validation context
28097  * @elem:  an element node
28098  *
28099  * Validate a branch of a tree, starting with the given @elem.
28100  *
28101  * Returns 0 if the element and its subtree is valid, a positive error
28102  * code number otherwise and -1 in case of an internal or API error.
28103  */
28104 int
xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt,xmlNodePtr elem)28105 xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
28106 {
28107     if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
28108 	return (-1);
28109 
28110     if (ctxt->schema == NULL)
28111 	return (-1);
28112 
28113     ctxt->doc = elem->doc;
28114     ctxt->node = elem;
28115     ctxt->validationRoot = elem;
28116     return(xmlSchemaVStart(ctxt));
28117 }
28118 
28119 /**
28120  * xmlSchemaValidateDoc:
28121  * @ctxt:  a schema validation context
28122  * @doc:  a parsed document tree
28123  *
28124  * Validate a document tree in memory.
28125  *
28126  * Returns 0 if the document is schemas valid, a positive error code
28127  *     number otherwise and -1 in case of internal or API error.
28128  */
28129 int
xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt,xmlDocPtr doc)28130 xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
28131 {
28132     if ((ctxt == NULL) || (doc == NULL))
28133         return (-1);
28134 
28135     ctxt->doc = doc;
28136     ctxt->node = xmlDocGetRootElement(doc);
28137     if (ctxt->node == NULL) {
28138         xmlSchemaCustomErr(ACTXT_CAST ctxt,
28139 	    XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
28140 	    (xmlNodePtr) doc, NULL,
28141 	    "The document has no document element", NULL, NULL);
28142         return (ctxt->err);
28143     }
28144     ctxt->validationRoot = ctxt->node;
28145     return (xmlSchemaVStart(ctxt));
28146 }
28147 
28148 
28149 /************************************************************************
28150  *									*
28151  *		Function and data for SAX streaming API			*
28152  *									*
28153  ************************************************************************/
28154 typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
28155 typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
28156 
28157 struct _xmlSchemaSplitSAXData {
28158     xmlSAXHandlerPtr      user_sax;
28159     void                 *user_data;
28160     xmlSchemaValidCtxtPtr ctxt;
28161     xmlSAXHandlerPtr      schemas_sax;
28162 };
28163 
28164 #define XML_SAX_PLUG_MAGIC 0xdc43ba21
28165 
28166 struct _xmlSchemaSAXPlug {
28167     unsigned int magic;
28168 
28169     /* the original callbacks information */
28170     xmlSAXHandlerPtr     *user_sax_ptr;
28171     xmlSAXHandlerPtr      user_sax;
28172     void                **user_data_ptr;
28173     void                 *user_data;
28174 
28175     /* the block plugged back and validation information */
28176     xmlSAXHandler         schemas_sax;
28177     xmlSchemaValidCtxtPtr ctxt;
28178 };
28179 
28180 /* All those functions just bounces to the user provided SAX handlers */
28181 static void
internalSubsetSplit(void * ctx,const xmlChar * name,const xmlChar * ExternalID,const xmlChar * SystemID)28182 internalSubsetSplit(void *ctx, const xmlChar *name,
28183 	       const xmlChar *ExternalID, const xmlChar *SystemID)
28184 {
28185     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28186     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28187         (ctxt->user_sax->internalSubset != NULL))
28188 	ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
28189 	                               SystemID);
28190 }
28191 
28192 static int
isStandaloneSplit(void * ctx)28193 isStandaloneSplit(void *ctx)
28194 {
28195     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28196     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28197         (ctxt->user_sax->isStandalone != NULL))
28198 	return(ctxt->user_sax->isStandalone(ctxt->user_data));
28199     return(0);
28200 }
28201 
28202 static int
hasInternalSubsetSplit(void * ctx)28203 hasInternalSubsetSplit(void *ctx)
28204 {
28205     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28206     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28207         (ctxt->user_sax->hasInternalSubset != NULL))
28208 	return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
28209     return(0);
28210 }
28211 
28212 static int
hasExternalSubsetSplit(void * ctx)28213 hasExternalSubsetSplit(void *ctx)
28214 {
28215     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28216     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28217         (ctxt->user_sax->hasExternalSubset != NULL))
28218 	return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
28219     return(0);
28220 }
28221 
28222 static void
externalSubsetSplit(void * ctx,const xmlChar * name,const xmlChar * ExternalID,const xmlChar * SystemID)28223 externalSubsetSplit(void *ctx, const xmlChar *name,
28224 	       const xmlChar *ExternalID, const xmlChar *SystemID)
28225 {
28226     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28227     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28228         (ctxt->user_sax->externalSubset != NULL))
28229 	ctxt->user_sax->externalSubset(ctxt->user_data, name, ExternalID,
28230 	                               SystemID);
28231 }
28232 
28233 static xmlParserInputPtr
resolveEntitySplit(void * ctx,const xmlChar * publicId,const xmlChar * systemId)28234 resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
28235 {
28236     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28237     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28238         (ctxt->user_sax->resolveEntity != NULL))
28239 	return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
28240 	                                     systemId));
28241     return(NULL);
28242 }
28243 
28244 static xmlEntityPtr
getEntitySplit(void * ctx,const xmlChar * name)28245 getEntitySplit(void *ctx, const xmlChar *name)
28246 {
28247     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28248     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28249         (ctxt->user_sax->getEntity != NULL))
28250 	return(ctxt->user_sax->getEntity(ctxt->user_data, name));
28251     return(NULL);
28252 }
28253 
28254 static xmlEntityPtr
getParameterEntitySplit(void * ctx,const xmlChar * name)28255 getParameterEntitySplit(void *ctx, const xmlChar *name)
28256 {
28257     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28258     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28259         (ctxt->user_sax->getParameterEntity != NULL))
28260 	return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
28261     return(NULL);
28262 }
28263 
28264 
28265 static void
entityDeclSplit(void * ctx,const xmlChar * name,int type,const xmlChar * publicId,const xmlChar * systemId,xmlChar * content)28266 entityDeclSplit(void *ctx, const xmlChar *name, int type,
28267           const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
28268 {
28269     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28270     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28271         (ctxt->user_sax->entityDecl != NULL))
28272 	ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
28273 	                           systemId, content);
28274 }
28275 
28276 static void
attributeDeclSplit(void * ctx,const xmlChar * elem,const xmlChar * name,int type,int def,const xmlChar * defaultValue,xmlEnumerationPtr tree)28277 attributeDeclSplit(void *ctx, const xmlChar * elem,
28278                    const xmlChar * name, int type, int def,
28279                    const xmlChar * defaultValue, xmlEnumerationPtr tree)
28280 {
28281     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28282     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28283         (ctxt->user_sax->attributeDecl != NULL)) {
28284 	ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
28285 	                              def, defaultValue, tree);
28286     } else {
28287 	xmlFreeEnumeration(tree);
28288     }
28289 }
28290 
28291 static void
elementDeclSplit(void * ctx,const xmlChar * name,int type,xmlElementContentPtr content)28292 elementDeclSplit(void *ctx, const xmlChar *name, int type,
28293 	    xmlElementContentPtr content)
28294 {
28295     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28296     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28297         (ctxt->user_sax->elementDecl != NULL))
28298 	ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
28299 }
28300 
28301 static void
notationDeclSplit(void * ctx,const xmlChar * name,const xmlChar * publicId,const xmlChar * systemId)28302 notationDeclSplit(void *ctx, const xmlChar *name,
28303 	     const xmlChar *publicId, const xmlChar *systemId)
28304 {
28305     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28306     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28307         (ctxt->user_sax->notationDecl != NULL))
28308 	ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
28309 	                             systemId);
28310 }
28311 
28312 static void
unparsedEntityDeclSplit(void * ctx,const xmlChar * name,const xmlChar * publicId,const xmlChar * systemId,const xmlChar * notationName)28313 unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
28314 		   const xmlChar *publicId, const xmlChar *systemId,
28315 		   const xmlChar *notationName)
28316 {
28317     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28318     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28319         (ctxt->user_sax->unparsedEntityDecl != NULL))
28320 	ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
28321 	                                   systemId, notationName);
28322 }
28323 
28324 static void
setDocumentLocatorSplit(void * ctx,xmlSAXLocatorPtr loc)28325 setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
28326 {
28327     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28328     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28329         (ctxt->user_sax->setDocumentLocator != NULL))
28330 	ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
28331 }
28332 
28333 static void
startDocumentSplit(void * ctx)28334 startDocumentSplit(void *ctx)
28335 {
28336     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28337     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28338         (ctxt->user_sax->startDocument != NULL))
28339 	ctxt->user_sax->startDocument(ctxt->user_data);
28340 }
28341 
28342 static void
endDocumentSplit(void * ctx)28343 endDocumentSplit(void *ctx)
28344 {
28345     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28346     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28347         (ctxt->user_sax->endDocument != NULL))
28348 	ctxt->user_sax->endDocument(ctxt->user_data);
28349 }
28350 
28351 static void
processingInstructionSplit(void * ctx,const xmlChar * target,const xmlChar * data)28352 processingInstructionSplit(void *ctx, const xmlChar *target,
28353                       const xmlChar *data)
28354 {
28355     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28356     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28357         (ctxt->user_sax->processingInstruction != NULL))
28358 	ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
28359 }
28360 
28361 static void
commentSplit(void * ctx,const xmlChar * value)28362 commentSplit(void *ctx, const xmlChar *value)
28363 {
28364     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28365     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28366         (ctxt->user_sax->comment != NULL))
28367 	ctxt->user_sax->comment(ctxt->user_data, value);
28368 }
28369 
28370 /*
28371  * Varargs error callbacks to the user application, harder ...
28372  */
28373 
28374 static void
warningSplit(void * ctx,const char * msg ATTRIBUTE_UNUSED,...)28375 warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28376     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28377     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28378         (ctxt->user_sax->warning != NULL)) {
28379 	/* TODO */
28380     }
28381 }
28382 static void
errorSplit(void * ctx,const char * msg ATTRIBUTE_UNUSED,...)28383 errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28384     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28385     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28386         (ctxt->user_sax->error != NULL)) {
28387 	/* TODO */
28388     }
28389 }
28390 static void
fatalErrorSplit(void * ctx,const char * msg ATTRIBUTE_UNUSED,...)28391 fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28392     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28393     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28394         (ctxt->user_sax->fatalError != NULL)) {
28395 	/* TODO */
28396     }
28397 }
28398 
28399 /*
28400  * Those are function where both the user handler and the schemas handler
28401  * need to be called.
28402  */
28403 static void
charactersSplit(void * ctx,const xmlChar * ch,int len)28404 charactersSplit(void *ctx, const xmlChar *ch, int len)
28405 {
28406     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28407     if (ctxt == NULL)
28408         return;
28409     if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
28410 	ctxt->user_sax->characters(ctxt->user_data, ch, len);
28411     if (ctxt->ctxt != NULL)
28412 	xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28413 }
28414 
28415 static void
ignorableWhitespaceSplit(void * ctx,const xmlChar * ch,int len)28416 ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
28417 {
28418     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28419     if (ctxt == NULL)
28420         return;
28421     if ((ctxt->user_sax != NULL) &&
28422         (ctxt->user_sax->ignorableWhitespace != NULL))
28423 	ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
28424     if (ctxt->ctxt != NULL)
28425 	xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28426 }
28427 
28428 static void
cdataBlockSplit(void * ctx,const xmlChar * value,int len)28429 cdataBlockSplit(void *ctx, const xmlChar *value, int len)
28430 {
28431     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28432     if (ctxt == NULL)
28433         return;
28434     if ((ctxt->user_sax != NULL) &&
28435         (ctxt->user_sax->cdataBlock != NULL))
28436 	ctxt->user_sax->cdataBlock(ctxt->user_data, value, len);
28437     if (ctxt->ctxt != NULL)
28438 	xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
28439 }
28440 
28441 static void
referenceSplit(void * ctx,const xmlChar * name)28442 referenceSplit(void *ctx, const xmlChar *name)
28443 {
28444     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28445     if (ctxt == NULL)
28446         return;
28447     if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28448         (ctxt->user_sax->reference != NULL))
28449 	ctxt->user_sax->reference(ctxt->user_data, name);
28450     if (ctxt->ctxt != NULL)
28451         xmlSchemaSAXHandleReference(ctxt->user_data, name);
28452 }
28453 
28454 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)28455 startElementNsSplit(void *ctx, const xmlChar * localname,
28456 		    const xmlChar * prefix, const xmlChar * URI,
28457 		    int nb_namespaces, const xmlChar ** namespaces,
28458 		    int nb_attributes, int nb_defaulted,
28459 		    const xmlChar ** attributes) {
28460     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28461     if (ctxt == NULL)
28462         return;
28463     if ((ctxt->user_sax != NULL) &&
28464         (ctxt->user_sax->startElementNs != NULL))
28465 	ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
28466 	                               URI, nb_namespaces, namespaces,
28467 				       nb_attributes, nb_defaulted,
28468 				       attributes);
28469     if (ctxt->ctxt != NULL)
28470 	xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
28471 	                                 URI, nb_namespaces, namespaces,
28472 					 nb_attributes, nb_defaulted,
28473 					 attributes);
28474 }
28475 
28476 static void
endElementNsSplit(void * ctx,const xmlChar * localname,const xmlChar * prefix,const xmlChar * URI)28477 endElementNsSplit(void *ctx, const xmlChar * localname,
28478 		    const xmlChar * prefix, const xmlChar * URI) {
28479     xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28480     if (ctxt == NULL)
28481         return;
28482     if ((ctxt->user_sax != NULL) &&
28483         (ctxt->user_sax->endElementNs != NULL))
28484 	ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
28485     if (ctxt->ctxt != NULL)
28486 	xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
28487 }
28488 
28489 /**
28490  * xmlSchemaSAXPlug:
28491  * @ctxt:  a schema validation context
28492  * @sax:  a pointer to the original xmlSAXHandlerPtr
28493  * @user_data:  a pointer to the original SAX user data pointer
28494  *
28495  * Plug a SAX based validation layer in a SAX parsing event flow.
28496  * The original @saxptr and @dataptr data are replaced by new pointers
28497  * but the calls to the original will be maintained.
28498  *
28499  * Returns a pointer to a data structure needed to unplug the validation layer
28500  *         or NULL in case of errors.
28501  */
28502 xmlSchemaSAXPlugPtr
xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,xmlSAXHandlerPtr * sax,void ** user_data)28503 xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
28504 		 xmlSAXHandlerPtr *sax, void **user_data)
28505 {
28506     xmlSchemaSAXPlugPtr ret;
28507     xmlSAXHandlerPtr old_sax;
28508 
28509     if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
28510         return(NULL);
28511 
28512     /*
28513      * We only allow to plug into SAX2 event streams
28514      */
28515     old_sax = *sax;
28516     if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
28517         return(NULL);
28518     if ((old_sax != NULL) &&
28519         (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
28520         ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
28521         return(NULL);
28522 
28523     /*
28524      * everything seems right allocate the local data needed for that layer
28525      */
28526     ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
28527     if (ret == NULL) {
28528         return(NULL);
28529     }
28530     memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
28531     ret->magic = XML_SAX_PLUG_MAGIC;
28532     ret->schemas_sax.initialized = XML_SAX2_MAGIC;
28533     ret->ctxt = ctxt;
28534     ret->user_sax_ptr = sax;
28535     ret->user_sax = old_sax;
28536     if (old_sax == NULL) {
28537         /*
28538 	 * go direct, no need for the split block and functions.
28539 	 */
28540 	ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
28541 	ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
28542 	/*
28543 	 * Note that we use the same text-function for both, to prevent
28544 	 * the parser from testing for ignorable whitespace.
28545 	 */
28546 	ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
28547 	ret->schemas_sax.characters = xmlSchemaSAXHandleText;
28548 
28549 	ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
28550 	ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
28551 
28552 	ret->user_data = ctxt;
28553 	*user_data = ctxt;
28554     } else {
28555        /*
28556         * for each callback unused by Schemas initialize it to the Split
28557 	* routine only if non NULL in the user block, this can speed up
28558 	* things at the SAX level.
28559 	*/
28560         if (old_sax->internalSubset != NULL)
28561             ret->schemas_sax.internalSubset = internalSubsetSplit;
28562         if (old_sax->isStandalone != NULL)
28563             ret->schemas_sax.isStandalone = isStandaloneSplit;
28564         if (old_sax->hasInternalSubset != NULL)
28565             ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
28566         if (old_sax->hasExternalSubset != NULL)
28567             ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
28568         if (old_sax->resolveEntity != NULL)
28569             ret->schemas_sax.resolveEntity = resolveEntitySplit;
28570         if (old_sax->getEntity != NULL)
28571             ret->schemas_sax.getEntity = getEntitySplit;
28572         if (old_sax->entityDecl != NULL)
28573             ret->schemas_sax.entityDecl = entityDeclSplit;
28574         if (old_sax->notationDecl != NULL)
28575             ret->schemas_sax.notationDecl = notationDeclSplit;
28576         if (old_sax->attributeDecl != NULL)
28577             ret->schemas_sax.attributeDecl = attributeDeclSplit;
28578         if (old_sax->elementDecl != NULL)
28579             ret->schemas_sax.elementDecl = elementDeclSplit;
28580         if (old_sax->unparsedEntityDecl != NULL)
28581             ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
28582         if (old_sax->setDocumentLocator != NULL)
28583             ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
28584         if (old_sax->startDocument != NULL)
28585             ret->schemas_sax.startDocument = startDocumentSplit;
28586         if (old_sax->endDocument != NULL)
28587             ret->schemas_sax.endDocument = endDocumentSplit;
28588         if (old_sax->processingInstruction != NULL)
28589             ret->schemas_sax.processingInstruction = processingInstructionSplit;
28590         if (old_sax->comment != NULL)
28591             ret->schemas_sax.comment = commentSplit;
28592         if (old_sax->warning != NULL)
28593             ret->schemas_sax.warning = warningSplit;
28594         if (old_sax->error != NULL)
28595             ret->schemas_sax.error = errorSplit;
28596         if (old_sax->fatalError != NULL)
28597             ret->schemas_sax.fatalError = fatalErrorSplit;
28598         if (old_sax->getParameterEntity != NULL)
28599             ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
28600         if (old_sax->externalSubset != NULL)
28601             ret->schemas_sax.externalSubset = externalSubsetSplit;
28602 
28603 	/*
28604 	 * the 6 schemas callback have to go to the splitter functions
28605 	 * Note that we use the same text-function for ignorableWhitespace
28606 	 * if possible, to prevent the parser from testing for ignorable
28607 	 * whitespace.
28608 	 */
28609         ret->schemas_sax.characters = charactersSplit;
28610 	if ((old_sax->ignorableWhitespace != NULL) &&
28611 	    (old_sax->ignorableWhitespace != old_sax->characters))
28612 	    ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
28613 	else
28614 	    ret->schemas_sax.ignorableWhitespace = charactersSplit;
28615         ret->schemas_sax.cdataBlock = cdataBlockSplit;
28616         ret->schemas_sax.reference = referenceSplit;
28617         ret->schemas_sax.startElementNs = startElementNsSplit;
28618         ret->schemas_sax.endElementNs = endElementNsSplit;
28619 
28620 	ret->user_data_ptr = user_data;
28621 	ret->user_data = *user_data;
28622 	*user_data = ret;
28623     }
28624 
28625     /*
28626      * plug the pointers back.
28627      */
28628     *sax = &(ret->schemas_sax);
28629     ctxt->sax = *sax;
28630     ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28631     xmlSchemaPreRun(ctxt);
28632     return(ret);
28633 }
28634 
28635 /**
28636  * xmlSchemaSAXUnplug:
28637  * @plug:  a data structure returned by xmlSchemaSAXPlug
28638  *
28639  * Unplug a SAX based validation layer in a SAX parsing event flow.
28640  * The original pointers used in the call are restored.
28641  *
28642  * Returns 0 in case of success and -1 in case of failure.
28643  */
28644 int
xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)28645 xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
28646 {
28647     xmlSAXHandlerPtr *sax;
28648     void **user_data;
28649 
28650     if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
28651         return(-1);
28652     plug->magic = 0;
28653 
28654     xmlSchemaPostRun(plug->ctxt);
28655     /* restore the data */
28656     sax = plug->user_sax_ptr;
28657     *sax = plug->user_sax;
28658     if (plug->user_sax != NULL) {
28659 	user_data = plug->user_data_ptr;
28660 	*user_data = plug->user_data;
28661     }
28662 
28663     /* free and return */
28664     xmlFree(plug);
28665     return(0);
28666 }
28667 
28668 /**
28669  * xmlSchemaValidateSetLocator:
28670  * @vctxt: a schema validation context
28671  * @f: the locator function pointer
28672  * @ctxt: the locator context
28673  *
28674  * Allows to set a locator function to the validation context,
28675  * which will be used to provide file and line information since
28676  * those are not provided as part of the SAX validation flow
28677  * Setting @f to NULL disable the locator.
28678  */
28679 
28680 void
xmlSchemaValidateSetLocator(xmlSchemaValidCtxtPtr vctxt,xmlSchemaValidityLocatorFunc f,void * ctxt)28681 xmlSchemaValidateSetLocator(xmlSchemaValidCtxtPtr vctxt,
28682                             xmlSchemaValidityLocatorFunc f,
28683 			    void *ctxt)
28684 {
28685     if (vctxt == NULL) return;
28686     vctxt->locFunc = f;
28687     vctxt->locCtxt = ctxt;
28688 }
28689 
28690 /**
28691  * xmlSchemaValidateStreamLocator:
28692  * @ctx: the xmlTextReaderPtr used
28693  * @file: returned file information
28694  * @line: returned line information
28695  *
28696  * Internal locator function for the readers
28697  *
28698  * Returns 0 in case the Schema validation could be (de)activated and
28699  *         -1 in case of error.
28700  */
28701 static int
xmlSchemaValidateStreamLocator(void * ctx,const char ** file,unsigned long * line)28702 xmlSchemaValidateStreamLocator(void *ctx, const char **file,
28703                                unsigned long *line) {
28704     xmlParserCtxtPtr ctxt;
28705 
28706     if ((ctx == NULL) || ((file == NULL) && (line == NULL)))
28707         return(-1);
28708 
28709     if (file != NULL)
28710         *file = NULL;
28711     if (line != NULL)
28712         *line = 0;
28713 
28714     ctxt = (xmlParserCtxtPtr) ctx;
28715     if (ctxt->input != NULL) {
28716        if (file != NULL)
28717            *file = ctxt->input->filename;
28718        if (line != NULL)
28719            *line = ctxt->input->line;
28720        return(0);
28721     }
28722     return(-1);
28723 }
28724 
28725 /**
28726  * xmlSchemaValidateStreamInternal:
28727  * @ctxt:  a schema validation context
28728  * @pctxt:  a parser context
28729  *
28730  * Returns 0 if the document is schemas valid, a positive error code
28731  *     number otherwise and -1 in case of internal or API error.
28732  */
28733 static int
xmlSchemaValidateStreamInternal(xmlSchemaValidCtxtPtr ctxt,xmlParserCtxtPtr pctxt)28734 xmlSchemaValidateStreamInternal(xmlSchemaValidCtxtPtr ctxt,
28735                                  xmlParserCtxtPtr pctxt) {
28736     xmlSchemaSAXPlugPtr plug = NULL;
28737     int ret;
28738 
28739     pctxt->linenumbers = 1;
28740     xmlSchemaValidateSetLocator(ctxt, xmlSchemaValidateStreamLocator, pctxt);
28741 
28742     ctxt->parserCtxt = pctxt;
28743     ctxt->input = pctxt->input->buf;
28744 
28745     /*
28746      * Plug the validation and launch the parsing
28747      */
28748     plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
28749     if (plug == NULL) {
28750         ret = -1;
28751 	goto done;
28752     }
28753     ctxt->input = pctxt->input->buf;
28754     ctxt->sax = pctxt->sax;
28755     ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28756     ret = xmlSchemaVStart(ctxt);
28757 
28758     if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
28759 	ret = ctxt->parserCtxt->errNo;
28760 	if (ret == 0)
28761 	    ret = 1;
28762     }
28763 
28764 done:
28765     ctxt->parserCtxt = NULL;
28766     ctxt->sax = NULL;
28767     ctxt->input = NULL;
28768     if (plug != NULL) {
28769         xmlSchemaSAXUnplug(plug);
28770     }
28771     return (ret);
28772 }
28773 
28774 /**
28775  * xmlSchemaValidateStream:
28776  * @ctxt:  a schema validation context
28777  * @input:  the input to use for reading the data
28778  * @enc:  an optional encoding information
28779  * @sax:  a SAX handler for the resulting events
28780  * @user_data:  the context to provide to the SAX handler.
28781  *
28782  * Validate an input based on a flow of SAX event from the parser
28783  * and forward the events to the @sax handler with the provided @user_data
28784  * the user provided @sax handler must be a SAX2 one.
28785  *
28786  * Returns 0 if the document is schemas valid, a positive error code
28787  *     number otherwise and -1 in case of internal or API error.
28788  */
28789 int
xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,xmlParserInputBufferPtr input,xmlCharEncoding enc,const xmlSAXHandler * sax,void * user_data)28790 xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
28791                         xmlParserInputBufferPtr input, xmlCharEncoding enc,
28792                         const xmlSAXHandler *sax, void *user_data)
28793 {
28794     xmlParserCtxtPtr pctxt = NULL;
28795     xmlParserInputPtr inputStream = NULL;
28796     int ret;
28797 
28798     if ((ctxt == NULL) || (input == NULL))
28799         return (-1);
28800 
28801     /*
28802      * prepare the parser
28803      */
28804     if (sax != NULL) {
28805         pctxt = xmlNewSAXParserCtxt(sax, user_data);
28806         if (pctxt == NULL)
28807             return (-1);
28808     } else {
28809         pctxt = xmlNewParserCtxt();
28810         if (pctxt == NULL)
28811             return (-1);
28812         /* We really want pctxt->sax to be NULL here. */
28813         xmlFree(pctxt->sax);
28814         pctxt->sax = NULL;
28815     }
28816 #if 0
28817     if (options)
28818         xmlCtxtUseOptions(pctxt, options);
28819 #endif
28820 
28821     inputStream = xmlNewIOInputStream(pctxt, input, enc);;
28822     if (inputStream == NULL) {
28823         ret = -1;
28824 	goto done;
28825     }
28826     if (xmlCtxtPushInput(pctxt, inputStream) < 0) {
28827         xmlFreeInputStream(inputStream);
28828         ret = -1;
28829         goto done;
28830     }
28831 
28832     ctxt->enc = enc;
28833 
28834     ret = xmlSchemaValidateStreamInternal(ctxt, pctxt);
28835 
28836 done:
28837     /* cleanup */
28838     if (pctxt != NULL) {
28839 	xmlFreeParserCtxt(pctxt);
28840     }
28841     return (ret);
28842 }
28843 
28844 /**
28845  * xmlSchemaValidateFile:
28846  * @ctxt: a schema validation context
28847  * @filename: the URI of the instance
28848  * @options: a future set of options, currently unused
28849  *
28850  * Do a schemas validation of the given resource, it will use the
28851  * SAX streamable validation internally.
28852  *
28853  * Returns 0 if the document is valid, a positive error code
28854  *     number otherwise and -1 in case of an internal or API error.
28855  */
28856 int
xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,const char * filename,int options ATTRIBUTE_UNUSED)28857 xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
28858                       const char * filename,
28859 		      int options ATTRIBUTE_UNUSED)
28860 {
28861     int ret;
28862     xmlParserCtxtPtr pctxt = NULL;
28863 
28864     if ((ctxt == NULL) || (filename == NULL))
28865         return (-1);
28866 
28867     pctxt = xmlCreateURLParserCtxt(filename, 0);
28868     if (pctxt == NULL)
28869 	return (-1);
28870     /* We really want pctxt->sax to be NULL here. */
28871     xmlFree(pctxt->sax);
28872     pctxt->sax = NULL;
28873     ret = xmlSchemaValidateStreamInternal(ctxt, pctxt);
28874     xmlFreeParserCtxt(pctxt);
28875     return (ret);
28876 }
28877 
28878 /**
28879  * xmlSchemaValidCtxtGetParserCtxt:
28880  * @ctxt: a schema validation context
28881  *
28882  * allow access to the parser context of the schema validation context
28883  *
28884  * Returns the parser context of the schema validation context or NULL
28885  *         in case of error.
28886  */
28887 xmlParserCtxtPtr
xmlSchemaValidCtxtGetParserCtxt(xmlSchemaValidCtxtPtr ctxt)28888 xmlSchemaValidCtxtGetParserCtxt(xmlSchemaValidCtxtPtr ctxt)
28889 {
28890     if (ctxt == NULL)
28891         return(NULL);
28892     return (ctxt->parserCtxt);
28893 }
28894 
28895 #endif /* LIBXML_SCHEMAS_ENABLED */
28896